From 91e46da27d9461e462c7eca9c4e206f246939a8a Mon Sep 17 00:00:00 2001 From: velz Date: Mon, 29 Dec 2025 13:35:11 +0530 Subject: [PATCH 01/17] FIX_ECARD_S3_MIG --- app/Controllers/EmployeeController.php | 374 ++++++++++++++----------- 1 file changed, 207 insertions(+), 167 deletions(-) diff --git a/app/Controllers/EmployeeController.php b/app/Controllers/EmployeeController.php index fe377c2a..1c6c9ce5 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,206 @@ 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'] + ])); + + $ecard_gen_res = $this->generateIDCardForEmployee($row['rand_string'],0,2); // 2 means skip S3 check + + $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 } - /** - * --------------------------- - * 5. Apply batching (only if provided) - * --------------------------- - */ - if (!empty($batch_size) && !empty($batch_no)) { - $offset = ($batch_no - 1) * $batch_size; - $builder->limit($batch_size, $offset); + $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 + ] + ]); } - $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', - ], - ]); - } - - // 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". "END Batch {$batch_no}"); } From 3fe796d7ffe3e13daa6518ab324790cc2fa85be8 Mon Sep 17 00:00:00 2001 From: "venkatesh.r" Date: Mon, 29 Dec 2025 15:19:41 +0530 Subject: [PATCH 02/17] OPD_CLAIM_HANDLE --- app/Controllers/EmployeeRestController.php | 3 + app/Controllers/TicketController.php | 72 +++++++++++++++++++--- app/Views/ticket_form_gmc.php | 29 ++++++++- app/Views/ticket_form_handler.php | 26 +++++++- app/Views/ticket_type_modal.php | 1 + 5 files changed, 116 insertions(+), 15 deletions(-) diff --git a/app/Controllers/EmployeeRestController.php b/app/Controllers/EmployeeRestController.php index bb64f69e..8190e7a8 100755 --- a/app/Controllers/EmployeeRestController.php +++ b/app/Controllers/EmployeeRestController.php @@ -3653,6 +3653,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']; } 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..e3bf14e3 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) { diff --git a/app/Views/ticket_form_handler.php b/app/Views/ticket_form_handler.php index b3f34cd9..07637cf6 100644 --- a/app/Views/ticket_form_handler.php +++ b/app/Views/ticket_form_handler.php @@ -62,7 +62,7 @@ ', { + value: item.id, + text: item.policy_type + '-' + item.policy_no, + }); + + $('#emp_client_policy_data_list').append(option).select2(); + } + } else { // console.log("inside else condition"); } @@ -1119,6 +1130,7 @@ function setMemberData(input) { var selectedOption = $(input).find(':selected'); + var ticket_type_id = $('#ticket_type_id').val(); // Retrieve the data-* attributes var empId = selectedOption.data('empid'); @@ -1140,13 +1152,21 @@ if (tpaNo == "") { - $('#claim_status_id').val(1) + if(ticket_type_id == 1){ + $('#claim_status_id').val(1) + }else{ + $('#claim_status_id').val(67) + } $('#non_id_reason').attr('required', true); var $label = $("#non_id_reason_lable_id"); $label.text('*'); } else { - $('#claim_status_id').val(2) + if(ticket_type_id == 1){ + $('#claim_status_id').val(2) + }else{ + $('#claim_status_id').val(68) + } $('#non_id_reason').attr('required', false); var $label = $("#non_id_reason_lable_id"); $label.text(""); diff --git a/app/Views/ticket_type_modal.php b/app/Views/ticket_type_modal.php index 99782601..2e7fdf82 100644 --- a/app/Views/ticket_type_modal.php +++ b/app/Views/ticket_type_modal.php @@ -29,6 +29,7 @@ +
From 5982bedb0db2c3031146d022cbffda2c0c4f1a6a Mon Sep 17 00:00:00 2001 From: "venkatesh.r" Date: Mon, 29 Dec 2025 15:37:22 +0530 Subject: [PATCH 03/17] FIX_ISSUE --- app/Controllers/EmployeeRestController.php | 1 + app/Views/ticket_form_gmc.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/Controllers/EmployeeRestController.php b/app/Controllers/EmployeeRestController.php index 8190e7a8..bbbc08fd 100755 --- a/app/Controllers/EmployeeRestController.php +++ b/app/Controllers/EmployeeRestController.php @@ -3921,6 +3921,7 @@ class EmployeeRestController extends AdminController 1 => 2, 6 => 3, 7 => 4, + 72 => 72, ]; foreach ($policy_type_ids as $value) { diff --git a/app/Views/ticket_form_gmc.php b/app/Views/ticket_form_gmc.php index e3bf14e3..5d1ae008 100644 --- a/app/Views/ticket_form_gmc.php +++ b/app/Views/ticket_form_gmc.php @@ -1157,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($(' Ticket ID : ((TICKET_ID)) has remained in the same status for ((HOURS)) hours. Please take the necessary action.'; + + $common = [ + 'module' => 'THZ', + 'mail_type' => 'Thz_Reminder_mail' + ]; + + $mail_send_count = 0; + + if(!empty($result)){ + foreach ($result as $value) { + + // Calculate hours difference + $createdAt = new \DateTime($value['created_at']); + $now = new \DateTime(); + $hours = floor(($now->getTimestamp() - $createdAt->getTimestamp()) / 3600); + $ticket_url = base_url('ticketConversationList?return_type=web&thz_id=' . $value['thz_id']); + + // Replace placeholders + $subject = str_replace('((HOURS))', $hours, $subjectTemplate); + + $message = str_replace( + ['((TICKET_ID))', '((HOURS))', '((TICKET_URL))'], + [$value['thz_id'], $hours, $ticket_url], + $messageTemplate + ); + + + $client_id = $value['client_id']; + $level_of_user_data = $this->getRmsIdUsingClientId($client_id); + + if(!empty($level_of_user_data)){ + foreach ($level_of_user_data as $user) { + + $res = MailHelper::send_email([ + 'mail' => $user['email'], + 'subject' => $subject, + 'message' => $message, + 'common' => $common + ]); + + $mail_send_count++; + + $this->myLogger->logme( + 'error', + 'THZ Reminder Mail Sent | Ticket ID: ' . $value['thz_id'] . ' | Client ID : ' . $client_id . ' | Response: ' . json_encode($res) + ); + } + }else{ + $this->myLogger->logme('error', 'CLIENT ID : ' . $client_id . "has no RM's found skipped...." ); + } + } + }else{ + if($this->request){ + return $this->respond(['message' => "No ticket Pending for More Than 8 hrs"], 200); + }else{ + $this->myLogger->logme('error', 'No ticket Pending for More Than 8 hrs'); + echo 'No ticket Pending for More Than 8 hrs'; + return; + } + } + + if($this->request){ + return $this->respond(['mail_send_count' => $mail_send_count], 200); + }else{ + print_r(['mail_send_count' => $mail_send_count]); + return; + } + } + + } From ab43cdc68afbfc2be31c8fb5aebc478c0631a267 Mon Sep 17 00:00:00 2001 From: "venkatesh.r" Date: Wed, 31 Dec 2025 12:52:57 +0530 Subject: [PATCH 14/17] FIX_TABLE_NOT_FOUND_ISSUE --- app/Controllers/EmployeeController.php | 17 +++++++++++++++-- app/Views/view_file_upload_emp_list.php | 16 +++++++--------- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/app/Controllers/EmployeeController.php b/app/Controllers/EmployeeController.php index 66549050..d40ee267 100755 --- a/app/Controllers/EmployeeController.php +++ b/app/Controllers/EmployeeController.php @@ -1076,10 +1076,23 @@ class EmployeeController extends AdminController } return $this->respond(['dataStatus' => true, 'code' => 200, 'data' => $html, 'file_data' => $file_name, 'excel_data' => $excel_data], 200); - } catch (\Exception $e) { + } catch (\Throwable $th) { + + $errorData = [ + 'message' => $th->getMessage(), + 'file' => $th->getFile(), + 'line' => $th->getLine(), + 'code' => $th->getCode(), + 'trace' => $th->getTraceAsString(), + 'trace_array' => $th->getTrace(), // full array version (optional) + 'function' => $th->getTrace()[0]['function'] ?? null, + 'class' => $th->getTrace()[0]['class'] ?? null, + ]; + // Handle exception - $errorMessage = 'Error occurred: ' . $e->getMessage(); + $errorMessage = 'Error occurred:' . PHP_EOL . json_encode($errorData, JSON_PRETTY_PRINT); $this->myLogger->logme('error', $errorMessage); + $html = '
No Data Found
'; return $this->respond(['dataStatus' => false, 'code' => 500, 'data' => $html, 'file_data' => $file_name], 500); } diff --git a/app/Views/view_file_upload_emp_list.php b/app/Views/view_file_upload_emp_list.php index 96ce9b36..aab97b08 100755 --- a/app/Views/view_file_upload_emp_list.php +++ b/app/Views/view_file_upload_emp_list.php @@ -22,15 +22,13 @@ table.dataTable tbody td { - - - - - - - - - + + + + + + + From 7b994166c60796ed3bbec54f088aa746bca583dc Mon Sep 17 00:00:00 2001 From: "venkatesh.r" Date: Wed, 31 Dec 2025 18:11:52 +0530 Subject: [PATCH 15/17] FIX_ISSUE_MOBILE_NUMBER --- app/Controllers/RestAuthenticationController.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/Controllers/RestAuthenticationController.php b/app/Controllers/RestAuthenticationController.php index 9c9065b9..bad20540 100755 --- a/app/Controllers/RestAuthenticationController.php +++ b/app/Controllers/RestAuthenticationController.php @@ -101,6 +101,7 @@ class RestAuthenticationController extends AdminController ->where('employees.mobile', $mobile_number) ->where('EP.is_active', 1) ->whereIn('EP.status', ['active', 'expired']) + ->orderBy('employees.id', 'desc') ->first(); $lastQuery = $this->employeeModel->db->getLastQuery(); @@ -122,7 +123,7 @@ class RestAuthenticationController extends AdminController AND employees.relationship = 'self' AND employees.is_active = 1 AND employee_polices.is_active = 1 - AND employee_polices.status IN ('active') + AND employee_polices.status IN ('active', 'expired') "; $db = db_connect(); @@ -166,7 +167,7 @@ class RestAuthenticationController extends AdminController log_message('error', ' '); log_message('error', ' ************************************* POST END **************************************** '); log_message('error', ' '); - return $this->respond(['status' => 'failed','code' => 500,'data' => $th],500); + return $this->respond(['status' => 'failed','code' => 500,'data' => $th->getMessage()],500); } } From 0a7d93a195d4935097ed0b4bf54a44ee0b696ff8 Mon Sep 17 00:00:00 2001 From: "venkatesh.r" Date: Fri, 2 Jan 2026 11:02:40 +0530 Subject: [PATCH 16/17] FEAT_REGENERATE_ECARD_TO_S3 --- app/Controllers/EmpDataServiceController.php | 8 +++ app/Controllers/EmployeeController.php | 2 + app/Models/EmployeePolicyModel.php | 1 + app/Views/employee_data_list.php | 71 ++++++++++++++++++++ 4 files changed, 82 insertions(+) diff --git a/app/Controllers/EmpDataServiceController.php b/app/Controllers/EmpDataServiceController.php index 179aa7b3..452f414b 100755 --- a/app/Controllers/EmpDataServiceController.php +++ b/app/Controllers/EmpDataServiceController.php @@ -2203,6 +2203,9 @@ class EmpDataServiceController extends BaseController if ($get_policy_type['policy_type_id'] != 1) { + // generate e-card and store S3 + $r = Jobs::addJob(['job_name' => 'bulkGenerateEcardAndStoreinS3', 'payload' => ['client_policy_id' => $client_policy_id]]); + $job_details = new Jobs(); $r = Jobs::addJob(['job_name' => 'sendMailForDownloadingECard', 'payload' => ['ids' => $emp_policy_ids, 'client_policy_id' => $client_policy_id]]); } @@ -2524,6 +2527,7 @@ class EmpDataServiceController extends BaseController $event_type = $file['event_type']; $policy_issue_date = $file['policy_issue_date']; + $client_policy_data = $this->clientPolicyModel->where('id', $client_policy_id)->first(); $status_val = 'success'; if ($status == 'in-progress-partially') { @@ -2613,6 +2617,10 @@ class EmpDataServiceController extends BaseController 'status' => $status_val, ]); + if($client_policy_data['policy_type_id'] != 1){ + // re-generate e-card and store S3 + $r = Jobs::addJob(['job_name' => 'bulkGenerateEcardAndStoreinS3', 'payload' => ['client_policy_id' => $client_policy_id]]); + } $this->myLogger->logme('error', 'importCorrectionUpdateEndorsementID employee count : {data}', ['data'=> $emp_count]); $this->myLogger->logme('error', 'importCorrectionUpdateEndorsementID batch file status : {data}', ['data'=> $status_val]); diff --git a/app/Controllers/EmployeeController.php b/app/Controllers/EmployeeController.php index d40ee267..d394de03 100755 --- a/app/Controllers/EmployeeController.php +++ b/app/Controllers/EmployeeController.php @@ -4163,6 +4163,8 @@ class EmployeeController extends AdminController return $this->respond([ 'status' => 'ECARD_BULK_TO_S3 Job queued', + 'message' => 'E-card re-generation process has started successfully.', + 'dataStatus' => true, 'total' => $total, 'batches' => $total_batches ], 200); diff --git a/app/Models/EmployeePolicyModel.php b/app/Models/EmployeePolicyModel.php index 0e86d94a..81f8c580 100755 --- a/app/Models/EmployeePolicyModel.php +++ b/app/Models/EmployeePolicyModel.php @@ -279,6 +279,7 @@ class EmployeePolicyModel extends Model 'client_branch.branch_code as client_branch_code', 'cp.policy_no', 'cp.policy_type_id', + 'cp.is_addon', $ecard_download_link ]) ->join('employees emp', 'employee_polices.employee_id = emp.id') diff --git a/app/Views/employee_data_list.php b/app/Views/employee_data_list.php index 3e3178b6..d4704749 100755 --- a/app/Views/employee_data_list.php +++ b/app/Views/employee_data_list.php @@ -206,6 +206,14 @@ Send E-Card Mail + + Re-Generate E-Card + + + + Re-Generate E-Card + + @@ -780,4 +788,67 @@ } + function showReGenerateConfirmation(client_policy_id, emp_code){ + + Swal.fire({ + title: "Do you want to Re-Generate Ecard for this family?", + showDenyButton: true, + showCancelButton: false, + confirmButtonText: "Yes", + denyButtonText: "No" + }).then((result) => { + + if (result.isConfirmed) { + reGenerateEcardForSingleFamily(client_policy_id, emp_code) + } + + }); + + } + + function reGenerateEcardForSingleFamily(client_policy_id, emp_code) + { + if(!client_policy_id){ + toastr.warning('Failed to re-Generate E-card', 'WARNING'); + } + if(!emp_code){ + toastr.warning('Failed to re-Generate E-card', 'WARNING'); + } + + console.log({client_policy_id, emp_code}); + + let url = ''; + + // Data to send in the AJAX request + let requestData = { + client_policy_id: client_policy_id, + emp_code: emp_code, + }; + + $('.loader').fadeIn(); + $('.loader-mask').fadeIn(); + + // Send AJAX request + sendAjaxRequestForGlobal(url, 'GET', requestData, function(response) { + + console.log('Data fetched successfully:', response); + + if (response.dataStatus == true) { + toastr.success(response.message || 'Initiating successafully.', 'SUCCESS'); + } else { + toastr.warning(response.status || 'Unable to regenerate e-card.', 'WARNING'); + } + + $('.loader').fadeOut(); + $('.loader-mask').delay(350).fadeOut('slow'); + + }, function(xhr, status, error) { + console.error('Error fetching data:', error); + console.error(xhr.responseText); + toastr.error('Unable to regenerate e-card.', 'ERROR'); + }); + + + } + From bb0ffbcf3aa2e80028a5948dab50afca2880cdb9 Mon Sep 17 00:00:00 2001 From: velz Date: Fri, 2 Jan 2026 12:41:13 +0530 Subject: [PATCH 17/17] FEAT_CHECK_ENV_SCRIPT --- .env.sample | 244 ++++++++------------------- app/Config/Routes.php | 1 + app/Controllers/MasterController.php | 76 +++++++++ 3 files changed, 146 insertions(+), 175 deletions(-) diff --git a/.env.sample b/.env.sample index b3f6111e..ebc9ab1d 100755 --- a/.env.sample +++ b/.env.sample @@ -1,27 +1,15 @@ -#-------------------------------------------------------------------- -# Example Environment Configuration file -# -# This file can be used as a starting point for your own -# custom .env files, and contains most of the possible settings -# available in a default install. -# -# By default, all of the settings are commented out. If you want -# to override the setting, you must un-comment it by removing the '#' -# at the beginning of the line. -#-------------------------------------------------------------------- - #-------------------------------------------------------------------- # ENVIRONMENT #-------------------------------------------------------------------- -# CI_ENVIRONMENT = development +CI_ENVIRONMENT = #-------------------------------------------------------------------- # APP #-------------------------------------------------------------------- -app.baseURL = 'http://localhost/client_changes/nhance/' -app.appTimezone = 'Asia/Kolkata' +app.baseURL = +app.appTimezone = # If you have trouble with `.`, you could also use `_`. # app_baseURL = '' # app.forceGlobalSecureRequests = false @@ -30,187 +18,93 @@ app.appTimezone = 'Asia/Kolkata' #-------------------------------------------------------------------- # DATABASE #-------------------------------------------------------------------- - - -# Dev DB Connection - -database.default.hostname = 119.18.54.85 -database.default.database = venbaehn_nhance -database.default.username = venbaehn_nhance_user1 -database.default.password = 'iM~X7(cR+}A-' -database.default.DBDriver = MySQLi -database.default.DBPrefix = -database.default.port = 3306 - -database.tests.hostname = 119.18.54.85 -database.tests.database = venbaehn_nhance -database.tests.username = venbaehn_nhance_user1 -database.tests.password = 'iM~X7(cR+}A-' -database.tests.DBDriver = MySQLi -database.tests.DBPrefix = -database.tests.port = 3306 - -# Test DB Connection - -# database.default.hostname = 119.18.54.85 -# database.default.database = venbaehn_nhance_test -# database.default.username = venbaehn_nhance_user1 -# database.default.password = 'iM~X7(cR+}A-' -# database.default.DBDriver = MySQLi -# database.default.DBPrefix = -# database.default.port = 3306 - -# database.tests.hostname = 119.18.54.85 -# database.tests.database = venbaehn_nhance_test -# database.tests.username = venbaehn_nhance_user1 -# database.tests.password = 'iM~X7(cR+}A-' -# database.tests.DBDriver = MySQLi -# database.tests.DBPrefix = -# database.tests.port = 3306 - -# UAT DB Connection - -# database.default.hostname = 119.18.54.85 -# database.default.database = venbaehn_nhance_uat -# database.default.username = venbaehn_nhance_user1 -# database.default.password = 'iM~X7(cR+}A-' -# database.default.DBDriver = MySQLi -# database.default.DBPrefix = -# database.default.port = 3306 - -# database.tests.hostname = 119.18.54.85 -# database.tests.database = venbaehn_nhance_uat -# database.tests.username = venbaehn_nhance_user1 -# database.tests.password = 'iM~X7(cR+}A-' -# database.tests.DBDriver = MySQLi -# database.tests.DBPrefix = -# database.tests.port = 3306 - -# Local PhpMyAdmin DB Connection - -# database.default.hostname = localhost -# database.default.database = nhance -# database.default.username = root -# database.default.password = '' -# database.default.DBDriver = MySQLi -# database.default.DBPrefix = -# database.default.port = 3306 - -# database.tests.hostname = localhost -# database.tests.database = nhance -# database.tests.username = root -# database.tests.password = '' -# database.tests.DBDriver = MySQLi -# database.tests.DBPrefix = -# database.tests.port = 3306 - -#-------------------------------------------------------------------- -# CONTENT SECURITY POLICY -#-------------------------------------------------------------------- - -# contentsecuritypolicy.reportOnly = false -# contentsecuritypolicy.defaultSrc = 'none' -# contentsecuritypolicy.scriptSrc = 'self' -# contentsecuritypolicy.styleSrc = 'self' -# contentsecuritypolicy.imageSrc = 'self' -# contentsecuritypolicy.baseURI = null -# contentsecuritypolicy.childSrc = null -# contentsecuritypolicy.connectSrc = 'self' -# contentsecuritypolicy.fontSrc = null -# contentsecuritypolicy.formAction = null -# contentsecuritypolicy.frameAncestors = null -# contentsecuritypolicy.frameSrc = null -# contentsecuritypolicy.mediaSrc = null -# contentsecuritypolicy.objectSrc = null -# contentsecuritypolicy.pluginTypes = null -# contentsecuritypolicy.reportURI = null -# contentsecuritypolicy.sandbox = false -# contentsecuritypolicy.upgradeInsecureRequests = false -# contentsecuritypolicy.styleNonceTag = '{csp-style-nonce}' -# contentsecuritypolicy.scriptNonceTag = '{csp-script-nonce}' -# contentsecuritypolicy.autoNonce = true - -#-------------------------------------------------------------------- -# COOKIE -#-------------------------------------------------------------------- - -# cookie.prefix = '' -# cookie.expires = 0 -# cookie.path = '/' -# cookie.domain = '' -# cookie.secure = false -# cookie.httponly = false -# cookie.samesite = 'Lax' -# cookie.raw = false - -#-------------------------------------------------------------------- -# ENCRYPTION -#-------------------------------------------------------------------- - -# encryption.key = -# encryption.driver = OpenSSL -# encryption.blockSize = 16 -# encryption.digest = SHA512 - -#-------------------------------------------------------------------- -# HONEYPOT -#-------------------------------------------------------------------- - -# honeypot.hidden = 'true' -# honeypot.label = 'Fill This Field' -# honeypot.name = 'honeypot' -# honeypot.template = '' -# honeypot.container = '
{template}
' - -#-------------------------------------------------------------------- -# SECURITY -#-------------------------------------------------------------------- - -# security.csrfProtection = 'cookie' -# security.tokenRandomize = false -# security.tokenName = 'csrf_token_name' -# security.headerName = 'X-CSRF-TOKEN' -# security.cookieName = 'csrf_cookie_name' -# security.expires = 7200 -# security.regenerate = true -# security.redirect = false -# security.samesite = 'Lax' +DB_SSL_ENABLE = +database.default.hostname = +database.default.database = +database.default.username = +database.default.password = +database.default.DBDriver = +#database.default.DBPrefix = +#database.default.port = #-------------------------------------------------------------------- # SESSION #-------------------------------------------------------------------- # session.driver = 'CodeIgniter\Session\Handlers\FileHandler' -session.cookieName = 'ci_session_dev' -session.expiration = 86400 +# session.cookieName = 'ci_session' +#session.expiration = 28800 # session.savePath = null # session.matchIP = false -session.timeToUpdate = 300 -session.regenerateDestroy = true +# session.timeToUpdate = 300 +# session.regenerateDestroy = false #-------------------------------------------------------------------- # LOGGER #-------------------------------------------------------------------- -# logger.threshold = 4 +logger.threshold = 4 #-------------------------------------------------------------------- # CURLRequest #-------------------------------------------------------------------- - # curlrequest.shareOptions = true +GOOGLE_OAUTH_APP_NAME = +#GOOGLE_OAUTH_CLIENT_ID = +#GOOGLE_OAUTH_CLIENT_SECRET = + +GOOGLE_OAUTH_CLIENT_ID = +GOOGLE_OAUTH_CLIENT_SECRET = +GOOGLE_OAUTH_REDIRECT_URI = +GOOGLE_OAUTH_SCOPES = +App_Url = +NHANCE_LOGO = +helpdeskURL = +TOKENTIMEOUT = +POST_ENROLLMENT_APP_LINK = +GDRIVE_ROOT_FOLDER_ID = + + +email.fromEmail = +email.fromName = +ZEPTO_API_KEY = +email.SMTPPass = + #-------------------------------------------------------------------- -# Google-OAUTH-Credentials +# SET COOKIE DATA #-------------------------------------------------------------------- +cookie.Path = '/'; +cookie.Domain = '.nhanceindia.in'; //Enter Domain Name with preceding .(dot) -> .nhanceindia.in +cookie.secure = 'true';// if https set as true or if http set as false -GOOGLE_OAUTH_APP_NAME = 'OAuth' -GOOGLE_OAUTH_CLIENT_ID = '696241936560-m2mr272ge7vr2n4q36c22l3d2gdgi90l.apps.googleusercontent.com' -GOOGLE_OAUTH_CLIENT_SECRET = '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' -GOOGLE_OAUTH_REDIRECT_URI = 'http://localhost/client_changes/nhance/oauth2callback' -GOOGLE_OAUTH_SCOPES = "https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/userinfo.profile" +unlayer.projectID = +email.enquiryMail = +database.postDB.hostname = +database.postDB.database = +database.postDB.username = +database.postDB.password = +database.postDB.DBDriver = +database.postDB.DBPrefix = +database.postDB.port = -App_Url = https://venbait.in/nhance/app/dev/ -POST_ENROLLMENT_APP_LINK = https://venbait.in/nhance/employee/dev/ -NHANCE_LOGO = https://venbait.in/nhance/dev/public/assets/images/Nhance_Favi.png \ No newline at end of file +POST_ENROLLMENT_BASEURL = + +#SMS +SMS_API_KEY = +SMS_SENDER_ID = +SMS_TEMPLATE_ID = +SMS_SERVICE_NAME = +SMS_APP_NAME = + +# CORS Configuration +CORS_ALLOWED_ORIGINS= +CORS_ALLOW_CREDENTIALS=true +CORS_ALLOWED_METHODS=GET,POST,PUT,PATCH,DELETE,OPTIONS +CORS_ALLOWED_HEADERS=Content-Type,Authorization,X-Requested-With,Accept,Origin,App-Signature +CORS_EXPOSE_HEADERS=X-Total-Count,X-Page-Count,X-RateLimit-Remaining +CORS_MAX_AGE=7200 +CORS_DEBUG=true + +APP_SIGNATURE = diff --git a/app/Config/Routes.php b/app/Config/Routes.php index c091eaf1..639a1409 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -519,6 +519,7 @@ $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/new_gdrive_token', 'GoogleDriveController::generateNewGoogleDriveAccessToken'); +$routes->cli('cli/check_env', 'MasterController::checkEnv'); //crone job $routes->cli('cli/enrollOpendAndClose', 'DashboardController::updatePolicyEnrollmentStatus'); diff --git a/app/Controllers/MasterController.php b/app/Controllers/MasterController.php index 2c243fee..79f5753b 100755 --- a/app/Controllers/MasterController.php +++ b/app/Controllers/MasterController.php @@ -41,6 +41,7 @@ use App\Models\RTOModel; use App\Models\PartnerPosModel; use CodeIgniter\CLI\CLI; +use CodeIgniter\CLI\BaseCommand; class MasterController extends AdminController { @@ -1950,6 +1951,7 @@ class MasterController extends AdminController $this->checkGoogleOAuthCredentialsinDB(); $this->getCronJobsList(); $this->checkGdriveRootFolderID(); + $this->checkEnv(); } public function checkAndCreateDirectories() @@ -2075,6 +2077,80 @@ class MasterController extends AdminController dd($result); } + + public function checkEnv() + { + $root = ROOTPATH; + + $sample_file_name = '.env.sample'; + $sample_file_path = $root . $sample_file_name; + + $envFile = $root . '.env'; + // echo ($exampleFile);//die(); + if (!file_exists($sample_file_path)) { + echo ("$sample_file_path file not found"); + exit(); + } + + if (!file_exists($envFile)) { + echo('.env file not found'); + exit(); + } + + $example = $this->parseEnv($sample_file_path); + $actual = $this->parseEnv($envFile); + + $missing = array_diff_key($example, $actual); + $extra = array_diff_key($actual, $example); + + CLI::write("#################### CHECKING ENV ##############################\n"); + if ($extra) { + CLI::write('⚠️ Extra ENV keys (not in .env.example)', 'yellow'); + foreach (array_keys($extra) as $key) { + CLI::write(" - $key", 'yellow'); + } + } + + CLI::newLine(); + if ($missing) { + CLI::error('❌ Missing ENV keys'); + foreach (array_keys($missing) as $key) { + CLI::write(" - $key", 'red'); + } + } + + CLI::newLine(); + if (!$missing && !$extra) { + CLI::write('✅ ENV configuration is clean', 'green'); + return CLI::EXIT_SUCCESS; + } + + CLI::write("#################### END OF CHECKING ENV ############################\n"); + + + } + + private function parseEnv(string $file): array + { + $lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + $env = []; + + foreach ($lines as $line) { + $line = trim($line); + + if ($line === '' || str_starts_with($line, '#')) { + continue; + } + + if (strpos($line, '=') !== false) { + [$key] = explode('=', $line, 2); + $env[trim($key)] = true; + } + } + + return $env; + } + //---------------------------------------------------------------------------------------------------------- public function nhanceBranchMaster()