Merge branch 'dev' of bitbucket.org:jubilian/nhance into dev

This commit is contained in:
sanjeev.p 2026-04-20 16:46:34 +05:30
commit 7ad48bb0dc
15 changed files with 767 additions and 26 deletions

View File

@ -560,6 +560,8 @@ $routes->cli('cli/send_mail_cli', 'MasterController::testGmailAPIViaCLI');
$routes->cli('cli/sendZeptoMail', 'MasterController::testZeptoSMTP'); $routes->cli('cli/sendZeptoMail', 'MasterController::testZeptoSMTP');
$routes->cli('cli/check_bounce_mail_cli', 'MasterController::testCheckBounceMails'); $routes->cli('cli/check_bounce_mail_cli', 'MasterController::testCheckBounceMails');
$routes->cli('cli/app_check_list', 'MasterController::appCheckList'); $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/new_gdrive_token', 'GoogleDriveController::generateNewGoogleDriveAccessToken');
$routes->cli('cli/list-sheet-folder-files', 'GoogleSheetController::listFolderSheetFilesCli'); $routes->cli('cli/list-sheet-folder-files', 'GoogleSheetController::listFolderSheetFilesCli');
$routes->cli('cli/list-sheet-folder-files/(:any)', 'GoogleSheetController::listFolderSheetFilesCli/$1'); $routes->cli('cli/list-sheet-folder-files/(:any)', 'GoogleSheetController::listFolderSheetFilesCli/$1');

View File

@ -446,6 +446,9 @@ class ApiServiceController extends BaseController
if ($tpaID == $this->medi_assist_primary_key) { // MediAssist if ($tpaID == $this->medi_assist_primary_key) { // MediAssist
$mediAssistController = new MediAssistApiController(); $mediAssistController = new MediAssistApiController();
return $mediAssistController->IRSubmission($claimId); return $mediAssistController->IRSubmission($claimId);
}else if ($tpaID == $this->vidal_primary_key) { // Vidal
$vidalApiController = new VidalApiController();
return $vidalApiController->IRSubmission($claimId);
}else{ }else{
log_message('error', "This ticket id ( {$claimId} ) TPA has no API service enabled. TPA ID : {$tpaID}"); log_message('error', "This ticket id ( {$claimId} ) TPA has no API service enabled. TPA ID : {$tpaID}");
} }

View File

@ -2409,13 +2409,16 @@ class EmployeeRestController extends AdminController
$client_id = $this->request->getGet('client_id') ?? null; $client_id = $this->request->getGet('client_id') ?? null;
$data['claim_status'] = $this->claimStatusModel $data['claim_status'] = $this->claimStatusModel
->select('id,ticket_type, display_name as claim_status') ->select('id, ticket_type, display_name as claim_status')
->where('is_active', 1) ->where('is_active', 1)
->where('display_name IS NOT NULL OR display_name <> ""') ->groupStart()
->whereIn('claim_status_id',[1,2,3,4]) ->where('display_name IS NOT NULL')
->groupBy('display_name') ->orWhere('display_name <>', '')
->findAll(); ->groupEnd()
->whereIn('ticket_type', [1,2,3,4])
->groupBy('display_name')
->findAll();
if (!empty($client_id)) { if (!empty($client_id)) {

View File

@ -85,6 +85,8 @@ class FhplApiController extends BaseController
cp.policy_no as policyNo, cp.policy_no as policyNo,
e.emp_code as memberId, e.emp_code as memberId,
tn.note as disease, tn.note as disease,
cf.id as fileId,
cf.url as filePath,
cf.url as filePath cf.url as filePath
') ')
->join('employees e', 'e.id = tm.emp_id', 'left') ->join('employees e', 'e.id = tm.emp_id', 'left')
@ -102,6 +104,7 @@ class FhplApiController extends BaseController
} }
// Build absolute file path // Build absolute file path
$file_id = $data['fileId'] ?? null;
$filename = basename($data['filePath']); $filename = basename($data['filePath']);
$pdfPath = WRITEPATH . 'uploads/claim_files/' . $filename; $pdfPath = WRITEPATH . 'uploads/claim_files/' . $filename;
@ -182,6 +185,18 @@ class FhplApiController extends BaseController
'tpa_claim_push_reference_no' => $fhplClaimNo, 'tpa_claim_push_reference_no' => $fhplClaimNo,
'updated_at' => date('Y-m-d H:i:s') '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); log_message('error', 'FHPL - Claim Push SUCCESS | claimId: '.$claimId.' | claimNO: '.$fhplClaimNo);
return ['status' => true, 'message' => 'Claim Push SUCCESS', 'response' => $response]; return ['status' => true, 'message' => 'Claim Push SUCCESS', 'response' => $response];

View File

@ -105,6 +105,7 @@ class HealthIndiaApiController extends BaseController
cp.policy_no as policyNumber, cp.policy_no as policyNumber,
e.emp_code as employeeCode, e.emp_code as employeeCode,
tn.note as disease, tn.note as disease,
cf.id as fileId,
cf.url as filePath, cf.url as filePath,
tm.claim_type as claimType, tm.claim_type as claimType,
tm.claim_type as benefitType tm.claim_type as benefitType
@ -130,6 +131,7 @@ class HealthIndiaApiController extends BaseController
} }
// Build absolute file path // Build absolute file path
$file_id = $data['fileId'] ?? null;
$filename = basename($data['filePath']); $filename = basename($data['filePath']);
$pdfPath = WRITEPATH . 'uploads/claim_files/' . $filename; $pdfPath = WRITEPATH . 'uploads/claim_files/' . $filename;
@ -231,6 +233,18 @@ class HealthIndiaApiController extends BaseController
'updated_at' => date('Y-m-d H:i:s') '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); log_message('error', 'HEALTH_INDIA - Claim Push SUCCESS | claimId: ' . $claimId . ' | CCN: ' . $ccn . ' | CCN_EXT: ' . $ccnExt);
return ['status' => true, 'message' => 'Claim Push SUCCESS', 'response' => $response]; return ['status' => true, 'message' => 'Claim Push SUCCESS', 'response' => $response];
} else { } else {

View File

@ -42,8 +42,9 @@ class MediAssistApiController extends BaseController
'Password:'. getenv('MEDI_ASSIST_API_PASSWORD').'', 'Password:'. getenv('MEDI_ASSIST_API_PASSWORD').'',
]; ];
$file_id = null;
//Prepare body data //Prepare body data
// Fetch the data from DB // Fetch the data from DB
$data = $this->db->table('ticket_master tm') $data = $this->db->table('ticket_master tm')
->select(' ->select('
@ -59,6 +60,7 @@ class MediAssistApiController extends BaseController
tm.tpa_no as memberId, tm.tpa_no as memberId,
tn.note as disease, tn.note as disease,
tn.note as reasonForHospitalization, tn.note as reasonForHospitalization,
cf.id as fileId,
cf.url as fileName, cf.url as fileName,
cf.url as filePath cf.url as filePath
') ')
@ -83,6 +85,7 @@ class MediAssistApiController extends BaseController
if ($fileDir) { if ($fileDir) {
$downloadUrl = base_url('fileDownload?file_path=').$fileDir; $downloadUrl = base_url('fileDownload?file_path=').$fileDir;
$file_id = $data['fileId'] ?? null;
} else { } else {
$downloadUrl = ''; $downloadUrl = '';
} }
@ -152,10 +155,23 @@ class MediAssistApiController extends BaseController
log_message('error','MEDI_ASSIST - Claim Push SUCCESS | claimId: '.$claimId.' | claimReferenceNo: '.$claimRef); log_message('error','MEDI_ASSIST - Claim Push SUCCESS | claimId: '.$claimId.' | claimReferenceNo: '.$claimRef);
// Update claim reference number in ticket_master
$this->db->table('ticket_master') $this->db->table('ticket_master')
->where('id',$claimId) ->where('id',$claimId)
->update([ 'tpa_claim_push_reference_no' => $claimRef ]); ->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]; return ['status' => true, 'message' => 'Claim Push SUCCESS', 'response' => $response];
} else { } else {
@ -695,16 +711,19 @@ class MediAssistApiController extends BaseController
$fileData = $this->db->table('claim_files f') $fileData = $this->db->table('claim_files f')
->where('f.ticket_id', $claimId) ->where('f.ticket_id', $claimId)
->where('f.docs_for_ir', 1) ->where('f.docs_for_ir', 1)
->where('f.file_type', 2)
->where('f.is_file_sent_to_tpa', 0)
->get() ->get()
->getResultArray(); ->getResultArray();
$Attachments = []; $Attachments = [];
$tpaSentFileIds = [];
if (count($fileData)) { if (count($fileData)) {
foreach ($fileData as $file) { foreach ($fileData as $file) {
if (!empty($file['url'])) { if (!empty($file['url']) && $file['file_type'] == 2) {
$filename = basename($file['url']); $filename = basename($file['url']);
$fileDir = WRITEPATH . 'uploads/claim_files/' . $filename; $fileDir = WRITEPATH . 'uploads/claim_files/' . $filename;
@ -721,6 +740,9 @@ class MediAssistApiController extends BaseController
"AttachmentName" => $filename, "AttachmentName" => $filename,
"AttachmentPath" => $downloadUrl "AttachmentPath" => $downloadUrl
]; ];
$tpaSentFileIds[] = $file['id']; // Collect file IDs to update later
} else { } else {
log_message('error',"MEDI_ASSIST - IR Submission Missing File URL → file_id={$file['id']}"); 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']}"); 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 [ return [
'status' => true, 'status' => true,
'message' => 'IR Submitted successfully', 'message' => 'IR Submitted successfully',

View File

@ -2326,6 +2326,10 @@ class RestAuthenticationController extends AdminController
public function logout() public function logout()
{ {
return $this->respond([
'status' => true,
'message' => 'Logged out successfully'
], 200);
$authHeader = $this->request->getHeaderLine('Authorization'); $authHeader = $this->request->getHeaderLine('Authorization');
if (!$authHeader) { if (!$authHeader) {
@ -2373,4 +2377,52 @@ class RestAuthenticationController extends AdminController
], 200); ], 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;
}
} }

View File

@ -539,6 +539,7 @@ class TicketController extends BaseController
'tm.emp_personal_mail', 'tm.emp_personal_mail',
'tm.mode_of_intimation', 'tm.mode_of_intimation',
'tm.claim_type', 'tm.claim_type',
'tm.tpa_claim_type',
'tm.hospital_name', 'tm.hospital_name',
'tm.doa', 'tm.doa',
'tm.dod', 'tm.dod',
@ -673,6 +674,7 @@ class TicketController extends BaseController
'tm.emp_personal_mail', 'tm.emp_personal_mail',
'tm.mode_of_intimation', 'tm.mode_of_intimation',
'tm.claim_type', 'tm.claim_type',
'tm.tpa_claim_type',
'tm.hospital_name', 'tm.hospital_name',
'tm.doa', 'tm.doa',
'tm.dod', 'tm.dod',
@ -1140,6 +1142,8 @@ class TicketController extends BaseController
public function createTicket() public function createTicket()
{ {
$request_data = $this->request->getPost(); $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'); $selected_ticket_type = $this->request->getPost('ticket_type_id');
// 1. Initialize an empty rules array // 1. Initialize an empty rules array
@ -1455,6 +1459,84 @@ class TicketController extends BaseController
$request_data = $this->request->getPost(); $request_data = $this->request->getPost();
$sanitized_data = sanitizeInputArrayAdvanced($request_data); $sanitized_data = sanitizeInputArrayAdvanced($request_data);
$ticket_data = $this->formatDateForClaim($sanitized_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, ); // $ticket_data = $this->getLastMatchedStatus($ticket_data, );
// print_rr($ticket_data); die; // print_rr($ticket_data); die;
@ -1499,6 +1581,37 @@ class TicketController extends BaseController
$ticket_data['claim_created_by'] = "CRM"; $ticket_data['claim_created_by'] = "CRM";
$return_value = $this->ticketMasterModel->insert($ticket_data); $return_value = $this->ticketMasterModel->insert($ticket_data);
if ($return_value) { 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 //mail trigger part
$this->putHistoryAfterInsert($ticket_data, $return_value); $this->putHistoryAfterInsert($ticket_data, $return_value);
$mail_responce = $this->sendAutoMailTrigger($return_value); $mail_responce = $this->sendAutoMailTrigger($return_value);
@ -1517,6 +1630,8 @@ class TicketController extends BaseController
{ {
$request_data = $this->request->getPost(); $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'); $selected_ticket_type = $this->request->getPost('ticket_type_id');
// 1. Initialize an empty rules array // 1. Initialize an empty rules array
@ -1832,6 +1947,85 @@ class TicketController extends BaseController
$sanitized_data = sanitizeInputArrayAdvanced($request_data); $sanitized_data = sanitizeInputArrayAdvanced($request_data);
$ticket_data = $this->formatDateForClaim($sanitized_data); $ticket_data = $this->formatDateForClaim($sanitized_data);
$ticket_id = $this->request->getPost('ticket_master_id'); $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(); $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['claim_status_id'] = $this->getLastMatchedStatus($ticket_data, $old_ticket_data);
$ticket_data['last_updated_by'] = 'USER'; $ticket_data['last_updated_by'] = 'USER';
@ -1842,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)]); $this->myLogger->logme('error', "[UPDATE_CLAIM] New Ticket Data: {data}", ['data' => json_encode($ticket_data, JSON_PRETTY_PRINT)]);
if ($ticket_data) { 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(); $return_value = $this->ticketMasterModel->where('id', $ticket_id)->set($ticket_data)->update();
if ($return_value) { if ($return_value) {
@ -3264,6 +3476,55 @@ class TicketController extends BaseController
return strpos($host, '.') !== false; 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() public function upload_url()
{ {
@ -3379,6 +3640,7 @@ class TicketController extends BaseController
} }
} }
//get the claim file list data against the ticket id
public function getUrlDataByTicketId() public function getUrlDataByTicketId()
{ {
$ticket_id = $this->request->getPost('ticket_id'); $ticket_id = $this->request->getPost('ticket_id');
@ -3401,6 +3663,7 @@ class TicketController extends BaseController
END AS url END AS url
") ")
->where('ticket_id', $ticket_id) ->where('ticket_id', $ticket_id)
->where('file_type !=', 3) // Assuming you want to fetch both URL and file uploads
->where('is_active', 1) ->where('is_active', 1)
->findAll(); ->findAll();

View File

@ -156,6 +156,7 @@ class VidalApiController extends BaseController
e.emp_code as memberId, e.emp_code as memberId,
tn.note as disease, tn.note as disease,
tn.note as reasonForHospitalization, tn.note as reasonForHospitalization,
cf.id as cfFileId,
cf.url as fileName, cf.url as fileName,
cf.url as filePath, cf.url as filePath,
pt.policy_type as typeOfClaim, pt.policy_type as typeOfClaim,
@ -195,6 +196,7 @@ class VidalApiController extends BaseController
} }
$fileId = $upload['fileId']; $fileId = $upload['fileId'];
$tpa_sent_file_id = $data['cfFileId'] ?? null;
// $url = 'https://devapigw.vidalhealthtpa.com/partner-integration/api/claims/submit'; // $url = 'https://devapigw.vidalhealthtpa.com/partner-integration/api/claims/submit';
$url = getenv('VIDAL_API_BASE_URL').'/claims/submit'; $url = getenv('VIDAL_API_BASE_URL').'/claims/submit';
$method = 'POST'; $method = 'POST';
@ -299,6 +301,18 @@ class VidalApiController extends BaseController
->where('id',$claimId) ->where('id',$claimId)
->update([ 'tpa_claim_push_reference_no' => $claimInwardNO , 'tpa_claim_id' => $claimNO , 'claim_number' => $claimNO ]); ->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']; return ['status' => true, 'message' => 'Claim Push SUCCESS'];
} else { } else {
@ -1664,6 +1678,8 @@ class VidalApiController extends BaseController
$fileData = $this->db->table('claim_files f') $fileData = $this->db->table('claim_files f')
->where('f.ticket_id', $claimId) ->where('f.ticket_id', $claimId)
->where('f.docs_for_ir', 1) ->where('f.docs_for_ir', 1)
->where('f.file_type', 2)
->where('f.is_file_sent_to_tpa', 0)
->get() ->get()
->getResultArray(); ->getResultArray();
@ -1678,6 +1694,7 @@ class VidalApiController extends BaseController
// 3. UPLOAD FILES TO VIDAL // 3. UPLOAD FILES TO VIDAL
$fileIdList = []; $fileIdList = [];
$tpaSentFileIds = [];
foreach ($fileData as $file) { foreach ($fileData as $file) {
@ -1701,6 +1718,7 @@ class VidalApiController extends BaseController
} }
$fileIdList[] = $upload['fileId']; // deeplink URL $fileIdList[] = $upload['fileId']; // deeplink URL
$tpaSentFileIds[] = $file['id']; // local file ID for updating
} }
if (empty($fileIdList)) { if (empty($fileIdList)) {
@ -1756,6 +1774,18 @@ class VidalApiController extends BaseController
log_message('error', "VIDAL - IR Submission SUCCESS → ClaimNO={$ticket['claimNO']}"); 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 [ return [
'status' => true, 'status' => true,
'message' => 'IR Submitted successfully', 'message' => 'IR Submitted successfully',

View File

@ -692,6 +692,7 @@ class VoloApiController extends BaseController
tm.claim_amount as requestedAmount, tm.claim_amount as requestedAmount,
tm.tpa_no as memberId, tm.tpa_no as memberId,
cp.policy_no as policyNo, cp.policy_no as policyNo,
cf.id as fileId,
cf.url as filePath cf.url as filePath
') ')
->join('client_policy cp', 'tm.client_policy_id = cp.id', 'left') ->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']; return ['status' => false, 'message' => 'Claim Push FAILED | File Missing'];
} }
$file_id = $data['fileId'] ?? null;
$filename = basename($data['filePath']); $filename = basename($data['filePath']);
$pdfPath = WRITEPATH . 'uploads/claim_files/' . $filename; $pdfPath = WRITEPATH . 'uploads/claim_files/' . $filename;
if (!is_readable($pdfPath)) { if (!is_readable($pdfPath)) {
@ -781,6 +783,18 @@ class VoloApiController extends BaseController
]); ]);
log_message('error', 'VOLO - Claim Push SUCCESS | claimId: ' . $claimId . ' | ref: ' . $ref); 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]; return ['status' => true, 'message' => 'Claim Push SUCCESS', 'response' => $response];
} }

View File

@ -24,6 +24,7 @@ class ClaimFilesModel extends Model
'file_name', 'file_name',
'mime_type', 'mime_type',
'docs_for_ir', 'docs_for_ir',
'is_file_sent_to_tpa',
]; ];
// Callbacks // Callbacks

View File

@ -465,15 +465,23 @@
let ticket_master_id = $('#ticket_master_id').val(); let ticket_master_id = $('#ticket_master_id').val();
console.log({ticket_master_id}); console.log({ticket_master_id});
if (!ticket_master_id) {
toastr.warning('Claim ID not found. Please ensure the form is loaded.', 'Warning');
return;
}
let requestData = { let requestData = {
claim_id: ticket_master_id, claim_id: ticket_master_id,
}; };
let url = '<?= base_url('ticket/getTpaClaimStatus') ?>'; let url = '<?= base_url('ticket/getTpaClaimStatus') ?>';
$('.loader').fadeIn();
$('.loader-mask').fadeIn();
// Send AJAX request // Send AJAX request
sendAjaxRequestForGlobal(url, 'GET', requestData, function(response) { sendAjaxRequestForGlobal(url, 'GET', requestData, function(response) {
$('.loader').fadeOut();
$('.loader-mask').delay(350).fadeOut('slow');
console.log('Data fetched successfully:', response); console.log('Data fetched successfully:', response);
@ -485,6 +493,8 @@
} }
}, function(xhr, status, error) { }, function(xhr, status, error) {
$('.loader').fadeOut();
$('.loader-mask').delay(350).fadeOut('slow');
console.error('Error fetching data:', error); console.error('Error fetching data:', error);
console.error(xhr.responseText); console.error(xhr.responseText);
toastr.error('An error occurred while saving docs.', 'Error'); toastr.error('An error occurred while saving docs.', 'Error');

View File

@ -429,10 +429,26 @@
value="<?= isset($ticket_data['approved_date']) ? $ticket_data['approved_date'] : '' ?>" name="approved_date"> value="<?= isset($ticket_data['approved_date']) ? $ticket_data['approved_date'] : '' ?>" name="approved_date">
</div> </div>
<div class="form-group col-md-6 approved" style="display: none;"> <div class="form-group col-md-3 approved" style="display: none;">
<label class="label-font-size" for="approved_letter">Approved Letter</label> <label class="label-font-size" for="approved_letter">Approved Letter URL</label>
<input type="text" class="form-control" id="approved_letter" placeholder="Enter Approved Letter" <input
value="<?= isset($ticket_data['approved_letter']) ? $ticket_data['approved_letter'] : '' ?>" name="approved_letter"> type="text"
class="form-control"
id="approved_letter"
placeholder="Enter Approved Letter URL"
value="<?= isset($ticket_data['approved_letter']) ? $ticket_data['approved_letter'] : '' ?>"
name="approved_letter">
</div>
<div class="form-group col-md-3 approved" style="display: none;">
<label class="label-font-size" for="approved_letter_file">Approved Letter PDF</label>
<input
type="file"
class="form-control"
id="approved_letter_file"
name="approved_letter_file"
accept=".pdf,application/pdf">
<small class="text-muted">Only PDF allowed.</small>
</div> </div>
<div class="form-group col-md-6 approved" style="display: none;"> <div class="form-group col-md-6 approved" style="display: none;">
@ -453,12 +469,23 @@
value="<?= isset($ticket_data['settled_date']) ? $ticket_data['settled_date'] : '' ?>" name="settled_date"> value="<?= isset($ticket_data['settled_date']) ? $ticket_data['settled_date'] : '' ?>" name="settled_date">
</div> </div>
<div class="form-group col-md-6 settled" style="display: none;"> <div class="form-group col-md-3 settled" style="display: none;">
<label class="label-font-size" for="settle_letter">Settle Letter</label> <label class="label-font-size" for="settle_letter">Settle Letter URL</label>
<input type="text" class="form-control" id="settle_letter" placeholder="Enter Settle Letter" <input type="text" class="form-control" id="settle_letter" placeholder="Enter Settle Letter URL"
value="<?= isset($ticket_data['settle_letter']) ? $ticket_data['settle_letter'] : '' ?>" name="settle_letter"> value="<?= isset($ticket_data['settle_letter']) ? $ticket_data['settle_letter'] : '' ?>" name="settle_letter">
</div> </div>
<div class="form-group col-md-3 settled" style="display: none;">
<label class="label-font-size" for="settle_letter_file">Settle Letter PDF</label>
<input
type="file"
class="form-control"
id="settle_letter_file"
name="settle_letter_file"
accept=".pdf,application/pdf">
<small class="text-muted">Only PDF allowed.</small>
</div>
<div class="form-group col-md-3 payment" style="display: none;"> <div class="form-group col-md-3 payment" style="display: none;">
<label class="label-font-size" for="pay_initiate_date">Payment Initiate Date</label> <label class="label-font-size" for="pay_initiate_date">Payment Initiate Date</label>
<input type="text" class="form-control datepicker" id="pay_initiate_date" placeholder="Select Payment Initiate Date" <input type="text" class="form-control datepicker" id="pay_initiate_date" placeholder="Select Payment Initiate Date"
@ -619,6 +646,8 @@
console.log("extraFields", extraFields); console.log("extraFields", extraFields);
claimStatusFieldChanges(extraFields); claimStatusFieldChanges(extraFields);
handleTPARequired(tpa_id_for_hid_filed); handleTPARequired(tpa_id_for_hid_filed);
// syncApprovedLetterInputs();
// syncSettleLetterInputs();
}) })
// function updateClaimStatusDisplay(value) { // function updateClaimStatusDisplay(value) {
@ -723,6 +752,8 @@
$field.prop('required', false); $field.prop('required', false);
var $parentDiv = $field.closest("div"); var $parentDiv = $field.closest("div");
$parentDiv.find("label[for='approved_description'] .text-danger").remove(); $parentDiv.find("label[for='approved_description'] .text-danger").remove();
syncApprovedLetterInputs();
syncSettleLetterInputs();
} }
$('#claim_status_id').on('change', function() { $('#claim_status_id').on('change', function() {
@ -774,6 +805,95 @@
}); });
function validateApprovedLetterPdf(fileInput) {
const file = fileInput.files && fileInput.files[0] ? fileInput.files[0] : null;
if (!file) {
return true;
}
const fileName = (file.name || '').toLowerCase();
const isPdfByName = fileName.endsWith('.pdf');
const mimeType = (file.type || '').toLowerCase();
const isPdfByType = mimeType === '' || mimeType === 'application/pdf' || mimeType === 'application/x-pdf';
const fieldLabel = fileInput.id === 'settle_letter_file' ? 'Settle Letter' : 'Approved Letter';
if (!isPdfByName || !isPdfByType) {
fileInput.value = '';
toastr.warning('Only PDF files are allowed for ' + fieldLabel + '.', 'Warning');
return false;
}
return true;
}
function syncApprovedLetterInputs() {
const $urlInput = $('#approved_letter');
const $fileInput = $('#approved_letter_file');
if (!$urlInput.length || !$fileInput.length) {
return;
}
const hasUrl = $.trim($urlInput.val()) !== '';
const hasFile = $fileInput[0].files && $fileInput[0].files.length > 0;
const isApprovedSectionVisible = $urlInput.closest('.approved').is(':visible');
$fileInput.prop('disabled', hasUrl);
$urlInput.prop('disabled', hasFile);
// Keep the file optional; URL remains conditionally required for approved state unless file is present.
$fileInput.prop('required', false);
$urlInput.prop('required', isApprovedSectionVisible && !hasFile);
}
function syncSettleLetterInputs() {
const $urlInput = $('#settle_letter');
const $fileInput = $('#settle_letter_file');
if (!$urlInput.length || !$fileInput.length) {
return;
}
const hasUrl = $.trim($urlInput.val()) !== '';
const hasFile = $fileInput[0].files && $fileInput[0].files.length > 0;
const isSettledSectionVisible = $urlInput.closest('.settled').is(':visible');
$fileInput.prop('disabled', hasUrl);
$urlInput.prop('disabled', hasFile);
$fileInput.prop('required', false);
$urlInput.prop('required', isSettledSectionVisible && !hasFile);
}
function enforceLetterPairRules() {
syncApprovedLetterInputs();
syncSettleLetterInputs();
}
$('#approved_letter').on('input blur', function () {
enforceLetterPairRules();
});
$('#approved_letter_file').on('change', function () {
if (validateApprovedLetterPdf(this)) {
enforceLetterPairRules();
} else {
enforceLetterPairRules();
}
});
$('#settle_letter').on('input blur', function () {
enforceLetterPairRules();
});
$('#settle_letter_file').on('change', function () {
if (validateApprovedLetterPdf(this)) {
enforceLetterPairRules();
} else {
enforceLetterPairRules();
}
});
function claimStatusFieldChanges(fields) { function claimStatusFieldChanges(fields) {
fields.forEach(function(fieldId) { fields.forEach(function(fieldId) {
@ -789,6 +909,13 @@
if ($label.length && !$label.find(".text-danger").length) { if ($label.length && !$label.find(".text-danger").length) {
// $label.append(' <span class="text-danger">*</span>'); // $label.append(' <span class="text-danger">*</span>');
} }
// Keep paired PDF upload visibility in sync with URL field visibility.
if (fieldId === 'approved_letter') {
$('#approved_letter_file').closest('div').show();
} else if (fieldId === 'settle_letter') {
$('#settle_letter_file').closest('div').show();
}
} }
}); });
} }
@ -860,6 +987,9 @@
} }
}); });
// Re-apply URL/file pair rules after bulk required toggles.
enforceLetterPairRules();
} }
$(document).on("input", function(event) { $(document).on("input", function(event) {
@ -870,7 +1000,7 @@
console.log('targetId', targetId); console.log('targetId', targetId);
console.log('fields.includes(targetId)', fields.includes(targetId)); console.log('fields.includes(targetId)', fields.includes(targetId));
if (fields.includes(targetId)) { if (fields.includes(targetId) || targetId == "approved_letter_file" || targetId == "settle_letter_file") {
let $field = $("#" + targetId); let $field = $("#" + targetId);
console.log('$field id', $field); console.log('$field id', $field);
@ -904,9 +1034,14 @@
$field.prop('required', false); $field.prop('required', false);
var $parentDiv = $field.closest("div"); var $parentDiv = $field.closest("div");
$parentDiv.find("label[for='approved_description'] .text-danger").remove(); $parentDiv.find("label[for='approved_description'] .text-danger").remove();
enforceLetterPairRules();
}); });
$('#ticket_form_data').on('submit', function() {
enforceLetterPairRules();
});
// function addRequiredFieldSymbol(field_name) { // function addRequiredFieldSymbol(field_name) {
// // Find the field with the given name // // Find the field with the given name
// var $field = $(`[name="${field_name}"]`); // var $field = $(`[name="${field_name}"]`);

View File

@ -281,12 +281,23 @@
value="<?= isset($ticket_data['approved_date']) ? $ticket_data['approved_date'] : '' ?>" name="approved_date"> value="<?= isset($ticket_data['approved_date']) ? $ticket_data['approved_date'] : '' ?>" name="approved_date">
</div> </div>
<div class="form-group col-md-6 approved" style="display: none;"> <div class="form-group col-md-3 approved" style="display: none;">
<label class="label-font-size" for="approved_letter">Approved Letter</label> <label class="label-font-size" for="approved_letter">Approved Letter URL</label>
<input type="text" class="form-control" id="approved_letter" placeholder="Enter Approved Letter" <input type="text" class="form-control" id="approved_letter" placeholder="Enter Approved Letter URL"
value="<?= isset($ticket_data['approved_letter']) ? $ticket_data['approved_letter'] : '' ?>" name="approved_letter"> value="<?= isset($ticket_data['approved_letter']) ? $ticket_data['approved_letter'] : '' ?>" name="approved_letter">
</div> </div>
<div class="form-group col-md-3 approved" style="display: none;">
<label class="label-font-size" for="approved_letter_file">Approved Letter PDF</label>
<input
type="file"
class="form-control"
id="approved_letter_file"
name="approved_letter_file"
accept=".pdf,application/pdf">
<small class="text-muted">Only PDF allowed.</small>
</div>
<div class="form-group col-md-6 approved" style="display: none;"> <div class="form-group col-md-6 approved" style="display: none;">
<label class="label-font-size" for="approved_description">Approved Description</label> <label class="label-font-size" for="approved_description">Approved Description</label>
<input type="text" class="form-control" id="approved_description" placeholder="Enter Approved Description" <input type="text" class="form-control" id="approved_description" placeholder="Enter Approved Description"
@ -305,12 +316,23 @@
value="<?= isset($ticket_data['settled_date']) ? $ticket_data['settled_date'] : '' ?>" name="settled_date"> value="<?= isset($ticket_data['settled_date']) ? $ticket_data['settled_date'] : '' ?>" name="settled_date">
</div> </div>
<div class="form-group col-md-6 settled" style="display: none;"> <div class="form-group col-md-3 settled" style="display: none;">
<label class="label-font-size" for="settle_letter">Settle Letter</label> <label class="label-font-size" for="settle_letter">Settle Letter URL</label>
<input type="text" class="form-control" id="settle_letter" placeholder="Enter Settle Letter" <input type="text" class="form-control" id="settle_letter" placeholder="Enter Settle Letter URL"
value="<?= isset($ticket_data['settle_letter']) ? $ticket_data['settle_letter'] : '' ?>" name="settle_letter"> value="<?= isset($ticket_data['settle_letter']) ? $ticket_data['settle_letter'] : '' ?>" name="settle_letter">
</div> </div>
<div class="form-group col-md-3 settled" style="display: none;">
<label class="label-font-size" for="settle_letter_file">Settle Letter PDF</label>
<input
type="file"
class="form-control"
id="settle_letter_file"
name="settle_letter_file"
accept=".pdf,application/pdf">
<small class="text-muted">Only PDF allowed.</small>
</div>
<div class="form-group col-md-3 canceled" style="display: none;"> <div class="form-group col-md-3 canceled" style="display: none;">
<label class="label-font-size" for="cancel_remark">Cancel Remark</label> <label class="label-font-size" for="cancel_remark">Cancel Remark</label>
<textarea class="form-control" id="cancel_remark" rows="1" placeholder="Enter Cancel Remark" name="cancel_remark"><?= isset($ticket_data['cancel_remark']) ? $ticket_data['cancel_remark'] : '' ?></textarea> <textarea class="form-control" id="cancel_remark" rows="1" placeholder="Enter Cancel Remark" name="cancel_remark"><?= isset($ticket_data['cancel_remark']) ? $ticket_data['cancel_remark'] : '' ?></textarea>
@ -432,6 +454,8 @@
GlobelExtraFields = extraFields; GlobelExtraFields = extraFields;
console.log("extraFields", extraFields); console.log("extraFields", extraFields);
claimStatusFieldChanges(extraFields); claimStatusFieldChanges(extraFields);
// syncApprovedLetterInputs();
// syncSettleLetterInputs();
}) })
@ -458,6 +482,7 @@
$field.prop('required', false); $field.prop('required', false);
var $parentDiv = $field.closest("div"); var $parentDiv = $field.closest("div");
$parentDiv.find("label[for='approved_description'] .text-danger").remove(); $parentDiv.find("label[for='approved_description'] .text-danger").remove();
enforceLetterPairRules();
} }
@ -465,6 +490,72 @@
updateClaimStatusDisplay($(this).val()); updateClaimStatusDisplay($(this).val());
}); });
function validateApprovedLetterPdf(fileInput) {
const file = fileInput.files && fileInput.files[0] ? fileInput.files[0] : null;
if (!file) {
return true;
}
const fileName = (file.name || '').toLowerCase();
const isPdfByName = fileName.endsWith('.pdf');
const mimeType = (file.type || '').toLowerCase();
const isPdfByType = mimeType === '' || mimeType === 'application/pdf' || mimeType === 'application/x-pdf';
const fieldLabel = fileInput.id === 'settle_letter_file' ? 'Settle Letter' : 'Approved Letter';
if (!isPdfByName || !isPdfByType) {
fileInput.value = '';
toastr.warning('Only PDF files are allowed for ' + fieldLabel + '.', 'Warning');
return false;
}
return true;
}
function syncApprovedLetterInputs() {
const $urlInput = $('#approved_letter');
const $fileInput = $('#approved_letter_file');
if (!$urlInput.length || !$fileInput.length) {
return;
}
const hasUrl = $.trim($urlInput.val()) !== '';
const hasFile = $fileInput[0].files && $fileInput[0].files.length > 0;
const isApprovedSectionVisible = $urlInput.closest('.approved').is(':visible');
$fileInput.prop('disabled', hasUrl);
$urlInput.prop('disabled', hasFile);
$fileInput.prop('required', false);
$urlInput.prop('required', isApprovedSectionVisible && !hasFile);
}
function syncSettleLetterInputs() {
const $urlInput = $('#settle_letter');
const $fileInput = $('#settle_letter_file');
if (!$urlInput.length || !$fileInput.length) {
return;
}
const hasUrl = $.trim($urlInput.val()) !== '';
const hasFile = $fileInput[0].files && $fileInput[0].files.length > 0;
$fileInput.prop('disabled', hasUrl);
$urlInput.prop('disabled', hasFile);
// Settled Letter should remain optional by default.
$fileInput.prop('required', false);
$urlInput.prop('required', false);
$("label[for='settle_letter'] .text-danger").remove();
$("label[for='settle_letter_file'] .text-danger").remove();
}
function enforceLetterPairRules() {
syncApprovedLetterInputs();
syncSettleLetterInputs();
}
function claimStatusFieldChanges(fields) { function claimStatusFieldChanges(fields) {
console.log('fields', fields); console.log('fields', fields);
fields.forEach(function(fieldId) { fields.forEach(function(fieldId) {
@ -480,6 +571,13 @@
if ($label.length && !$label.find(".text-danger").length) { if ($label.length && !$label.find(".text-danger").length) {
// $label.append(' <span class="text-danger">*</span>'); // $label.append(' <span class="text-danger">*</span>');
} }
// Keep paired PDF upload visibility in sync with URL field visibility.
if (fieldId === 'approved_letter') {
$('#approved_letter_file').closest('div').show();
} else if (fieldId === 'settle_letter') {
$('#settle_letter_file').closest('div').show();
}
} }
}); });
} }
@ -554,6 +652,9 @@
} }
}); });
// Re-apply URL/file pair rules after bulk required toggles.
enforceLetterPairRules();
} }
@ -565,7 +666,7 @@
console.log('targetId', targetId); console.log('targetId', targetId);
console.log('fields.includes(targetId)', fields.includes(targetId)); console.log('fields.includes(targetId)', fields.includes(targetId));
if (fields.includes(targetId)) { if (fields.includes(targetId) || targetId == "approved_letter_file" || targetId == "settle_letter_file") {
let $field = $("#" + targetId); let $field = $("#" + targetId);
console.log('$field id', $field); console.log('$field id', $field);
@ -593,8 +694,31 @@
$field.prop('required', false); $field.prop('required', false);
var $parentDiv = $field.closest("div"); var $parentDiv = $field.closest("div");
$parentDiv.find("label[for='approved_description'] .text-danger").remove(); $parentDiv.find("label[for='approved_description'] .text-danger").remove();
enforceLetterPairRules();
}); });
$('#approved_letter').on('input blur', function () {
enforceLetterPairRules();
});
$('#approved_letter_file').on('change', function () {
validateApprovedLetterPdf(this);
enforceLetterPairRules();
});
$('#settle_letter').on('input blur', function () {
enforceLetterPairRules();
});
$('#settle_letter_file').on('change', function () {
validateApprovedLetterPdf(this);
enforceLetterPairRules();
});
$('#ticket_form_data').on('submit', function() {
enforceLetterPairRules();
});
// function addRequiredFieldSymbol(field_name) { // function addRequiredFieldSymbol(field_name) {
// // Find the field with the given name // // Find the field with the given name
// var $field = $(`[name="${field_name}"]`); // var $field = $(`[name="${field_name}"]`);

View File

@ -30,6 +30,22 @@ table.dataTable tbody td {
color: #6c757d !important; color: #6c757d !important;
} }
.policy-type-icon {
display: inline-flex;
align-items: center;
margin-right: 6px;
font-size: 0.95rem;
vertical-align: middle;
}
.policy-type-icon--cashless {
color: #0ea5e9;
}
.policy-type-icon--reimbursement {
color: #f59e0b;
}
/* Claim source pill — text only, fixed width (DUMP_TPA); hidden when no value */ /* Claim source pill — text only, fixed width (DUMP_TPA); hidden when no value */
.claim-source-badge { .claim-source-badge {
display: inline-flex; display: inline-flex;
@ -221,7 +237,19 @@ table.dataTable tbody td {
]; ];
$claimSrcClass = $claimSrcClassMap[$claimSrc] ?? null; $claimSrcClass = $claimSrcClassMap[$claimSrc] ?? null;
$policyTypeLabel = str_replace('Claim-', '', $ticket_type[$row['ticket_type_id']] ?? 'N/A'); $policyTypeLabel = str_replace('Claim-', '', $ticket_type[$row['ticket_type_id']] ?? 'N/A');
echo esc($policyTypeLabel); $tpaClaimTypeRaw = trim((string)($row['tpa_claim_type'] ?? ''));
$tpaClaimType = strtolower($tpaClaimTypeRaw);
$policyTypeIconHtml = '';
if ($tpaClaimType !== '') {
if (strpos($tpaClaimType, 'cash') !== false) {
$policyTypeIconHtml = '<span class="policy-type-icon policy-type-icon--cashless" title="Cashless"><i class="mdi mdi-hospital-box-outline" aria-hidden="true"></i></span>';
} elseif (strpos($tpaClaimType, 'reimburse') !== false) {
$policyTypeIconHtml = '<span class="policy-type-icon policy-type-icon--reimbursement" title="Reimbursement"><i class="mdi mdi-cash-refund" aria-hidden="true"></i></span>';
}
}
echo $policyTypeIconHtml . esc($policyTypeLabel);
if ($claimSrcClass !== null) { if ($claimSrcClass !== null) {
echo '<br><span class="claim-source-badge ' . esc($claimSrcClass, 'attr') . '">' . esc($claimSrc) . '</span>'; echo '<br><span class="claim-source-badge ' . esc($claimSrcClass, 'attr') . '">' . esc($claimSrc) . '</span>';
} }
@ -368,6 +396,18 @@ function getClaimSourceBadgeHtml(claimCreatedBy) {
return '<span class="claim-source-badge ' + cls + '">' + escapeHtml(key) + '</span>'; return '<span class="claim-source-badge ' + cls + '">' + escapeHtml(key) + '</span>';
} }
function getPolicyTypeIconHtml(tpaClaimType) {
var type = (tpaClaimType || '').toString().trim().toLowerCase();
if (!type) return '';
if (type.indexOf('cash') !== -1) {
return '<span class="policy-type-icon policy-type-icon--cashless" title="Cashless"><i class="mdi mdi-hospital-box-outline" aria-hidden="true"></i></span>';
}
if (type.indexOf('reimburse') !== -1) {
return '<span class="policy-type-icon policy-type-icon--reimbursement" title="Reimbursement"><i class="mdi mdi-cash-refund" aria-hidden="true"></i></span>';
}
return '';
}
function getStatusDisplay(row) { function getStatusDisplay(row) {
var status = row.status || ''; var status = row.status || '';
var claimStatusId = Number(row.claim_status_id || 0); var claimStatusId = Number(row.claim_status_id || 0);
@ -413,6 +453,7 @@ function buildTicketRowHtml(row) {
var statusUpdated = row.ticket_updated_date ? '<span class="text-custom-grey"><br>Updated at ' + escapeHtml(row.ticket_updated_date) + '</span>' : ''; var statusUpdated = row.ticket_updated_date ? '<span class="text-custom-grey"><br>Updated at ' + escapeHtml(row.ticket_updated_date) + '</span>' : '';
var claimCreated = row.ticket_created_date ? '<span class="text-custom-grey"><br>Created at ' + escapeHtml(row.ticket_created_date) + '</span>' : ''; var claimCreated = row.ticket_created_date ? '<span class="text-custom-grey"><br>Created at ' + escapeHtml(row.ticket_created_date) + '</span>' : '';
var policyType = (window.ticketTypeMap[row.ticket_type_id] || '').replace('Claim-', ''); var policyType = (window.ticketTypeMap[row.ticket_type_id] || '').replace('Claim-', '');
var policyTypeIcon = getPolicyTypeIconHtml(row.tpa_claim_type);
var claimSourceBadge = getClaimSourceBadgeHtml(row.claim_created_by); var claimSourceBadge = getClaimSourceBadgeHtml(row.claim_created_by);
var modeOfIntimation = window.modeOfIntimateMap[row.mode_of_intimation] || ''; var modeOfIntimation = window.modeOfIntimateMap[row.mode_of_intimation] || '';
var priority = window.priorityTypeMap[row.priority || 0] || ''; var priority = window.priorityTypeMap[row.priority || 0] || '';
@ -423,7 +464,7 @@ function buildTicketRowHtml(row) {
'<span class="status-tooltip">' + getStatusDisplay(row) + '</span>' + '<span class="status-tooltip">' + getStatusDisplay(row) + '</span>' +
statusUpdated + statusUpdated +
'</td>' + '</td>' +
'<td>' + asText(policyType) + (claimSourceBadge ? '<br>' + claimSourceBadge : '') + '</td>' + '<td>' + policyTypeIcon + asText(policyType) + (claimSourceBadge ? '<br>' + claimSourceBadge : '') + '</td>' +
'<td>' + asText(row.claim_no) + claimCreated + '</td>' + '<td>' + asText(row.claim_no) + claimCreated + '</td>' +
'<td>' + asText(row.tpa_no) + '</td>' + '<td>' + asText(row.tpa_no) + '</td>' +
'<td>' + asText(row.emp_code) + '</td>' + '<td>' + asText(row.emp_code) + '</td>' +