diff --git a/app/Controllers/EmployeeController.php b/app/Controllers/EmployeeController.php index fe377c2a..3814a64d 100755 --- a/app/Controllers/EmployeeController.php +++ b/app/Controllers/EmployeeController.php @@ -1502,14 +1502,14 @@ class EmployeeController extends AdminController } // exit(); } - else - { - if($mode !== 2) - { - $data['message'] = 'Inprogress... Comeback later! or Contact support'; - return view('errors/404', $data); - } - } + // else + // { + // if($mode !== 2) + // { + // $data['message'] = 'Inprogress... Comeback later! or Contact support'; + // return view('errors/404', $data); + // } + // } //in else generate PDF and upload it in s3 // echo 'else'; @@ -1646,20 +1646,27 @@ class EmployeeController extends AdminController // echo '
PDF generated and uploaded to S3 successfully.
'; unlink($temp_local_path); - // exit(); - // if ($mode == 1) { - // // Inline view - // return $this->response - // ->setHeader('Content-Type', 'application/pdf') - // ->setHeader('Content-Disposition', 'inline; filename="' . $filename . '"') - // ->setBody($dompdf->output()); - // } else { - // // Force download - // return $this->response - // ->setHeader('Content-Type', 'application/pdf') - // ->setHeader('Content-Disposition', 'attachment; filename="' . $filename . '"') - // ->setBody($dompdf->output()); - // } + if($s3->exists($s3_key)) //2 => for bulk generate so skip s3 check and generate PDF + { + //get pre signed url & make it download + $s3_url = $s3->getPresignedUrl($s3_key ); + + $pdf = file_get_contents($s3_url['url']); + if ($mode == 1) { + // Inline view + return $this->response + ->setHeader('Content-Type', 'application/pdf') + ->setHeader('Content-Disposition', 'inline; filename="' . $s3_key . '"') + ->setBody($pdf); + } else if($mode == 0){ + // echo 'Force download';//die(); + return $this->response + ->setHeader('Content-Type', 'application/pdf') + ->setHeader('Content-Disposition', 'attachment; filename="' . $s3_key . '"') + ->setBody($pdf); + } + // exit(); + } // $this->myLogger->logme('error', 'generateIDCardForEmployee function completed successfully.'); @@ -1671,6 +1678,20 @@ class EmployeeController extends AdminController } + public function sanitizeFilePart(string $value): string + { + // Trim spaces + $value = trim($value); + + // Replace ANY unsafe character (including /) with underscore + $value = preg_replace('/[^A-Za-z0-9._()-]/', '_', $value); + + // Collapse multiple underscores + $value = preg_replace('/_+/', '_', $value); + + return $value; + } + // -------------------------------------------------------------------------------------------------------------------- public function viewECard() @@ -4019,187 +4040,209 @@ class EmployeeController extends AdminController exit; } - public function bulkGenerateEcardAndStoreinS3(array $params = []) + public function bulkGenerateEcardAndStoreinS3(array $params = []) { - /** - * --------------------------- - * 1. Detect mode + collect inputs - * --------------------------- - */ + $request = \Config\Services::request(); + $isCli = is_cli(); - $client_policy_id = $params['client_policy_id'] ?? null; - $emp_code = $params['emp_code'] ?? null; - $emp_pk = $params['emp_pk'] ?? null; - $batch_size = $params['batch_size'] ?? null; - $batch_no = $params['batch_no'] ?? null; - $execution_mode = $params['execution_mode'] ?? 'sequential';//parallel - $total_batches = $params['total_batches'] ?? 0;//parallel - - if (is_cli()) { - $mode = 'CLI'; - + /* --------------------------------------------------------- + * 1. INPUTS (shared for WEB + CLI) + * --------------------------------------------------------- */ + $client_policy_id = $params['client_policy_id'] ?? (!$isCli ? $request->getGet('client_policy_id') : null); + $emp_code = $params['emp_code'] ?? (!$isCli ? $request->getGet('emp_code') : null); + $emp_pk = $params['emp_pk'] ?? (!$isCli ? $request->getGet('emp_pk') : null); - } elseif (empty($params) && $this->request->getMethod() === 'get') { - $mode = 'WEB'; + $batch_size = (int) ($params['batch_size'] ?? (!$isCli ? $request->getGet('batch_size') : 100)); + $batch_size = $batch_size > 0 ? $batch_size : 100; - $client_policy_id = $this->request->getGet('client_policy_id'); - $emp_code = $this->request->getGet('emp_code'); - $emp_pk = $this->request->getGet('emp_pk'); - $execution_mode = $this->request->getGet('execution_mode') ?? 'sequential'; - $batch_size = (int) ($this->request->getGet('batch_size') ?? 100); - if($client_policy_id == null || empty($client_policy_id) || $client_policy_id == '') - { - return $this->respond(['status' => false, 'code' => 200, 'message' => 'client_policy_id is necessary'], 200); + $batch_no = isset($params['batch_no']) ? (int) $params['batch_no'] : null; + $total_batches = (int) ($params['total_batches'] ?? 0); + $execution_mode = $params['execution_mode'] ?? (!$isCli ? $request->getGet('execution_mode') : 'sequential'); + $execution_mode = in_array($execution_mode, ['sequential', 'parallel']) ? $execution_mode : 'sequential'; + $is_dry_run = $params['is_dry_run'] ?? (!$isCli ? $request->getGet('is_dry_run') : false); + + $log_search_context = 'ECARD_BULK_TO_S3'; + if($is_dry_run) + { + $log_search_context = 'ECARD_BULK_TO_S3_DRY_RUN'; + } + + // Cursor (KEY FIX: avoids OFFSET issues) + $last_emp_id = (int) ($params['last_emp_id'] ?? 0); + + $this->myLogger->logme('error', "$log_search_context"." INIT - ". json_encode([ + 'cli' => $isCli, + 'policy' => $client_policy_id, + 'batch_no' => $batch_no, + 'last_emp_id' => $last_emp_id, + 'mode' => $execution_mode + 'is_dry_run' => $is_dry_run + ])); + + /* --------------------------------------------------------- + * 2. WEB DISPATCHER (QUEUE CREATOR) + * --------------------------------------------------------- */ + if (!$isCli && empty($params)) { + + if (empty($client_policy_id)) { + return $this->respond(['status' => false, 'message' => 'client_policy_id required'], 200); } - /** - * --------------------------- - * 2. Calculate total records - * --------------------------- - */ - $total = $this->employeePolicyModel + + // COUNT QUERY (same filters as worker) + $countBuilder = $this->employeePolicyModel->builder() ->join('employees', 'employees.id = employee_polices.employee_id') - ->where('employees.emp_status', 'active') - ->where('employees.is_active', '1') - ->where("employee_polices.tpa_id IS NOT NULL AND employee_polices.tpa_id <> ''") - ->where('employee_polices.status', 'active') - ->where('employee_polices.is_active', '1') - ->where('employee_polices.client_policy_id', $client_policy_id) - ->countAllResults(); + ->where([ + 'employees.emp_status' => 'active', + 'employees.is_active' => '1', + 'employee_polices.status' => 'active', + 'employee_polices.is_active' => '1', + 'employee_polices.client_policy_id' => $client_policy_id + ]) + ->where("employee_polices.tpa_id IS NOT NULL AND employee_polices.tpa_id <> ''"); + + if ($emp_code) $countBuilder->where('employees.emp_code', $emp_code); + if ($emp_pk) $countBuilder->where('employees.id', $emp_pk); + + $total = (int) $countBuilder->countAllResults(); + + if ($total === 0) { + $this->myLogger->logme('error', "$log_search_context". 'No records found. Queue skipped.'); + return $this->respond(['status' => 'NO_RECORDS'], 200); + } $total_batches = (int) ceil($total / $batch_size); - // echo $total_batches;die(); + $this->myLogger->logme('error', "$log_search_context".'Queueing jobs - '. json_encode([ + 'total' => $total, + 'batches' => $total_batches, + 'mode' => $execution_mode + ])); + $basePayload = [ + 'client_policy_id' => $client_policy_id, + 'batch_size' => $batch_size, + 'total_batches' => $total_batches, + 'execution_mode' => $execution_mode, + 'emp_code' => $emp_code, + 'emp_pk' => $emp_pk, + 'last_emp_id' => 0, + 'is_dry_run' => $is_dry_run + ]; - /** - * --------------------------- - * 3. Push JOB per batch - * --------------------------- - */ if ($execution_mode === 'parallel') { - for ($batch_no = 1; $batch_no <= $total_batches; $batch_no++) { + for ($i = 1; $i <= $total_batches; $i++) { Jobs::addJob([ 'job_name' => 'bulkGenerateEcardAndStoreinS3', - 'payload' => [ - 'client_policy_id' => $client_policy_id, - 'emp_code' => $emp_code, - 'emp_pk' => $emp_pk, - 'batch_size' => $batch_size, - 'batch_no' => $batch_no, - 'total_batches' => $total_batches, - 'execution_mode' => 'parallel', - ], + 'payload' => array_merge($basePayload, ['batch_no' => $i]) ]); } + } else { + Jobs::addJob([ + 'job_name' => 'bulkGenerateEcardAndStoreinS3', + 'payload' => array_merge($basePayload, ['batch_no' => 1]) + ]); } - if ($execution_mode === 'sequential') { - Jobs::addJob([ - 'job_name' => 'bulkGenerateEcardAndStoreinS3', - 'payload' => [ - 'client_policy_id' => $client_policy_id, - 'batch_size' => $batch_size, - 'batch_no' => $batch_no ?? 1, - 'total_batches' => $total_batches, - 'execution_mode' => 'sequential', - ], - ]); - } + return $this->respond([ + 'status' => 'ECARD_BULK_TO_S3 Job queued', + 'total' => $total, + 'batches' => $total_batches + ], 200); + } - return $this->respond(['status' => true, 'code' => 200, 'message' => 'E-card generation started', - 'total' => $total, - 'batches' => $total_batches,], 200); - // return [ - // 'status' => true, - // 'message' => 'E-card generation started', - // 'total' => $total, - // 'batches' => $total_batches, - // ]; - } - //else { - // return true; - // } + /* --------------------------------------------------------- + * 3. CLI WORKER (ACTUAL PROCESSOR) + * --------------------------------------------------------- */ + if ($batch_no === null) { + $this->myLogger->logme('error', "$log_search_context".'Worker called without batch_no'); + return; + } - /** - * --------------------------- - * 4. Build query (CLI execution) - * --------------------------- - */ - $builder = $this->employeePolicyModel - ->select(' + $this->myLogger->logme('error', "$log_search_context"."START Batch {$batch_no}"); + + $builder = $this->employeePolicyModel->builder(); + $builder->select(' employee_polices.client_policy_id, employees.emp_code, + employees.id as emp_id, tpa.short_name, employees.client_id, - employee_polices.rand_string, - employees.id as emp_id + employee_polices.rand_string ') ->join('client_policy', 'client_policy.id = employee_polices.client_policy_id') ->join('employees', 'employees.id = employee_polices.employee_id') ->join('tpa', 'tpa.id = client_policy.tpa_id') - ->where('employees.emp_status', 'active') - ->where('employees.is_active', '1') + ->where([ + 'employees.emp_status' => 'active', + 'employees.is_active' => '1', + 'employee_polices.status' => 'active', + 'employee_polices.is_active' => '1', + 'employee_polices.client_policy_id' => $client_policy_id + ]) ->where("employee_polices.tpa_id IS NOT NULL AND employee_polices.tpa_id <> ''") - ->where('employee_polices.status', 'active') - ->where('employee_polices.is_active', '1') - ->where('employee_polices.client_policy_id', $client_policy_id); + ->orderBy('employees.id', 'ASC'); - if (!empty($emp_code)) { - $builder->where('employees.emp_code', $emp_code); + if ($emp_code) $builder->where('employees.emp_code', $emp_code); + if ($emp_pk) $builder->where('employees.id', $emp_pk); + if ($last_emp_id) $builder->where('employees.id >', $last_emp_id); + + $rows = $builder->get($batch_size)->getResultArray(); + $rowCount = count($rows); + + $this->myLogger->logme('error', "$log_search_context"." Batch {$batch_no} fetched {$rowCount} rows"); + + if ($rowCount === 0) { + $this->myLogger->logme('error', "$log_search_context"." Batch {$batch_no} empty. STOPPING."); + return; } - if (!empty($emp_pk)) { - $builder->where('employees.id', $emp_pk); - } + foreach ($rows as $row) { + $this->myLogger->logme('error', "$log_search_context".' Processing - '. json_encode([ + 'emp_id' => $row['emp_id'], + 'emp_code' => $row['emp_code'], + 'policy' => $row['client_policy_id'] + ])); - /** - * --------------------------- - * 5. Apply batching (only if provided) - * --------------------------- - */ - if (!empty($batch_size) && !empty($batch_no)) { - $offset = ($batch_no - 1) * $batch_size; - $builder->limit($batch_size, $offset); - } - - $res = $builder->findAll(); - - /** - * --------------------------- - * 6. Process batch - * --------------------------- - */ - foreach ($res as $row) { - $ecard_gen_res = $this->generateIDCardForEmployee( - $row['rand_string'], - 0, - 2 // skip S3 check, force regenerate - ); - - // print_rr([ - // 'batch' => $batch_no, - // 'emp' => $row['emp_code'], - // 'res' => $ecard_gen_res, - // ]); - - // echo date('Y-m-d H:i:s') . PHP_EOL; - } - - if ($execution_mode === 'sequential' && $batch_no < $total_batches) { - Jobs::addJob([ - 'job_name' => 'bulkGenerateEcardAndStoreinS3', - 'payload' => [ - 'client_policy_id' => $client_policy_id, - 'batch_size' => $batch_size, - 'batch_no' => ($batch_no + 1), - 'total_batches' => $total_batches, - 'execution_mode' => 'sequential', - ], - ]); + if(!$is_dry_run) //for tesing skip generate ecard and just log only + { + $ecard_gen_res = $this->generateIDCardForEmployee($row['rand_string'],0,2); // 2 means skip S3 check } - // echo "BATCH {$batch_no} COMPLETED @ " . date('Y-m-d H:i:s') . PHP_EOL; - return array($batch_no); + $this->myLogger->logme('error', "$log_search_context".' processed - '. json_encode([ + 'emp_id' => $row['emp_id'], + 'emp_code' => $row['emp_code'], + 'policy' => $row['client_policy_id'], + // 'ecard_gen_res' => $ecard_gen_res + ]));//check + } + + $new_last_emp_id = end($rows)['emp_id']; + + /* --------------------------------------------------------- + * 4. SEQUENTIAL RE-QUEUE (SAFE) + * --------------------------------------------------------- */ + if ($execution_mode === 'sequential' && $rowCount === $batch_size) { + $this->myLogger->logme('info', "$log_search_context"."Re-queueing next batch - " . json_encode([ + 'next_batch' => $batch_no + 1, + 'last_emp_id' => $new_last_emp_id + ])); + + Jobs::addJob([ + 'job_name' => 'bulkGenerateEcardAndStoreinS3', + 'payload' => [ + 'client_policy_id' => $client_policy_id, + 'batch_size' => $batch_size, + 'batch_no' => $batch_no + 1, + 'execution_mode' => 'sequential', + 'last_emp_id' => $new_last_emp_id, + 'emp_code' => $emp_code, + 'emp_pk' => $emp_pk, + 'is_dry_run' => $is_dry_run + ] + ]); + } + + $this->myLogger->logme('error', "$log_search_context". "END Batch {$batch_no}"); } diff --git a/app/Controllers/EmployeeRestController.php b/app/Controllers/EmployeeRestController.php index bb64f69e..8f141d28 100755 --- a/app/Controllers/EmployeeRestController.php +++ b/app/Controllers/EmployeeRestController.php @@ -2928,6 +2928,11 @@ class EmployeeRestController extends AdminController $data['ticket_settled_status_id'] = 44; $data['claim_subject'] = "Claim GTLI"; $data['sum_insured_label'] = "Sum Assured"; + } else if ($ClientPolicyValue['policy_type_id'] == 72){ + $data['ticket_type_id'] = 72; + $data['ticket_settled_status_id'] = 76; + $data['claim_subject'] = "Claim OPD"; + $data['sum_insured_label'] = "Sum Insured"; } else { $policyGroup = 'gmc'; $data['ticket_type_id'] = 1; @@ -3625,7 +3630,7 @@ class EmployeeRestController extends AdminController WHEN cp.policy_type_id = 1 THEN 2 WHEN cp.policy_type_id = 6 THEN 3 WHEN cp.policy_type_id = 7 THEN 4 - ELSE NULL + ELSE cp.policy_type_id END AS ticket_type_id from employees emp @@ -3653,6 +3658,9 @@ class EmployeeRestController extends AdminController if ($fetchData['ticket_type_id'] == 1 && !empty($fetchData['tpa_no'])) { $results = $claimStatusQuery->findAll(2); $fetchData['claim_status_id'] = $results[1]['id'] ?? $results[0]['id']; + } else if ($fetchData['ticket_type_id'] == 72 && !empty($fetchData['tpa_no'])) { + $results = $claimStatusQuery->findAll(2); + $fetchData['claim_status_id'] = $results[1]['id'] ?? $results[0]['id']; } else { $fetchData['claim_status_id'] = $claimStatusQuery->first()['id']; } @@ -3918,6 +3926,7 @@ class EmployeeRestController extends AdminController 1 => 2, 6 => 3, 7 => 4, + 72 => 72, ]; foreach ($policy_type_ids as $value) { diff --git a/app/Controllers/TicketController.php b/app/Controllers/TicketController.php index 73997e99..07b8db0e 100644 --- a/app/Controllers/TicketController.php +++ b/app/Controllers/TicketController.php @@ -76,7 +76,7 @@ class TicketController extends BaseController $this->ticketMasterModel = new TicketMasterModel(); - $this->ticketType = [1 => "Claim-GMC", 2 => "Claim-GPA", 3 => "EDLI", 4 => "GTLI", 8 => "Motor"]; + $this->ticketType = [1 => "Claim-GMC", 2 => "Claim-GPA", 3 => "EDLI", 4 => "GTLI", 8 => "Motor", 72 => "OPD"]; $this->priorityType = [ 1 => "Low", 2 => "Medium", @@ -287,7 +287,45 @@ class TicketController extends BaseController 13 => ['cancel_remark' => 'Cancel Remark'], 47 => ['cancel_remark' => 'Cancel Remark'], 53 => ['cancel_remark' => 'Cancel Remark'], - 58 => ['cancel_remark' => 'Cancel Remark'] + 58 => ['cancel_remark' => 'Cancel Remark'], + + + // OPD claim status + 67 => ['non_id_reason' => 'Non ID Reason'], + 69 => ['raised_date' => 'Raised Date'], + 70 => ['raised_date' => 'Raised Date'], + 71 => [ + 'claim_number' => 'Claim Number', + 'registration_date' => 'Registration Date' + ], + + 72 => ['query_received_date' => 'Query Received Date'], + 73 => [ + 'denial_reason' => 'Denial Reason', + 'denial_date' => 'Denial Date' + ], + 74 => [ + 'approved_amount' => 'Approved Amount', + 'approved_date' => 'Approved Date', + 'approved_letter' => 'Approved Letter', + 'approved_description' => 'Approved Description' + ], + + 75 => ['pay_initiate_date' => 'Payment Initiated Date'], + + 76 => [ + 'utr_details' => 'UTR Details', + 'settled_date' => 'Settled Date', + 'settle_letter' => 'Settle Letter' + ], + + 78 => ['cancel_remark' => 'Cancel Remark'], + + 79 => [ + 'return_remark' => 'Return Remark', + 'awb_no_courier_name' => 'AWB No Courier Name' + ], + ]; $this->nonIDReason = [ @@ -335,7 +373,12 @@ class TicketController extends BaseController 55 => [], 56 => [], 57 => [], - 60 => [] + 60 => [], + + 68 => [], + 77 => [], + 80 => [], + 81 => [], ]; $this->ticketMasterModel = new TicketMasterModel(); @@ -703,7 +746,8 @@ class TicketController extends BaseController 'priorityType' => $this->priorityType, 'relationshipType' => $this->relationshipType, 'modeOFIntimate' => $this->modeOFIntimate, - 'nonIDReason' => $this->nonIDReason + 'nonIDReason' => $this->nonIDReason, + 'claim_ticket_type_id' => $ticket_type ]; switch ($ticket_type) { @@ -719,6 +763,9 @@ class TicketController extends BaseController case 8: $data['ticket_form'] = 'Motor'; break; + case 72: + $data['ticket_form'] = 'OPD'; + break; } // Fetch ACM Users @@ -741,8 +788,9 @@ class TicketController extends BaseController $claim_status_id = 35; }else if($ticket_type == 8){ $claim_status_id = 62; - } - else{ + }else if($ticket_type == 72){ + $claim_status_id = 67; + }else{ $claim_status_id = 1; } } @@ -757,7 +805,9 @@ class TicketController extends BaseController $data['claim_type'] = $this->claimType[2]; } - $data['client_for_motor'] = $this->clientModel->select('id,client_name,phone')->where('client_type', 2)->where('is_active', 1)->findAll(); + if($ticket_type == 8){ + $data['client_for_motor'] = $this->clientModel->select('id,client_name,phone')->where('client_type', 2)->where('is_active', 1)->findAll(); + } $this->myLogger->logme('error', "Ticket form data fetched successfully for Ticket Type: $ticket_type"); @@ -2013,9 +2063,13 @@ class TicketController extends BaseController } } - if($lastMatchedStatus == 1){ + if($lastMatchedStatus == 1 || $lastMatchedStatus == 67){ if(!empty($incoming_form_values['tpa_no'])){ - $lastMatchedStatus = 2; + if($lastMatchedStatus == 1){ + $lastMatchedStatus = 2; + }else if($lastMatchedStatus == 67){ + $lastMatchedStatus = 68; + } } } diff --git a/app/Views/ticket_form_gmc.php b/app/Views/ticket_form_gmc.php index 1bf0da03..5d1ae008 100644 --- a/app/Views/ticket_form_gmc.php +++ b/app/Views/ticket_form_gmc.php @@ -38,7 +38,7 @@
-

Claim GMC

+

@@ -49,7 +49,7 @@
- + @@ -681,6 +681,29 @@ showClass = '.payment'; } + // OPD + if (value == 69 || value == 70) { // CDA & INFORMATION REQUIRED + showClass = '.cda_ir'; + } else if (value == 71) { // UNDER PROCESS - CLAIM NO. UPDATION + showClass = '.up_cnu'; + } else if (value == 72) { // UNDER PROCESS - QUERY DOCUMENT RECEIVED + showClass = '.up_qdr'; + } else if (value == 73) { // REJECTED + showClass = '.rejected'; + } else if (value == 74) { // APPROVED + showClass = '.approved'; + } else if (value == 76) { // SETTLED + showClass = '.settled'; + } else if (value == 78) { // CANCELLED + showClass = '.canceled'; + } else if (value == 79) { // RETURNED + showClass = '.returned'; + } else if (value == 67) { // NON ID + showClass = '.non_id'; + } else if (value == 75) { // PAYMENT INITIATED + showClass = '.payment'; + } + // Show the relevant section and enable required attributes if (showClass) { // $(showClass).show().find('input, textarea').attr('required', true); @@ -708,7 +731,7 @@ console.log('Selected Value:', selectedVal); console.log('Element ID:', elementId); - if (selectedVal == 2 || selectedVal == 14) { + if (selectedVal == 2 || selectedVal == 14 || selectedVal == 68 || selectedVal == 79) { $field = $('#non_id_reason') $field.prop('required', false); } else if (selectedVal == 1) { @@ -1134,7 +1157,7 @@ $.each(data, function(index, item) { // console.log(item); - if (ticket_type == 1 && item.policy_type_id != 1) { + if ((ticket_type == 1 && item.policy_type_id != 1) || (ticket_type == 72 && item.policy_type_id == 72)) { $('#emp_client_policy').append($(' +