diff --git a/app/Config/Acl.php b/app/Config/Acl.php index df90b2f2..b59905ff 100644 --- a/app/Config/Acl.php +++ b/app/Config/Acl.php @@ -276,7 +276,7 @@ class Acl // ===================== INTERNAL TEST ===================== '#^/test#' => [ - 'roles' => [ADMIN_ROLE_ID], + 'roles' => [ADMIN_ROLE_ID, HEAD_ROLE_ID], 'teams' => [] ], diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 2d363f2d..7ed357a6 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -887,6 +887,8 @@ $routes->get('HealthIndiaGetBenefDetails','HealthIndiaApiController::HealthIndia $routes->post("ecardRequest", "ApiServiceController::ecardRequest"); $routes->post("getTPAID", "ApiServiceController::getTPAID"); $routes->post("sendDataToTPA", "ApiServiceController::sendDataToTPA"); +$routes->get("jobStatus", "TestingController::jobStatus"); +$routes->post("jobStatus", "TestingController::jobStatus"); $routes->get('fileDownload','MediAssistApiController::fileDownload'); @@ -928,6 +930,8 @@ $routes->group('test', function($routes) { $routes->get('testingquerys','TestingController::testingquerys'); $routes->get('thzReminderCrone','ThzController::getOpenTicketsOlderThan24HoursAndAssignNextLevel'); $routes->get('chartbrewDashboardDemo','TestingController::chartbrewDashboardDemo'); + $routes->get('getVidalEnrollmentInfo','TestingController::getVidalEnrollmentInfo'); + // $routes->get('createDefaultMailTempalteInDB','TestingController::createDefaultMailTempalteInCrossDB'); // $routes->get('createDefaultMailTempalteInSameDB','TestingController::createDefaultMailTempalteInSameDB'); }); diff --git a/app/Controllers/ApiServiceController.php b/app/Controllers/ApiServiceController.php index 013aea7a..2b7c2e45 100644 --- a/app/Controllers/ApiServiceController.php +++ b/app/Controllers/ApiServiceController.php @@ -350,6 +350,15 @@ class ApiServiceController extends BaseController return $this->respond(['status' => true, 'code' => 200, 'message' => 'Action Triggered','data' => [] ]); + }else if ($tpa_id == $this->icici_primary_key) // ICICI Lombard (EWA) + { + $file_id = $fileModel->insert($data); + log_message('error', "ICICI - Files table inserted successfully, File id : {$file_id}"); + $r = Jobs::addJob(['job_name' => 'getEnrollmentBatchStatus', 'payload' => ['client_policy_id' => $policy_id, 'file_id' => $file_id, 'client_policy_id' => $policy_id, 'return_type' => 'job']]); + log_message('error', "ICICI - getEnrollmentBatchStatus job pushed successfully."); + + return $this->respond(['status' => true, 'code' => 200, 'message' => 'Action Triggered','data' => [] ]); + }else{ return $this->respond(['status' => false, 'code' => 200,'message' => 'TPA not found ','data' => [] ]); } @@ -553,7 +562,6 @@ class ApiServiceController extends BaseController ]); } - // public function getWellnessUrl() // { @@ -725,7 +733,98 @@ class ApiServiceController extends BaseController // } + public function sendDataToTPA() + { + + $requested_data = $this->request->getPost() ?? []; + log_message('error', "getTPAID payloads :" . json_encode($requested_data)); + $tpa_id = $requested_data['tpa_id'] ?? null; + $policy_no = $requested_data['policy_no'] ?? null; + $client_id = $requested_data['client_id'] ?? null; + $branch_id = $requested_data['client_branch_id'] ?? null; + $policy_id = $requested_data['client_policy_id'] ?? null; + $event = $requested_data['event'] ?? null; + + $event_mapping = [ + 'inception' => 'A', + 'missed_inception' => 'A', + 'addition' => 'A', + 'dependent_addition' => 'A', + 'deletion' => 'D', + 'correction' => 'M', + 'si_enhancement' => 'M' + ]; + + + $fileModel = new BatchFileModel(); + $filesData = $fileModel + ->join('client_policy', 'client_policy.id = batch_files.client_policy_id') + ->where('client_policy.tpa_id', $tpa_id) + ->where('batch_files.is_active', 1) + ->where('batch_files.event_type', 'api') + ->where('batch_files.icici_status_flag !=', 'COMPLETED') + ->countAllResults(); + + if($filesData > 0){ + log_message('error', "TPA initiation is in progress."); + return $this->respond(['status' => false, 'code' => 200,'message' => 'TPA initiation is in progress.','data' => [] ]); + } + + $employeePolicyModel = new EmployeePolicyModel(); + $employeePolicyData = $employeePolicyModel + ->select(' + employees.*, + employee_polices.id as emp_policy_id, + employee_polices.client_policy_id, + ') + ->join('employees', 'employees.id = employee_polices.employee_id') + ->where('employee_polices.is_active', 1) + ->where('employee_polices.status', 'active') + ->where('employees.is_active', 1) + ->where('employees.emp_status', 'active') + ->where('employee_polices.tpa_id IS NULL') + ->where('employee_polices.client_policy_id', $policy_id) + ->countAllResults(); + + if($employeePolicyData == 0){ + log_message('error', "No Employee Policy found with null TPA ID. TPA ID is already updated."); + return $this->respond(['status' => false, 'code' => 200,'message' => 'No employee to upload','data' => [] ]); + } + + $data = [ + 'file_name' => "API - Employee data push", + 'event_type' => $event, + 'actions' => "push", + 'insurer_or_tpa' => "tpa", + 'batch_code' => generate_random_string(4), + 'status' => "inprogress", + 'client_id' => $client_id, + 'client_policy_id'=> $policy_id, + 'client_branch_id'=> $branch_id, + 'created_by'=> get_session_userid(), + ]; + + if ($tpa_id == $this->icici_primary_key) // MediAssist + { + $file_id = $fileModel->insert($data); + log_message('error', "Files table inserted successfully, File id : {$file_id}"); + + $requested_data['file_id'] = $file_id; + $requested_data['return_type'] = 'job'; + $requested_data['insurer_or_tpa'] = 'tpa'; + $requested_data['flag_status'] = $event_mapping[$event] ?? "A"; + + $ICICILombardController = new ICICILombardController(); + $apiResponse = $ICICILombardController->ICICIPushEmployeeDetails($requested_data); + + // $r = Jobs::addJob(['job_name' => 'ICICIPushEmployeeDetails', 'payload' => $requested_data]); + // log_message('error', "ICICIPushEmployeeDetails job pushed successfully."); + + return $this->respond(['status' => true, 'code' => 200, 'message' => 'Action Triggered','data' => $apiResponse ]); + + } + } diff --git a/app/Controllers/ClientController.php b/app/Controllers/ClientController.php index cf931aa6..b5d1706c 100755 --- a/app/Controllers/ClientController.php +++ b/app/Controllers/ClientController.php @@ -5307,6 +5307,18 @@ class ClientController extends AdminController } $data['family_floaters']['elders_count'] = $this->request->getPost("elder_member_count") ? $this->request->getPost("elder_member_count") : 0; + + // OPD policy terms fields for policy_type_id = 72 + $data['mode_of_serviceability'] = $policy_terms['mode_of_serviceability'] ?? ''; + $data['eligibility'] = $policy_terms['eligibility'] ?? ''; + $data['total_sum_insured_limit'] = $policy_terms['total_sum_insured_limit'] ?? 'INR 15000'; + $data['in_person_doctor_consultation'] = $policy_terms['in_person_doctor_consultation'] ?? ''; + $data['prescribed_lab_test_pathology_radiology'] = $policy_terms['prescribed_lab_test_pathology_radiology'] ?? ''; + $data['prescribed_pharmacy'] = $policy_terms['prescribed_pharmacy'] ?? ''; + $data['dental'] = $policy_terms['dental'] ?? ''; + $data['vision'] = $policy_terms['vision'] ?? ''; + $data['vaccination_for_children_and_adults'] = $policy_terms['vaccination_for_children_and_adults'] ?? ''; + $data['special_condition_label'] = $policy_terms['special_condition_label'] ?? []; $data['special_condition_input'] = $policy_terms["special_condition_input"] ?? []; @@ -5364,6 +5376,7 @@ class ClientController extends AdminController $values = $data['special_condition_input'] ?? []; $special_conditions = []; + $display_fields = []; foreach ($labels as $i => $label) { $value = $values[$i] ?? ''; @@ -5376,7 +5389,39 @@ class ClientController extends AdminController $special_conditions[$label] = $value; } - return $special_conditions; + $labelMap = [ + 'mode_of_serviceability' => 'Mode Of Serviceability', + 'eligibility' => 'Eligibility', + 'total_sum_insured_limit' => 'Total Sum Insured Limit', + 'in_person_doctor_consultation' => 'In Person Doctor Consultation', + 'prescribed_lab_test_pathology_radiology' => 'Prescribed Lab Test Pathology Radiology', + 'prescribed_pharmacy' => 'Prescribed Pharmacy', + 'dental' => 'Dental', + 'vision' => 'Vision', + 'vaccination_for_children_and_adults' => 'Vaccination For Children And Adults', + ]; + + foreach ($data as $key => $value) { + if (!str_ends_with($key, '_display')) { + continue; + } + + if (empty($value)) { + continue; + } + + $baseKey = substr($key, 0, -8); + $baseValue = $data[$baseKey] ?? ''; + + if (trim((string)$baseValue) === '') { + continue; + } + + $label = $labelMap[$baseKey] ?? ucwords(str_replace('_', ' ', $baseKey)); + $display_fields[$label] = $baseValue; + } + + return array_merge($display_fields, $special_conditions); } public function checkPolicyType($policy_type_id, $client_branch_id, $client_id) diff --git a/app/Controllers/EmployeeController.php b/app/Controllers/EmployeeController.php index 8bc4d0e2..3fc7e8fe 100755 --- a/app/Controllers/EmployeeController.php +++ b/app/Controllers/EmployeeController.php @@ -2601,6 +2601,7 @@ class EmployeeController extends AdminController $employeeRest = new EmployeeRestController(); $tpa_api_service_status = $employeeRest->checkTpaApiEnable($client_policy_id, 'getTPAID', 'internel'); + $tpa_push_api_service_status = $employeeRest->checkTpaApiEnable($client_policy_id, 'sendDataToTPA', 'internel'); $slab_details = $this->policiesModel->getPolicySlabRatesForEmpOnboard($client_policy_id,$policy_details['client_id']); @@ -2620,7 +2621,7 @@ class EmployeeController extends AdminController $message = isset($message) ? ($message . ' The policy does not have a CD account number.') : null; } - return $this->respond(['dataStatus' => true, 'code' => 200, 'message' => $message, 'si_enhancement' => $si_enhancement_true_or_false, 'insurer_multi_event' => $insurer_details['is_multi_event'], 'tpa_api_service_status' => $tpa_api_service_status], 200); + return $this->respond(['dataStatus' => true, 'code' => 200, 'message' => $message, 'si_enhancement' => $si_enhancement_true_or_false, 'insurer_multi_event' => $insurer_details['is_multi_event'], 'tpa_api_service_status' => $tpa_api_service_status, 'tpa_push_api_service_status' => $tpa_push_api_service_status], 200); } @@ -4074,39 +4075,33 @@ class EmployeeController extends AdminController // d($not_in_nhance);die(); if (!empty($not_in_tpa) || !empty($not_in_nhance) || !empty($emp_data_wo_tpa_id)) { - if ($type === 'download') { + + $response = [ + 'not_in_tpa' => $not_in_tpa, + 'not_in_nhance' => $not_in_nhance, + 'mismatch_data' => $emp_data_wo_tpa_id, + ]; + + + if ($type === 'internal') { + return $response; + }else if ($type === 'download') { $this->exportVariationReportExcel($not_in_tpa, $not_in_nhance, $emp_data_wo_tpa_id); } else { - $response = [ - 'not_in_tpa' => $not_in_tpa, - 'not_in_nhance' => $not_in_nhance, - 'mismatch_data' => $emp_data_wo_tpa_id, - ]; - - return $this->respond( - [ - 'status' => true, - 'code' => 200, - 'message' => '', - 'data' => $response, - ], - 200 - ); + return $this->respond(['status' => true,'code' => 200,'message' => '','data' => $response,],200); } + } else { + + if ($type === 'internal') { + return []; + } + if ($type === 'download') { return false; } - return $this->respond( - [ - 'status' => false, - 'code' => 202, - 'message' => 'No data found', - 'data' => [], - ], - 200 - ); + return $this->respond(['status' => false,'code' => 202,'message' => 'No data found','data' => [],],200); } } @@ -4161,14 +4156,15 @@ class EmployeeController extends AdminController } elseif ($tab === 'need_to_review') { // For the "Need to Review" tab, generate a Correction Excel // using the same overall pipeline as the Not in Nhance implementation. - $generationResult = $this->generateCorrectionUploadFromNeedToReview((int) $file_id, $file); + // $generationResult = $this->generateCorrectionUploadFromNeedToReview((int) $file_id, $file); + $generationResult = $this->updateEmployeeDataFromTpa([$file_id]); if (!$generationResult['status']) { return $this->respond( [ 'status' => false, 'code' => 422, - 'message' => $generationResult['message'] ?? 'Unable to generate correction upload file from Need to Review data.', + 'message' => $generationResult['message'] ?? 'Unable to process the data from Need to Review tab.', 'data' => $generationResult['data'] ?? [], ], 200 @@ -4178,12 +4174,13 @@ class EmployeeController extends AdminController $this->myLogger->logme( 'error', - 'TPA variation review completed and proceed to next clicked', - [ - 'file_id' => $file_id, - 'user_id' => get_session_userid(), - 'tab' => $tab, - ] + 'TPA variation review completed and proceed to next clicked' . json_encode( + [ + 'file_id' => $file_id, + 'user_id' => get_session_userid(), + 'tab' => $tab, + ] + ) ); return $this->respond( @@ -4193,7 +4190,7 @@ class EmployeeController extends AdminController 'message' => $tab === 'not_in_nhance' ? 'Employee upload file generated from Not in Nhance data and queued for processing.' : ($tab === 'need_to_review' - ? 'Correction upload file generated from Need to Review data and queued for processing.' + ? 'Review data update successfully.' : 'Proceed to next step recorded successfully.'), 'data' => [], ], @@ -4246,13 +4243,7 @@ class EmployeeController extends AdminController $TpaApiDataModel = new TpaApiDataModel(); // Get master emp codes from Nhance for this client & policy - $masterEmpRows = $this->employeePolicyModel->getTPADataVariationReport( - $clientId, - $clientPolicyId, - $batchFileId, - [], - true - ); + $masterEmpRows = $this->employeePolicyModel->getTPADataVariationReport($clientId,$clientPolicyId,$batchFileId,[],true); if (!is_array($masterEmpRows)) { $masterEmpRows = []; } @@ -4450,7 +4441,7 @@ class EmployeeController extends AdminController // Run the same format validation used for manual uploads. - $validationResult = $empServiceController->excelFileFormatValidation(['file_id' => $newFileId]); + $validationResult = $empServiceController->excelFileFormatValidation(['file_id' => $newFileId, 'batch_file_id' => $batchFileId]); if (isset($validationResult['error_summary']) && count($validationResult['error_summary'])) { return [ @@ -4465,6 +4456,7 @@ class EmployeeController extends AdminController 'message' => 'Employee upload file generated from Not in Nhance data and queued for processing.', 'data' => ['file_id' => $newFileId], ]; + } catch (\Throwable $e) { $this->myLogger->logme( 'error', @@ -4763,6 +4755,352 @@ class EmployeeController extends AdminController } } + /** + * Apply TPA values to `employees` for rows in the same "Need to Review" set as + * {@see generateCorrectionUploadFromNeedToReview}: same `getTPADataVariationReport` slice, + * same `reconcileDbWithTpa` matching, then persist mismatched fields from TPA instead of + * generating a correction Excel. + * + * Updatable fields mirror the correction Excel allow-list where they exist on TPA rows: + * `name`, `dob`, `gender`, `relationship` (from TPA `relation`), `email_corporate` (if present on TPA). + * Note: {@see reconcileDbWithTpa} only pairs rows when DB `relationship` matches TPA `relation`, + * so `relationship` rarely appears in `not_matching`; name/dob/gender are the usual diffs. + * + * @param array $params Expects `batch_file_id` (int, required). + * + * @return array{success:bool,message:string,data:array} + */ + public function updateEmployeeDataFromTpa(array $params) + { + try { + + $batchFileId = (int) ($params['batch_file_id'] ?? 0); + + if ($batchFileId <= 0) { + return [ + 'success' => false, + 'message' => 'batch_file_id is required and must be a positive integer.', + 'data' => [], + ]; + } + + $batchFile = $this->batchFileModel->find($batchFileId); + + if (!$batchFile) { + return [ + 'success' => false, + 'message' => 'Batch file not found.', + 'data' => ['batch_file_id' => $batchFileId], + ]; + } + + $clientId = (int) ($batchFile['client_id'] ?? 0); + $clientPolicyId = (int) ($batchFile['client_policy_id'] ?? 0); + $clientBranchId = (int) ($batchFile['client_branch_id'] ?? 0); + + if (!$clientId || !$clientPolicyId || !$clientBranchId) { + return [ + 'success' => false, + 'message' => 'Incomplete batch file information. Client / policy / branch missing.', + 'data' => [], + ]; + } + + $TpaApiDataModel = new TpaApiDataModel(); + + $dbRows = $this->employeePolicyModel->getTPADataVariationReport( + $clientId, + $clientPolicyId, + $batchFileId + ); + + if (!is_array($dbRows) || $dbRows === []) { + return [ + 'success' => false, + 'message' => 'No employee data found for this TPA variation batch.', + 'data' => [], + ]; + } + + $allowedFields = ['name', 'dob', 'relationship', 'email_corporate', 'gender']; + + $employeeModel = new EmployeeModel(); + $employeesUpdated = 0; + $rowsSkippedNoDiff = 0; + $rowsSkippedNoEmployee = 0; + + foreach ($dbRows as $dbRow) { + $tpaRows = $TpaApiDataModel->select('*') + ->where('emp_code', $dbRow['emp_code'] ?? '') + ->where('file_id', $batchFileId) + ->where('is_active', 1) + ->findAll(); + + if ($tpaRows === []) { + continue; + } + + $match = $this->reconcileDbWithTpa($dbRow, $tpaRows); + + if (($match['status'] ?? '') !== 'matched') { + continue; + } + + $tpaRecord = $match['tpa_record'] ?? []; + $notMatching = $match['not_matching'] ?? []; + + if (!is_array($notMatching) || $notMatching === []) { + $rowsSkippedNoDiff++; + continue; + } + + $employeeId = (int) ($dbRow['employee_id'] ?? 0); + + if ($employeeId <= 0) { + $rowsSkippedNoEmployee++; + continue; + } + + $employeeRow = $employeeModel->find($employeeId); + + if ( + !$employeeRow + || (int) ($employeeRow['client_id'] ?? 0) !== $clientId + ) { + $rowsSkippedNoEmployee++; + continue; + } + + $updateData = []; + + foreach ($notMatching as $field) { + if (!in_array($field, $allowedFields, true)) { + continue; + } + + if ($field === 'relationship') { + $val = $tpaRecord['relation'] ?? null; + if ($val !== null && $val !== '') { + $updateData['relationship'] = $val; + } + continue; + } + + if ($field === 'email_corporate') { + $val = $tpaRecord['email_corporate'] ?? $tpaRecord['email'] ?? null; + if ($val !== null && $val !== '') { + $updateData['email_corporate'] = $val; + } + continue; + } + + $val = $tpaRecord[$field] ?? null; + if ($val !== null && $val !== '') { + $updateData[$field] = $val; + } + } + + if ($updateData === []) { + continue; + } + + if ($employeeModel->update($employeeId, $updateData)) { + $employeesUpdated++; + } + } + + if ($employeesUpdated === 0) { + $this->myLogger->logme( + 'error', + 'updateEmployeeDataFromTpa: zero employee rows updated', + [ + 'batch_file_id' => $batchFileId, + 'rows_skipped_no_diff' => $rowsSkippedNoDiff, + 'rows_skipped_no_employee' => $rowsSkippedNoEmployee, + ] + ); + } + + return [ + 'success' => true, + 'message' => 'TPA-aligned employee updates applied where mismatches were reconciled.', + 'data' => [ + 'batch_file_id' => $batchFileId, + 'employees_updated' => $employeesUpdated, + 'rows_skipped_no_diff' => $rowsSkippedNoDiff, + 'rows_skipped_no_employee' => $rowsSkippedNoEmployee, + ], + ]; + } catch (\Throwable $e) { + $this->myLogger->logme( + 'error', + 'updateEmployeeDataFromTpa failed: ' . json_encode([ + 'message' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + ], JSON_PRETTY_PRINT) + ); + + return [ + 'success' => false, + 'message' => 'Unable to process the data from Need to Review tab.', + 'data' => [], + ]; + } + } + + + /** + * @param array $params batch_file_id (required), file_id (optional, >0 filters employee_polices.file_id) + * @param mixed $jobId Optional queue job id when invoked from JobWorker (ignored). + * + * @return array{success:bool,message:string,data:array} + */ + public function updateTpaIdForNotInNhance($params, $jobId = null): array + { + try { + if (!is_array($params)) { + return [ + 'success' => false, + 'message' => 'Invalid parameters.', + 'data' => [], + ]; + } + + $TpaApiDataModel = new TpaApiDataModel(); + + $fileId = (int) ($params['file_id'] ?? 0); + $batchFileId = (int) ($params['batch_file_id'] ?? 0); + + if ($batchFileId <= 0) { + $this->myLogger->logme('error', 'Batch file ID missing in updateTpaIdForNotInNhance', ['params' => $params]); + + return [ + 'success' => false, + 'message' => 'Batch file ID is required.', + 'data' => [], + ]; + } + + $batchFileData = db_connect()->table('batch_files')->where('id', $batchFileId)->get()->getRowArray(); + + if (empty($batchFileData) || empty($batchFileData['client_policy_id'])) { + $this->myLogger->logme('error', 'Batch file not found or missing client_policy_id in updateTpaIdForNotInNhance', ['batch_file_id' => $batchFileId]); + + return [ + 'success' => false, + 'message' => 'Batch file not found or missing client policy.', + 'data' => [], + ]; + } + + $client_policy_data = $this->clientPolicyModel->where('id', $batchFileData['client_policy_id'])->first(); + + if (empty($client_policy_data)) { + $this->myLogger->logme('error', 'Client policy not found in updateTpaIdForNotInNhance', ['client_policy_id' => $batchFileData['client_policy_id']]); + + return [ + 'success' => false, + 'message' => 'Client policy not found.', + 'data' => [], + ]; + } + + // Get master emp codes from Nhance for this client & policy + $masterEmpRows = $this->employeePolicyModel->getTPADataVariationReport( + $batchFileData['client_id'], + $batchFileData['client_policy_id'], + $batchFileId, + [], + true + ); + if (!is_array($masterEmpRows)) { + $masterEmpRows = []; + } + $masterEmpCodes = array_values(array_filter( + array_unique(array_column($masterEmpRows, 'emp_code')), + static fn ($code) => $code !== null && $code !== '' + )); + + // Fetch Not in Nhance rows for this batch file + $notInNhanceQuery = $TpaApiDataModel->select('*') + ->where('is_active', 1) + ->where('file_id', $batchFileId); + + if ($masterEmpCodes !== []) { + $notInNhanceQuery->whereNotIn('emp_code', $masterEmpCodes); + } + + $notInNhance = $notInNhanceQuery->findAll(); + + $uhidValue = $client_policy_data['policy_no'] ?? null; + + $empPolicyIds = []; + foreach ($notInNhance as $tpaRow) { + $builder = $this->employeePolicyModel + ->select('employee_polices.id') + ->join('employees e', 'e.id = employee_polices.employee_id') + ->where('e.name', $tpaRow['name'] ?? '') + ->where('e.emp_code', $tpaRow['emp_code'] ?? '') + ->where('e.dob', $tpaRow['dob'] ?? null) + ->where('e.relationship', $tpaRow['relation'] ?? null) + ->where('e.gender', $tpaRow['gender'] ?? null) + ->where('employee_polices.client_policy_id', (int) $batchFileData['client_policy_id']) + ->where('e.client_id', (int) $batchFileData['client_id']); + + if ($fileId > 0) { + $builder->where('employee_polices.file_id', $fileId); + } + + $empPolicyRow = $builder->first(); + + if (empty($empPolicyRow['id'])) { + continue; + } + + $epId = (int) $empPolicyRow['id']; + if ($this->employeePolicyModel->update($epId, [ + 'tpa_id' => $tpaRow['tpa_id'] ?? null, + 'uhid' => $uhidValue, + ])) { + $empPolicyIds[] = $epId; + } + } + + if ($empPolicyIds === []) { + $this->myLogger->logme( + 'warning', + 'updateTpaIdForNotInNhance: zero employee_policy rows updated', + [ + 'batch_file_id' => $batchFileId, + 'not_in_nhance_count' => count($notInNhance), + ] + ); + } + + return [ + 'success' => true, + 'message' => 'TPA id / UHID applied on matching employee policies for Not in Nhance rows.', + 'data' => [ + 'employee_policies_updated' => count($empPolicyIds), + 'employee_policy_ids' => $empPolicyIds, + ], + ]; + } catch (\Throwable $e) { + $this->myLogger->logme( + 'error', + 'updateTpaIdForNotInNhance exception: ' . $e->getMessage(), + ['params' => $params, 'trace' => $e->getTraceAsString()] + ); + + return [ + 'success' => false, + 'message' => 'Unexpected error while updating TPA id from Not in Nhance data.', + 'data' => [], + ]; + } + } + // not in use once all functionality workes well in this funciton then remvoe this function function compareDbWithTpa(array $db, array $tpaRows): array diff --git a/app/Controllers/EmployeeServiceController.php b/app/Controllers/EmployeeServiceController.php index d6fa858f..0864c3c2 100755 --- a/app/Controllers/EmployeeServiceController.php +++ b/app/Controllers/EmployeeServiceController.php @@ -784,6 +784,8 @@ class EmployeeServiceController extends AdminController //get file name // check_dob_diff('4-APr-1990');die(); $file_id = $params['file_id']; + $batch_file_id = $params['batch_file_id'] ?? null; + $file = $this->fileModel->find((int)$file_id); // dd($file); $return = []; @@ -1063,7 +1065,7 @@ class EmployeeServiceController extends AdminController //proceed next data level validation in JOB queue $job_details = new Jobs(); - $r = Jobs::addJob(['job_name' => 'excelFileDataValidation','payload' => ['file_id' => $file_id]]); + $r = Jobs::addJob(['job_name' => 'excelFileDataValidation','payload' => ['file_id' => $file_id, 'batch_file_id' => $batch_file_id]]); // $jobWorker = new JobWorker(); // JobWorker::processJob($r); @@ -1077,6 +1079,8 @@ class EmployeeServiceController extends AdminController helper('excel_util_helper'); //get file name $file_id = $params['file_id']; + $batch_file_id = $params['batch_file_id'] ?? null; + $file = $this->fileModel->find((int)$file_id); // dd($file); $return = []; @@ -1307,13 +1311,13 @@ class EmployeeServiceController extends AdminController //proceed next data level validation in JOB queue $job_details = new Jobs(); - $r = Jobs::addJob(['job_name' => 'employeesCorrectionProcess','payload' => ['file_id' => $file_id]]); + $r = Jobs::addJob(['job_name' => 'employeesCorrectionProcess','payload' => ['file_id' => $file_id, 'batch_file_id' => $batch_file_id]]); } else if ($file['action'] == 'inception' || $file['action'] == 'missed_inception' || $file['action'] == 'addition' || $file['action'] == 'dependent_addition')//inception OR addition OR dependent addition { //proceed next data level validation in JOB queue // $job_details = new Jobs(); - $r = Jobs::addJob(['job_name' => 'employeesOnboardPreprocess','payload' => ['file_id' => $file_id]]); + $r = Jobs::addJob(['job_name' => 'employeesOnboardPreprocess','payload' => ['file_id' => $file_id, 'batch_file_id' => $batch_file_id]]); // $jobWorker = new JobWorker(); // JobWorker::processJob($r); } @@ -1333,166 +1337,183 @@ class EmployeeServiceController extends AdminController { helper('excel_util_helper'); // dd($params); - if(isset($params['file_id']))//handle data from excel to inception + if (isset($params['file_id'])) //handle data from excel to inception { - //get file name - $file_id = $params['file_id']; - $file = $this->fileModel->find((int)$file_id); - // dd($file); - $return = []; - if(!isset($file)) - { - //file not found in DB - return array('status' => false, 'msg' => 'file not found in DB'); - } - $file_name_with_path = WRITEPATH."/uploads/excel/".$file['file_name']; - - //check physical file - if(!file_exists($file_name_with_path)) - { - //file not found update status and reason - $message = "Physical file not found"; - // echo $message; - $this->myLogger->logme('error',($message . ' for file id ' . $file_id)); - $this->fileModel->where('id', $file_id)->set(['status' => 'failed','reason' => json_encode(['error_summary' => array_count_values([5]),'error_data' => $message])])->update(); - return array('error_summary' => [5], 'error_data' => $message); - } + //get file name + $file_id = $params['file_id']; + $file = $this->fileModel->find((int)$file_id); + // dd($file); + $return = []; + if (!isset($file)) { + //file not found in DB + return array('status' => false, 'msg' => 'file not found in DB'); + } + $file_name_with_path = WRITEPATH . "/uploads/excel/" . $file['file_name']; - $columns_to_check = []; - if($file['action'] == 'inception'){ $columns_to_check = $this->inception_excel_columns; } - if($file['action'] == 'addition'){ $columns_to_check = $this->inception_excel_columns; } - if($file['action'] == 'dependent_addition'){ $columns_to_check = $this->inception_excel_columns; } - if($file['action'] == 'deletion'){ $columns_to_check = $this->deletion_excel_columns; } - if($file['action'] == 'correction'){ $columns_to_check = $this->correction_excel_columns; } - if($file['action'] == 'si_enhancement'){ $columns_to_check = $this->si_enhance_excel_columns; } - if($file['action'] == 'missed_inception'){ $columns_to_check = $this->inception_excel_columns; } + //check physical file + if (!file_exists($file_name_with_path)) { + //file not found update status and reason + $message = "Physical file not found"; + // echo $message; + $this->myLogger->logme('error', ($message . ' for file id ' . $file_id)); + $this->fileModel->where('id', $file_id)->set(['status' => 'failed', 'reason' => json_encode(['error_summary' => array_count_values([5]), 'error_data' => $message])])->update(); + return array('error_summary' => [5], 'error_data' => $message); + } - $current_column_action = null; - if($file['action'] == 'inception'){ $current_column_action = 'I'; } - else if($file['action'] == 'addition'){ $current_column_action = 'A'; } - else if($file['action'] == 'dependent_addition'){ $current_column_action = 'DA'; } - else if($file['action'] == 'deletion'){ $current_column_action = 'D'; } - else if($file['action'] == 'correction'){ $current_column_action = 'C'; } - else if($file['action'] == 'si_enhancement'){ $current_column_action = 'SI'; } - else if($file['action'] == 'enrollment'){ $current_column_action = 'I'; } - else if($file['action'] == 'missed_inception'){ $current_column_action = 'MI'; } + $columns_to_check = []; + if ($file['action'] == 'inception') { + $columns_to_check = $this->inception_excel_columns; + } + if ($file['action'] == 'addition') { + $columns_to_check = $this->inception_excel_columns; + } + if ($file['action'] == 'dependent_addition') { + $columns_to_check = $this->inception_excel_columns; + } + if ($file['action'] == 'deletion') { + $columns_to_check = $this->deletion_excel_columns; + } + if ($file['action'] == 'correction') { + $columns_to_check = $this->correction_excel_columns; + } + if ($file['action'] == 'si_enhancement') { + $columns_to_check = $this->si_enhance_excel_columns; + } + if ($file['action'] == 'missed_inception') { + $columns_to_check = $this->inception_excel_columns; + } - // get policy and rack details - $policy_terms = $this->clientPolicyModel->getPolicyDetails($file['client_id'],$file['policy_id']); - $policy_terms = (array) $policy_terms[0];// convert obj to array - // $policy_terms = json_decode($policy_terms[0]->policy_terms); - - // dd($policy_terms); - //get excel data - $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file_name_with_path); - $sheet = $spreadsheet->getActiveSheet(); - - $highestRowAndColumn = $sheet->getHighestRowAndColumn(); - $allowedHighestColumn = end($columns_to_check); - // dd($allowedHighestColumn); - $excel_data = $sheet->rangeToArray('A1:' . $allowedHighestColumn['col_cell_name'] . $highestRowAndColumn['row']); - unset($excel_data[0]); + $current_column_action = null; + if ($file['action'] == 'inception') { + $current_column_action = 'I'; + } else if ($file['action'] == 'addition') { + $current_column_action = 'A'; + } else if ($file['action'] == 'dependent_addition') { + $current_column_action = 'DA'; + } else if ($file['action'] == 'deletion') { + $current_column_action = 'D'; + } else if ($file['action'] == 'correction') { + $current_column_action = 'C'; + } else if ($file['action'] == 'si_enhancement') { + $current_column_action = 'SI'; + } else if ($file['action'] == 'enrollment') { + $current_column_action = 'I'; + } else if ($file['action'] == 'missed_inception') { + $current_column_action = 'MI'; + } + // get policy and rack details + $policy_terms = $this->clientPolicyModel->getPolicyDetails($file['client_id'], $file['policy_id']); + $policy_terms = (array) $policy_terms[0]; // convert obj to array + // $policy_terms = json_decode($policy_terms[0]->policy_terms); - //get policy slab rates - $slab_details = $this->policiesModel->getPolicySlabRatesForEmpOnboard($file['policy_id'],$file['client_id']); - // dd($slab_details); - //get existing units in the current branch - $existing_units = $this->clientBranchModel->getExisitingUnits(client_id: $file['client_id'],client_branch_id: $file['client_branch_id']); + // dd($policy_terms); + //get excel data + $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file_name_with_path); + $sheet = $spreadsheet->getActiveSheet(); - $employee_data_group_by_family = data_group_by_family($excel_data, 'excel', '', $current_column_action); - // dd($employee_data_group_by_family); + $highestRowAndColumn = $sheet->getHighestRowAndColumn(); + $allowedHighestColumn = end($columns_to_check); + // dd($allowedHighestColumn); + $excel_data = $sheet->rangeToArray('A1:' . $allowedHighestColumn['col_cell_name'] . $highestRowAndColumn['row']); + unset($excel_data[0]); + // dd($excel_data); - $employee_insert_count = 0; - foreach ($employee_data_group_by_family as $emp_id => $family) - { + //get policy slab rates + $slab_details = $this->policiesModel->getPolicySlabRatesForEmpOnboard($file['policy_id'], $file['client_id']); + // dd($slab_details); + //get existing units in the current branch + $existing_units = $this->clientBranchModel->getExisitingUnits(client_id: $file['client_id'], client_branch_id: $file['client_branch_id']); - //if action is DA then get all familiy members,transfrom them into excel array, addd data source as db or excel - if($file['action'] == 'dependent_addition') - { - $existing_famility_details = $this->employeeModel->getEmpFamilybyEmpCode(emp_code: $emp_id,client_id: $file['client_id'],client_policy_id: $file ['policy_id'],emp_status: ['active'],policy_status:['active'],client_branch_id: [ $file['client_branch_id'] ]); - // dd($existing_famility_details); - //transsform familiy details from db columns to exxcel row with column indexs for checking remaining functionalitites - $existing_famility_details = transform_db_data_to_excel($existing_famility_details,$file); - // Kint::dump($existing_famility_details); - $family = array_merge($family,$existing_famility_details); - $family = data_group_by_family($family, 'excel', 1)[ $emp_id ];// reason to call this again is bring self to first index of the array - // dd($family); - $self = current(array_filter($family, fn($r) => strtolower($r[5] ?? '') === 'self')); - $premium = (int)($self['temp']['rata_premimum'] ?? 0); - foreach ($family as &$r) if (strtolower($r[5] ?? '') !== 'self') $r['self_rata_premium'] = $premium; - } + $employee_data_group_by_family = data_group_by_family($excel_data, 'excel', '', $current_column_action); + // dd($employee_data_group_by_family); - // Kint::dump($family); - $data = calculate_premium_new(family_data:$family,policy_terms: $policy_terms,slab_details : $slab_details,fileArr: $file, existing_units:$existing_units); - // dd($data); - $employee_data_group_by_family[$emp_id] = $data; - $res = $this->employeesOnboardProcess(['familiy_data' => $data,'file' => $file]); + $employee_insert_count = 0; + foreach ($employee_data_group_by_family as $emp_id => $family) { - if($res > 0){ - $employee_insert_count++; - } - } + //if action is DA then get all familiy members,transfrom them into excel array, addd data source as db or excel + if ($file['action'] == 'dependent_addition') { + $existing_famility_details = $this->employeeModel->getEmpFamilybyEmpCode(emp_code: $emp_id, client_id: $file['client_id'], client_policy_id: $file['policy_id'], emp_status: ['active'], policy_status: ['active'], client_branch_id: [$file['client_branch_id']]); + // dd($existing_famility_details); + //transsform familiy details from db columns to exxcel row with column indexs for checking remaining functionalitites + $existing_famility_details = transform_db_data_to_excel($existing_famility_details, $file); + // Kint::dump($existing_famility_details); + $family = array_merge($family, $existing_famility_details); + $family = data_group_by_family($family, 'excel', 1)[$emp_id]; // reason to call this again is bring self to first index of the array + // dd($family); + $self = current(array_filter($family, fn($r) => strtolower($r[5] ?? '') === 'self')); + $premium = (int)($self['temp']['rata_premimum'] ?? 0); + foreach ($family as &$r) if (strtolower($r[5] ?? '') !== 'self') $r['self_rata_premium'] = $premium; + } - if($employee_insert_count > 0){ - $this->fileModel->where('id', $file_id)->set(['status' => 'success','reason' => ''])->update(); - $this->myLogger->logme("error",'{file_id} uploaded success',['file_id' => $file_id]); - }else{ - $reason = json_encode([ - 'error_summary' => [5 => 1], - 'error_data' => "Rack rate configuration issue: Please check the slab rates configuration" - ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); - $this->fileModel->where('id', $file_id)->set(['status' => 'failed','reason' => $reason])->update(); - $this->myLogger->logme("error",'{file_id} uploaded failed with reason: Rack rate configuration issue: Please check the slab rates configuration',['file_id' => $file_id]); + // Kint::dump($family); + $data = calculate_premium_new(family_data: $family, policy_terms: $policy_terms, slab_details: $slab_details, fileArr: $file, existing_units: $existing_units); + // dd($data); + $employee_data_group_by_family[$emp_id] = $data; + // $res = $this->employeesOnboardProcess(['familiy_data' => $data, 'file' => $file]); - } + // if ($res > 0) { + // $employee_insert_count++; + // } + } - $this->setPullNotification($this->getFileMetaDataByFileId($file_id,'success')); + // if ($employee_insert_count > 0) { + // $this->fileModel->where('id', $file_id)->set(['status' => 'success', 'reason' => ''])->update(); + // $this->myLogger->logme("error", '{file_id} uploaded success', ['file_id' => $file_id]); + // } else { + // $reason = json_encode([ + // 'error_summary' => [5 => 1], + // 'error_data' => "Rack rate configuration issue: Please check the slab rates configuration" + // ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + // $this->fileModel->where('id', $file_id)->set(['status' => 'failed', 'reason' => $reason])->update(); + // $this->myLogger->logme("error", '{file_id} uploaded failed with reason: Rack rate configuration issue: Please check the slab rates configuration', ['file_id' => $file_id]); + // } - - } - else if(isset($params['client_policy_id']))//handle data from enrollment to inception - { + // $this->setPullNotification($this->getFileMetaDataByFileId($file_id, 'success')); + } else if (isset($params['client_policy_id'])) //handle data from enrollment to inception + { $client_policy_id = $params['client_policy_id']; //get client id $client_id = ($this->clientPolicyModel->select('client_id')->find((int)$client_policy_id))['client_id']; // dd($client_id); // get policy and rack details - $policy_terms = $this->clientPolicyModel->getPolicyDetails($client_id,$client_policy_id); - $policy_terms = (array) $policy_terms[0];// convert obj to array + $policy_terms = $this->clientPolicyModel->getPolicyDetails($client_id, $client_policy_id); + $policy_terms = (array) $policy_terms[0]; // convert obj to array //get policy slab rates - $slab_details = $this->policiesModel->getPolicySlabRatesForEmpOnboard($client_policy_id,$client_id); + $slab_details = $this->policiesModel->getPolicySlabRatesForEmpOnboard($client_policy_id, $client_id); - $existing_famility_details = $this->employeeModel->getEmpFamilybyEmpCode(client_id: $client_id,client_policy_id: $client_policy_id,emp_status: ['enrolled'],policy_status:['enrolled']); + $existing_famility_details = $this->employeeModel->getEmpFamilybyEmpCode(client_id: $client_id, client_policy_id: $client_policy_id, emp_status: ['enrolled'], policy_status: ['enrolled']); // $file = ['id' => null,'client_id' => $client_id,'policy_id' => $client_policy_id,'action' => 'inception']; - $file = ['id' => null,'client_id' => $client_id,'policy_id' => $client_policy_id,'action' => 'inception','created_by' => get_session_userid(),'client_branch_id' => $params['client_branch_id']]; + $file = ['id' => null, 'client_id' => $client_id, 'policy_id' => $client_policy_id, 'action' => 'inception', 'created_by' => get_session_userid(), 'client_branch_id' => $params['client_branch_id']]; //get existing units in the current branch - $existing_units = $this->clientBranchModel->getExisitingUnits(client_id: $file['client_id'],client_branch_id: $file['client_branch_id']); + $existing_units = $this->clientBranchModel->getExisitingUnits(client_id: $file['client_id'], client_branch_id: $file['client_branch_id']); // dd($this->employeeModel->getLastQuery()); // Kint::dump($existing_famility_details);die(); - $employee_data_group_by_family = data_group_by_family($existing_famility_details,$data_source = 'db'); - // dd($employee_data_group_by_family); - foreach ($employee_data_group_by_family as $emp_id => $family) - { + $employee_data_group_by_family = data_group_by_family($existing_famility_details, $data_source = 'db'); + // dd($employee_data_group_by_family); + foreach ($employee_data_group_by_family as $emp_id => $family) { $transformed_famility_details = transform_db_data_to_excel($family); - // $data = calculate_premium_new($transformed_famility_details,$policy_terms,$slab_details,$file); - $data = calculate_premium_new(family_data:$transformed_famility_details,policy_terms: $policy_terms,slab_details : $slab_details,fileArr: $file, existing_units:$existing_units); - // dd($data); - $employee_data_group_by_family[$emp_id] = $data; - $this->employeesOnboardProcess(['familiy_data' => $data,'file' => $file]); - } + // $data = calculate_premium_new($transformed_famility_details,$policy_terms,$slab_details,$file); + $data = calculate_premium_new(family_data: $transformed_famility_details, policy_terms: $policy_terms, slab_details: $slab_details, fileArr: $file, existing_units: $existing_units); + // dd($data); + $employee_data_group_by_family[$emp_id] = $data; + $this->employeesOnboardProcess(['familiy_data' => $data, 'file' => $file]); + } - // dd($employee_data_group_by_family); - } + // dd($employee_data_group_by_family); + } + if(count($employee_data_group_by_family ?? []) && isset($params['batch_file_id'])){ + $r = Jobs::addJob(['job_name' => 'updateEmployeeDataFromTpa','payload' => ['file_id' => $file_id, 'batch_file_id' => $params['batch_file_id']]]); + $this->myLogger->logme("info", 'Batch file id {batch_file_id} processed successfully', ['batch_file_id' => $params['batch_file_id']]); + } // die(); return (count($employee_data_group_by_family)); - } //deletion of emp @@ -1652,6 +1673,7 @@ class EmployeeServiceController extends AdminController helper('excel_util_helper'); //get file name $file_id = $params['file_id']; + $batch_file_id = $params['batch_file_id'] ?? null; $file = $this->fileModel->find((int)$file_id); // dd($file); @@ -1718,6 +1740,12 @@ class EmployeeServiceController extends AdminController } + + if(!empty($batch_file_id)){ + $r = Jobs::addJob(['job_name' => 'updateEmployeeDataFromTpa','payload' => ['file_id' => $file_id, 'batch_file_id' => $batch_file_id]]); + $this->myLogger->logme("error", 'Batch file id {batch_file_id} processed successfully', ['batch_file_id' => $batch_file_id]); + } + $this->fileModel->where('id', $file_id)->set(['status' => 'success','reason' => ''])->update(); $this->myLogger->logme("error",'{file_id} uploaded success',['file_id' => $file_id]); //set success msg to pull notifications diff --git a/app/Controllers/ICICILombardController.php b/app/Controllers/ICICILombardController.php index 5b1ed258..92b6c594 100644 --- a/app/Controllers/ICICILombardController.php +++ b/app/Controllers/ICICILombardController.php @@ -6,6 +6,8 @@ use CodeIgniter\Controller; use Kint; use Ramsey\Uuid\Uuid; use App\Models\BatchFileModel; +use App\Models\EmployeePolicyModel; +use App\Models\TpaApiDataModel; class ICICILombardController extends AdminController @@ -17,12 +19,15 @@ class ICICILombardController extends AdminController * @param string|null $overrideImid If provided, uses this value instead of icici_batch_id. * @return array {new_status, updatedCount, response} */ - private function fetchUhidAndUpdateEmployeePolicies(array $batch, ?string $overrideImid = null): array + private function fetchUhidAndUpdateEmployeePolicies(array $batch, ?string $overrideImid = null, $file_id = null): array { helper('api'); + log_message('error', 'ICICI - fetchUhidAndUpdateEmployeePolicies started for batch: ' . json_encode($batch, JSON_PRETTY_PRINT)); + $tokenResponse = $this->generateAuthToken('esbgpauhid'); if (!$tokenResponse || empty($tokenResponse['data']['access_token'])) { + log_message('error', 'ICICI - Token generation failed for UHID fetch: ' . json_encode($tokenResponse, JSON_PRETTY_PRINT)); return [ 'new_status' => 'FAILED', 'updatedCount' => 0, @@ -31,6 +36,7 @@ class ICICILombardController extends AdminController ]; } $token = $tokenResponse['data']['access_token']; + log_message('error', 'ICICI - Token generated for UHID fetch.'); $url = env('ICICI_BASE_URL') . '/fetchuhid'; $headers = [ @@ -49,12 +55,16 @@ class ICICILombardController extends AdminController mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), - mt_rand(0, 0xffff), + mt_rand(0, 0xffff) ); + log_message('error', 'ICICI - Using CorrelationId: ' . $correlationId); + $imid = $overrideImid ?: ($batch['icici_batch_id'] ?? null); + log_message('error', 'ICICI - Using IMID: ' . var_export($imid, true) . ' (overrideImid: ' . var_export($overrideImid, true) . ')'); if (empty($imid) || empty($batch['icici_endorsement_policy_no'])) { + log_message('error', 'ICICI - IMID or endorsement PolicyNumber missing for UHID fetch. IMID: ' . var_export($imid, true) . ', endorsementPolicyNo: ' . var_export($batch['icici_endorsement_policy_no'] ?? null, true)); return [ 'new_status' => 'FAILED', 'updatedCount' => 0, @@ -65,30 +75,51 @@ class ICICILombardController extends AdminController $body = [ 'PolicyNumber' => $batch['icici_endorsement_policy_no'], - 'IMID' => $imid, + 'IMID' => $imid, 'CorrelationId' => $correlationId, ]; + log_message('error', 'ICICI - Calling fetchuhid API. URL: ' . $url . ' Request: ' . json_encode($body, JSON_PRETTY_PRINT)); $response = call_third_party_api($url, 'POST', $headers, $body, true); + log_message('error', 'ICICI - fetchuhid API response: ' . json_encode($response, JSON_PRETTY_PRINT)); + $apiData = $response['data'] ?? []; $newFlag = 'FAILED'; $updatedCount = 0; + $emp_policy_pks = []; + + $client_policy_data = db_connect()->table('client_policy') + ->select('cp.policy_no as policyNumber, cdm.cd_ac_no as CDBGAccountNumber, policy_type.policy_type') + ->join('cd_master cdm', 'client_policy.cd_ac_pk = cdm.id') + ->join('policy_type', 'policy_type.id = client_policy.policy_type_id') + ->where('client_policy.id', $batch['client_policy_id']) + ->get() + ->getRowArray(); + + $file_data = db_connect()->table('batch_files') + ->where('batch_files.id', $file_id) + ->get() + ->getRowArray(); if (!empty($response['status']) && $response['status'] === true && (($apiData['statusMessage'] ?? null) === 'SUCCESS')) { $newFlag = 'COMPLETED'; + log_message('error', 'ICICI - fetchuhid API returned SUCCESS. Processing memberDetails.'); // Update UHID in employee_polices table based on memberDetails $memberDetails = $apiData['memberDetails'] ?? []; if (!empty($memberDetails) && is_array($memberDetails)) { $db = \Config\Database::connect(); $clientPolicyId = (int) ($batch['client_policy_id'] ?? 0); + log_message('error', 'ICICI - MemberDetails count: ' . count($memberDetails) . ', client_policy_id: ' . $clientPolicyId); foreach ($memberDetails as $member) { $employeeMemberId = $member['employeeMemberId'] ?? null; $uhid = $member['uhid'] ?? null; + log_message('error', 'ICICI - Processing member: ' . json_encode($member, JSON_PRETTY_PRINT)); if (empty($employeeMemberId) || empty($uhid)) { + log_message('error', 'ICICI - Skipping member due to missing employeeMemberId or uhid. employeeMemberId: ' . var_export($employeeMemberId, true) . ', uhid: ' . var_export($uhid, true)); continue; } @@ -96,35 +127,96 @@ class ICICILombardController extends AdminController $employee = $db->table('employees') ->select('id') ->where('emp_code', $employeeMemberId) + ->where('client_id', $batch['client_id']) + ->where('is_active', 1) ->get() ->getRowArray(); if (empty($employee)) { + log_message('error', 'ICICI - No employee found for emp_code: ' . $employeeMemberId); continue; } - // Update UHID for that employee and policy - $db->table('employee_polices') - ->where('employee_id', $employee['id']) - ->where('client_policy_id', $clientPolicyId) - ->set('uhid', $uhid) - ->update(); + // Update TPA ID for that employee and policy + if($file_data['action'] == 'deletion'){ + $emp_policy_pks[] = $this->updateDeletionData($employee['id'], $clientPolicyId, $uhid, $member['endorsementNumber'] ?? null); + }else if(in_array($file_data['action'], ['correction', 'si_enhancement'])){ + $emp_policy_pks[] = $this->updateModificationData($employee, $member['endorsementNumber'] ?? null, $member, $file_data); + }else{ + $this->updateAdditionData($employee['id'], $clientPolicyId, $uhid); + } + log_message('error', 'ICICI - Updated employee_polices for employee_id: ' . $employee['id'] . ', client_policy_id: ' . $clientPolicyId . ', set tpa_id: ' . $uhid); $updatedCount++; } + } else { + log_message('error', 'ICICI - No memberDetails present or not an array in API response.'); } + + if($file_id){ + + $json = json_encode($memberDetails, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); + $filePath = WRITEPATH . 'tmp/'.time().'_'.$file_id.'.json'; + file_put_contents($filePath, $json); + + //call a job for dump JSON data to DB + $job_details = new Jobs(); + $r = Jobs::addJob(['job_name' => 'saveMediAssitAPIData', 'payload' => ['file_id' => $file_id, 'json_file_path' => $filePath ]]); + } + + + if(!empty($emp_policy_pks)){ + if($file_data['action'] == 'deletion'){ + $r = Jobs::addJob(['job_name' => 'cashDepositCalculationForDeletion', 'payload' => [ + 'employeeIds' => $emp_policy_pks, + 'client_id' => $file_data['client_id'] ?? null, + 'client_policy_id' => $file_data['client_policy_id'] ?? null, + 'client_branch_id' => $file_data['client_branch_id'] ?? null, + 'cd_ac_no' => $client_policy_data['CDBGAccountNumber'] ?? null, + 'endorsement_no' => null, + 'count' => count($emp_policy_pks), + 'event_name' => $file_data['event_type'], + 'policy_name' => $client_policy_data['policy_type'], + 'user_id' => $file_data['created_by'] ?? null, + 'file_id' => $file_id, + ]]); + } + + if($file_data['action'] == 'si_enhancement'){ + $job_details = new Jobs(); + $r = Jobs::addJob(['job_name' => 'cashDepositCalculationForSIEnhancement','payload' => [ + 'employeeIds' => $emp_policy_pks, + 'client_id' => $file_data['client_id'] ?? null, + 'client_policy_id' => $file_data['client_policy_id'] ?? null, + 'client_branch_id' => $file_data['client_branch_id'] ?? null, + 'cd_ac_no' => $client_policy_data['CDBGAccountNumber'] ?? null, + 'endorsement_no' => $file_data['endorsementNumber'] ?? null, + 'count' => count($emp_policy_pks), + 'event_name' => $file_data['event_type'], + 'policy_name' => $client_policy_data['policy_type'], + 'user_id' => $file_data['created_by'] ?? null, + 'file_id' => $file_id, + ]]); + } + } + + + + } else { + log_message('error', 'ICICI - fetchuhid API did not return SUCCESS. status: ' . var_export($response['status'] ?? null, true) . ', statusMessage: ' . var_export($apiData['statusMessage'] ?? null, true) . ', message: ' . var_export($apiData['message'] ?? null, true)); } $batchModel = new BatchFileModel(); $batchModel->update($batch['id'], [ 'icici_uhid_status_flag' => $newFlag, ]); + log_message('error', 'ICICI - Updated batch_files id ' . ($batch['id'] ?? 'unknown') . ' with icici_uhid_status_flag: ' . $newFlag . '. total UHIDs updated: ' . $updatedCount); return [ 'new_status' => $newFlag, 'updatedCount' => $updatedCount, - 'response' => $response, - 'request' => $body, + 'response' => $response, + 'request' => $body, ]; } @@ -160,263 +252,489 @@ class ICICILombardController extends AdminController return $response; } - public function createEnrollmentBatch() + public function ICICIPushEmployeeDetails($requested_data = null) { - $client_id = $this->request->getGet('client_id'); - $client_branch_id = $this->request->getGet('client_branch_id'); - // Prefer `client_policy_id` key (also accept legacy `policy_id`) - $policy_id = $this->request->getGet('client_policy_id') ?? $this->request->getGet('policy_id'); - $event = $this->request->getGet('event'); + $function_calling_type = $requested_data['return_type'] ?? 'api'; - //fetch token - $tokenResponse = $this->generateAuthToken('esbgpabatchcreation'); - if (!$tokenResponse || empty($tokenResponse['data']['access_token'])) { - return $this->response->setJSON([ - 'status' => false, - 'message' => 'Token generation failed.', - 'data' => $tokenResponse - ]); - } - $token = $tokenResponse['data']['access_token']; - + try { - $url = env('ICICI_BASE_URL').'/batchcreation'; - $headers = [ - 'Authorization: Bearer ' . $token, - 'Content-Type: application/json', - ]; + // 1. Centralize Input + $client_id = $requested_data['client_id'] ?? $this->request->getGet('client_id') ?? null; + $client_branch_id = $requested_data['client_branch_id'] ?? $this->request->getGet('client_branch_id') ?? null; + $policy_id = $requested_data['client_policy_id'] ?? $this->request->getGet('client_policy_id') ?? null; + $file_id = $requested_data['file_id'] ?? $this->request->getGet('file_id') ?? null; + $flagStatus = $requested_data['flag_status'] ?? $this->request->getGet('flag_status') ?? null; + $action = $requested_data['event'] ?? $this->request->getGet('event') ?? null; + $event = "ADD"; + $fileModel = new BatchFileModel(); + $updateBatchFileStatus = function (string $status) use ($file_id, $fileModel) { + if (empty($file_id)) { + log_message('error', 'ICICI - ICICIPushEmployeeDetails | file_id missing, skipped batch_files.status update.'); + return; + } + + $fileModel->where('id', $file_id)->set('status', $status)->update(); + log_message('error', "ICICI - ICICIPushEmployeeDetails | batch_files.status updated for file_id {$file_id} => {$status}"); + }; + + //fetch token + $tokenResponse = $this->generateAuthToken('esbgpabatchcreation'); + if (!$tokenResponse || empty($tokenResponse['data']['access_token'])) { + + $return_respond_data = [ + 'status' => false, + 'message' => 'Token generation failed.', + 'data' => $tokenResponse + ]; + + log_message('error', 'ICICI - ICICIPushEmployeeDetails Failed: ' . json_encode($return_respond_data, JSON_PRETTY_PRINT)); + $updateBatchFileStatus('failed-8'); + + if ($function_calling_type == "job") { + return $return_respond_data; + } else { + return $this->response->setJSON($return_respond_data); + } + } + $token = $tokenResponse['data']['access_token']; - // Prepare body data from employee policies - $db = \Config\Database::connect(); - $data = $db->table('employee_polices ep') - ->select('cp.policy_no as policyNumber, cp.cd_ac_no as CDBGAccountNumber, - e.id,e.emp_code as MemberEmpId, e.doj as DOJ, e.name as InsuredName, e.dob as DOB, e.relationship as Relationship, - e.gender as Gender, ep.date_coverage as DOC,ep.basic_cover_si as SumInsured, e.email_corporate as EmailId - ') - ->join('employees e', 'e.id = ep.employee_id') - ->join('client_policy cp', 'ep.client_policy_id = cp.id') - ->where('ep.client_policy_id', $policy_id) - ->where('ep.status', 'active') - ->where('ep.is_active', 1) - // ->where('ep.uhid', null) - ->get() - ->getResultArray(); - // dd($data); - if (empty($data)) { - return $this->response->setJSON([ - 'status' => false, - 'message' => 'No active employee policies found for given policy.', - 'data' => [], - ]); - } - - $body = $this->formatPolicyData($data); - if (empty($body['CDBGAccountNumber'])) { - return $this->response->setJSON([ - 'status' => false, - 'message' => 'CDBGAccountNumber is empty for selected policy. Please configure policy CDBG account number.', - 'data' => $body, - ]); - } - - if (empty($body['MemberDetails'])) { - return $this->response->setJSON([ - 'status' => false, - 'message' => 'No valid member records available for ICICI enrollment payload.', - 'data' => $body, - ]); - } - - $response = call_third_party_api($url, 'POST', $headers, $body, true); // true = raw body mode - - // Save batch information only on successful API call - if (!empty($response['status']) && $response['status'] === true) { - $apiData = $response['data'] ?? []; - - $batchModel = new BatchFileModel(); - $batchModel->insert([ - 'client_id' => $client_id, - 'client_policy_id' => $policy_id, - 'client_branch_id' => $client_branch_id, - 'event_type' => $event, - 'insurer_or_tpa' => 'ICICI_LOMBARD', - 'actions' => 'ICICI_GPA_ENROLLMENT', - 'is_active' => 1, - 'icici_correlation_id' => $body['CorrelationId'] ?? null, - 'icici_batch_id' => $apiData['batchId'] ?? null, - 'icici_status_flag' => 'PENDING', - 'icici_status_message' => $apiData['message'] ?? null, - 'icici_endorsement_policy_no' => null, - 'icici_uhid_status_flag' => 'PENDING', - ]); - } - - return $this->response->setJSON($response); - } - - public function getEnrollmentBatchStatus() - { - helper('api'); - - // User request: use `client_policy_id` key (also accept legacy `policy_id`) - $clientPolicyId = $this->request->getGet('client_policy_id') ?? $this->request->getGet('policy_id'); - - //fetch token - $tokenResponse = $this->generateAuthToken('esbgpabatchstatus'); - if (!$tokenResponse || empty($tokenResponse['data']['access_token'])) { - return $this->response->setJSON([ - 'status' => false, - 'message' => 'Token generation failed.', - 'data' => $tokenResponse - ]); - } - $token = $tokenResponse['data']['access_token']; - - - $url = env('ICICI_BASE_URL').'/batchstatus'; - $headers = [ - 'Authorization: Bearer ' . $token, - 'Content-Type: application/json' - ]; - - $db = \Config\Database::connect(); - - // Fetch all pending / in-process batches for ICICI - $query = $db->table('batch_files bf') - ->select('bf.id, bf.client_policy_id, bf.icici_batch_id, bf.icici_correlation_id, cp.policy_no') - ->join('client_policy cp', 'cp.id = bf.client_policy_id') - ->where('bf.is_active', 1) - ->whereIn('bf.icici_status_flag', ['PENDING', 'IN_PROCESS']) - ->where('bf.icici_batch_id IS NOT NULL'); - - if (!empty($clientPolicyId)) { - $query->where('bf.client_policy_id', (int) $clientPolicyId); - } - - $batches = $query->get()->getResultArray(); - - if (empty($batches)) { - return $this->response->setJSON([ - 'status' => true, - 'message' => 'No pending ICICI GPA batches found.', - 'data' => [], - ]); - } - - $batchModel = new BatchFileModel(); - $results = []; - - foreach ($batches as $batch) { - $body = [ - 'PolicyNumber' => $batch['policy_no'], - 'BatchId' => $batch['icici_batch_id'], - 'CorrelationId' => $batch['icici_correlation_id'], + $url = env('ICICI_BASE_URL') . '/batchcreation'; + $headers = [ + 'Authorization: Bearer ' . $token, + 'Content-Type: application/json', ]; - $response = call_third_party_api($url, 'POST', $headers, $body, true); - $apiData = $response['data'] ?? []; - $message = $apiData['message'] ?? null; - $statusMessage = $apiData['statusMessage'] ?? null; + if(in_array($action, ['inception', 'addition', 'missed_inception', 'dependent_addition'])){ + // Prepare body data from employee policies + $db = \Config\Database::connect(); + $data = $db->table('employee_polices ep') + ->select(' - $newStatusFlag = 'FAILED'; - if (!empty($response['status']) && $response['status'] === true && $statusMessage === 'SUCCESS') { - if ($message === 'Process Completed') { - $newStatusFlag = 'COMPLETED'; - } elseif ($message === 'In Process') { - $newStatusFlag = 'IN_PROCESS'; + cp.policy_no as policyNumber, + cdm.cd_ac_no as CDBGAccountNumber, + e.id,e.emp_code as MemberEmpId, + e.doj as DOJ, + e.name as InsuredName, + e.dob as DOB, + e.relationship as Relationship, + e.gender as Gender, + ep.date_coverage as DOC, + ep.basic_cover_si as SumInsured, + e.email_corporate as EmailId + + ') + ->join('employees e', 'e.id = ep.employee_id') + ->join('client_policy cp', 'ep.client_policy_id = cp.id') + ->join('cd_master cdm', 'cp.cd_ac_pk = cdm.id') + ->where('ep.client_policy_id', $policy_id) + ->where('ep.status', 'active') + ->where('ep.is_active', 1) + ->where('ep.tpa_id', null) + ->get() + ->getResultArray(); + + }else if(in_array($action, ['deletion', 'correction', 'si_enhancement'])) { + + $EmployeePolicyModel = new EmployeePolicyModel(); + + if($action == 'deletion'){ + $deletion_data = $EmployeePolicyModel->getDeletionEmployeeDataForExportExcel($requested_data, 1); + $data = $this->formatPolicyDataForDeletion($deletion_data, $policy_id); + }else if($action == 'correction'){ + $correction_data = $EmployeePolicyModel->getCorrectionEmployeesDataForExportExcel($requested_data, 1); + $data = $this->formatPolicyDataForCorrection($correction_data, $policy_id); + }else if($action == 'si_enhancement'){ + $si_enhancement_data = $EmployeePolicyModel->getSIEnhancementEmployeesDataForExportExcel($requested_data, 1); + $data = $this->formatPolicyDataForSIEnhancement($si_enhancement_data, $policy_id); + } + + } + + // dd($data); + if (empty($data)) { + + $return_respond_data = [ + 'status' => false, + 'message' => 'No active employee policies found for given policy.', + 'data' => [], + ]; + + log_message('error', 'ICICI - ICICIPushEmployeeDetails Failed: ' . json_encode($return_respond_data, JSON_PRETTY_PRINT)); + $updateBatchFileStatus('failed-8'); + + if ($function_calling_type == "job") { + return $return_respond_data; } else { - $newStatusFlag = 'PENDING'; + return $this->response->setJSON($return_respond_data); } } - $updateData = [ - 'icici_status_flag' => $newStatusFlag, - 'icici_status_message' => $message, - 'icici_endorsement_policy_no'=> $apiData['endorsementPolicyNo'] ?? null, - ]; + $body = $this->formatPolicyData($data, $flagStatus); + if (empty($body['CDBGAccountNumber'])) { - // If process completed successfully, UHID step becomes pending - if ($newStatusFlag === 'COMPLETED') { - $updateData['icici_uhid_status_flag'] = 'PENDING'; + $return_respond_data = [ + 'status' => false, + 'message' => 'CDBGAccountNumber is empty for selected policy. Please configure policy CD account number.', + 'data' => $body, + ]; + + log_message('error', 'ICICI - ICICIPushEmployeeDetails Failed: ' . json_encode($return_respond_data, JSON_PRETTY_PRINT)); + $updateBatchFileStatus('failed-8'); + + if ($function_calling_type == "job") { + return $return_respond_data; + } else { + return $this->response->setJSON($return_respond_data); + } } - $batchModel->update($batch['id'], $updateData); + if (empty($body['MemberDetails'])) { - // After COMPLETED, trigger UHID fetch internally (no extra imid param). - $uhidResult = null; - if ($newStatusFlag === 'COMPLETED') { - // Ensure we pass endorsement policy number to the internal UHID fetch helper. - $batch['icici_endorsement_policy_no'] = $updateData['icici_endorsement_policy_no'] ?? null; - $uhidResult = $this->fetchUhidAndUpdateEmployeePolicies($batch); + $return_respond_data = [ + 'status' => false, + 'message' => 'No valid member records available for ICICI enrollment payload.', + 'data' => $body, + ]; + + log_message('error', 'ICICI - ICICIPushEmployeeDetails Failed: ' . json_encode($return_respond_data, JSON_PRETTY_PRINT)); + $updateBatchFileStatus('failed-8'); + + if ($function_calling_type == "job") { + return $return_respond_data; + } else { + return $this->response->setJSON($return_respond_data); + } } - $results[] = [ - 'batch_file_id' => $batch['id'], - 'request' => $body, - 'response' => $response, - 'new_status' => $newStatusFlag, - 'uhid_fetch' => $uhidResult, + $response = call_third_party_api($url, 'POST', $headers, $body, true); // true = raw body mode + log_message('error', 'ICICI - ICICIPushEmployeeDetails call_third_party_api Response: ' . json_encode($response, JSON_PRETTY_PRINT)); + + + // Save batch information only on successful API call + if (!empty($response['status']) && $response['status'] === true) { + $apiData = $response['data'] ?? []; + + $updateData = [ + 'icici_correlation_id' => $body['CorrelationId'] ?? null, + 'icici_batch_id' => $apiData['batchId'] ?? null, + 'icici_status_flag' => 'PENDING', + 'icici_status_message' => $apiData['message'] ?? null, + 'icici_endorsement_policy_no' => $apiData['endorsement_policy_no'] ?? null, + 'icici_uhid_status_flag' => 'PENDING', + ]; + + $batchModel = new BatchFileModel(); + $batchModel->where('id', $file_id)->set($updateData)->update(); + + log_message('error', "ICICI - ICICIPushEmployeeDetails success and update batch files table with file id : $file_id : " . json_encode($updateData, JSON_PRETTY_PRINT)); + } + + if ($function_calling_type == "job") { + $updateBatchFileStatus(!empty($response['status']) && $response['status'] === true ? 'success' : 'failed-8'); + return $response; + } else { + $updateBatchFileStatus(!empty($response['status']) && $response['status'] === true ? 'success' : 'failed-8'); + return $this->response->setJSON($response); + } + + } 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, ]; + + log_message('error', 'ICICI - Exception thrown while calling ICICIPushEmployeeDetails API: ' . json_encode($errorData, JSON_PRETTY_PRINT)); + if (!empty($requested_data['file_id'])) { + $catchFileModel = new BatchFileModel(); + $catchFileModel->where('id', $requested_data['file_id'])->set('status', 'failed-8')->update(); + log_message('error', "ICICI - ICICIPushEmployeeDetails | batch_files.status updated in catch for file_id {$requested_data['file_id']} => failed-8"); + } + $updateBatchFileStatus('failed-8'); + + if ($function_calling_type == "job") { + return ['status' => false, 'message' => 'API call failed', 'data' => $errorData]; + } else { + return $this->response->setJSON(['status' => false, 'message' => 'API call failed', 'data' => []]); + } } - - return $this->response->setJSON([ - 'status' => true, - 'message' => 'Batch status updated.', - 'data' => $results, - ]); } - public function fetchUHIDDetails() + public function getEnrollmentBatchStatus($param) { helper('api'); - // Accept `client_policy_id` key (also accept legacy `policy_id`) - $policy_id = $this->request->getGet('client_policy_id') ?? $this->request->getGet('policy_id'); - $imid = $this->request->getGet('imid'); // optional; if omitted we derive from icici_batch_id + try { - if (empty($policy_id)) { - return $this->response->setJSON([ + $clientPolicyId = $param['client_policy_id']; + $fileId = $param['file_id']; + $fileModel = new BatchFileModel(); + $updateBatchFileStatus = function (string $status) use ($fileId, $fileModel) { + if (empty($fileId)) { + log_message('error', 'ICICI - getEnrollmentBatchStatus | file_id missing, skipped batch_files.status update.'); + return; + } + + $fileModel->where('id', $fileId)->set('status', $status)->update(); + log_message('error', "ICICI - getEnrollmentBatchStatus | batch_files.status updated for file_id {$fileId} => {$status}"); + }; + + log_message('error', "ICICI - getEnrollmentBatchStatus started for client_policy_id: {$clientPolicyId}, file_id: {$fileId}"); + + //fetch token + $tokenResponse = $this->generateAuthToken('esbgpabatchstatus'); + if (!$tokenResponse || empty($tokenResponse['data']['access_token'])) { + log_message('error', 'ICICI - Token generation failed for batch status: ' . json_encode($tokenResponse, JSON_PRETTY_PRINT)); + $updateBatchFileStatus('failed-8'); + return [ + 'status' => false, + 'message' => 'Token generation failed.', + 'data' => $tokenResponse + ]; + } + $token = $tokenResponse['data']['access_token']; + log_message('error', 'ICICI - Token generated for batch status.'); + + $url = env('ICICI_BASE_URL') . '/batchstatus'; + $headers = [ + 'Authorization: Bearer ' . $token, + 'Content-Type: application/json' + ]; + + $db = \Config\Database::connect(); + + // Fetch all pending / in-process batches for ICICI + $query = $db->table('batch_files bf') + ->select('bf.id, bf.client_policy_id, bf.icici_batch_id, bf.icici_correlation_id, cp.policy_no') + ->join('client_policy cp', 'cp.id = bf.client_policy_id') + ->where('bf.is_active', 1) + ->whereIn('bf.icici_status_flag', ['PENDING', 'IN_PROCESS']) + ->where('bf.icici_batch_id IS NOT NULL'); + + if (!empty($clientPolicyId)) { + $query->where('bf.client_policy_id', (int) $clientPolicyId); + } + + $batches = $query->get()->getResultArray(); + + log_message('error', 'ICICI - Fetched pending batches count: ' . count($batches)); + + if (empty($batches)) { + log_message('error', 'ICICI - No pending ICICI GPA batches found.'); + $updateBatchFileStatus('success'); + return [ + 'status' => true, + 'message' => 'No pending ICICI GPA batches found.', + 'data' => [], + ]; + } + + $batchModel = new BatchFileModel(); + $results = []; + + foreach ($batches as $batch) { + $body = [ + 'PolicyNumber' => $batch['policy_no'], + 'BatchId' => $batch['icici_batch_id'], + 'CorrelationId' => $batch['icici_correlation_id'], + ]; + + log_message('error', 'ICICI - Calling batchstatus API for batch_file_id: ' . $batch['id'] . ', payload: ' . json_encode($body, JSON_PRETTY_PRINT)); + + $response = call_third_party_api($url, 'POST', $headers, $body, true); + log_message('error', 'ICICI - batchstatus API response for batch_file_id: ' . $batch['id'] . ': ' . json_encode($response, JSON_PRETTY_PRINT)); + + $apiData = $response['data'] ?? []; + + $message = $apiData['message'] ?? null; + $statusMessage = $apiData['statusMessage'] ?? null; + + $newStatusFlag = 'FAILED'; + if (!empty($response['status']) && $response['status'] === true && $statusMessage === 'SUCCESS') { + if ($message === 'Process Completed') { + $newStatusFlag = 'COMPLETED'; + } elseif ($message === 'In Process') { + $newStatusFlag = 'IN_PROCESS'; + } else { + $newStatusFlag = 'PENDING'; + } + } + + $updateData = [ + 'icici_status_flag' => $newStatusFlag, + 'icici_status_message' => $message, + 'icici_endorsement_policy_no' => $apiData['endorsementPolicyNo'] ?? null, + ]; + + // If process completed successfully, UHID step becomes pending + if ($newStatusFlag === 'COMPLETED') { + $updateData['icici_uhid_status_flag'] = 'PENDING'; + } + + $batchModel->update($batch['id'], $updateData); + log_message('error', 'ICICI - Updated batch_files for id ' . $batch['id'] . ' with: ' . json_encode($updateData, JSON_PRETTY_PRINT)); + + // After COMPLETED, trigger UHID fetch internally (no extra imid param). + // $uhidResult = null; + // if ($newStatusFlag === 'COMPLETED') { + // // Ensure we pass endorsement policy number to the internal UHID fetch helper. + // $batch['icici_endorsement_policy_no'] = $updateData['icici_endorsement_policy_no'] ?? null; + // log_message('error', 'ICICI - Triggering UHID fetch for batch_file_id: ' . $batch['id']); + // $uhidResult = $this->fetchUhidAndUpdateEmployeePolicies($batch); + // log_message('error', 'ICICI - UHID fetch result for batch_file_id ' . $batch['id'] . ': ' . json_encode($uhidResult, JSON_PRETTY_PRINT)); + // } + + $results[] = [ + 'batch_file_id' => $batch['id'], + 'request' => $body, + 'response' => $response, + 'new_status' => $newStatusFlag, + // 'uhid_fetch' => $uhidResult, + ]; + } + + // Push a job to fetch UHID details asynchronously if needed (keeps backward compatibility) + $r = Jobs::addJob(['job_name' => 'fetchUHIDDetails', 'payload' => ['client_policy_id' => $clientPolicyId, 'file_id' => $fileId, 'return_type' => 'job']]); + log_message('error', "ICICI - getEnrollmentBatchStatus job pushed for client_policy_id: {$clientPolicyId}, file_id: {$fileId}, job_result: " . json_encode($r, JSON_PRETTY_PRINT)); + $updateBatchFileStatus('success'); + + return [ + 'status' => true, + 'message' => 'Batch status updated.', + 'data' => $results, + ]; + + } catch (\Throwable $th) { + $errorData = [ + 'message' => $th->getMessage(), + 'file' => $th->getFile(), + 'line' => $th->getLine(), + 'code' => $th->getCode(), + 'trace' => $th->getTraceAsString(), + 'trace_array' => $th->getTrace(), + ]; + + if (!empty($param['file_id'])) { + $catchFileModel = new BatchFileModel(); + $catchFileModel->where('id', $param['file_id'])->set('status', 'failed-8')->update(); + log_message('error', "ICICI - getEnrollmentBatchStatus | batch_files.status updated in catch for file_id {$param['file_id']} => failed-8"); + } + + log_message('error', 'ICICI - Exception in getEnrollmentBatchStatus: ' . json_encode($errorData, JSON_PRETTY_PRINT)); + $updateBatchFileStatus('failed-8'); + + return [ 'status' => false, - 'message' => 'client_policy_id is required.', - 'data' => [], - ]); + 'message' => 'Batch status updated failed.', + 'data' => $errorData, + ]; } - - $batchModel = new BatchFileModel(); - $batch = $batchModel - ->where('client_policy_id', $policy_id) - ->where('is_active', 1) - ->where('icici_status_flag', 'COMPLETED') - ->whereIn('icici_uhid_status_flag', ['PENDING', 'FAILED']) - ->orderBy('id', 'DESC') - ->first(); - - if (empty($batch)) { - return $this->response->setJSON([ - 'status' => false, - 'message' => 'No completed ICICI GPA batch found for UHID fetch.', - 'data' => [], - ]); - } - - $uhidResult = $this->fetchUhidAndUpdateEmployeePolicies($batch, $imid); - - return $this->response->setJSON([ - 'status' => true, - 'message' => 'UHID details fetched.', - 'data' => [ - 'batch_file_id' => $batch['id'], - 'request' => $uhidResult['request'] ?? [], - 'response' => $uhidResult['response'] ?? [], - 'new_status' => $uhidResult['new_status'] ?? 'FAILED', - 'uhid_updated_count' => $uhidResult['updatedCount'] ?? 0, - ], - ]); } - public function formatPolicyData($data) + public function fetchUHIDDetails($param) + { + helper('api'); + + try { + + log_message('error', 'ICICI - fetchUHIDDetails started with params: ' . json_encode($param, JSON_PRETTY_PRINT)); + + $policy_id = $param['client_policy_id']; + $fileId = $param['file_id']; + $imid = $param['imid'] ?? null; // optional; if omitted we derive from icici_batch_id + $fileModel = new BatchFileModel(); + $updateBatchFileStatus = function (string $status) use ($fileId, $fileModel) { + if (empty($fileId)) { + log_message('error', 'ICICI - fetchUHIDDetails | file_id missing, skipped batch_files.status update.'); + return; + } + + $fileModel->where('id', $fileId)->set('status', $status)->update(); + log_message('error', "ICICI - fetchUHIDDetails | batch_files.status updated for file_id {$fileId} => {$status}"); + }; + + if (empty($policy_id)) { + log_message('error', 'ICICI - fetchUHIDDetails failed: client_policy_id is required. Params: ' . json_encode($param, JSON_PRETTY_PRINT)); + $updateBatchFileStatus('failed-8'); + return [ + 'status' => false, + 'message' => 'client_policy_id is required.', + 'data' => [], + ]; + } + + $batchModel = new BatchFileModel(); + $batch = $batchModel + ->where('client_policy_id', $policy_id) + ->where('is_active', 1) + ->where('icici_status_flag', 'COMPLETED') + ->whereIn('icici_uhid_status_flag', ['PENDING', 'FAILED']) + ->orderBy('id', 'DESC') + ->first(); + + if (empty($batch)) { + log_message('error', "ICICI - No completed ICICI GPA batch found for UHID fetch. client_policy_id: {$policy_id}"); + $updateBatchFileStatus('failed-8'); + return [ + 'status' => false, + 'message' => 'No completed ICICI GPA batch found for UHID fetch.', + 'data' => [], + ]; + } + + log_message('error', 'ICICI - fetchUHIDDetails found batch: ' . json_encode($batch, JSON_PRETTY_PRINT)); + + log_message('error', 'ICICI - Triggering fetchUhidAndUpdateEmployeePolicies for batch_id: ' . $batch['id'] . ', imid: ' . var_export($imid, true)); + $uhidResult = $this->fetchUhidAndUpdateEmployeePolicies($batch, $imid, $fileId); + log_message('error', 'ICICI - fetchUhidAndUpdateEmployeePolicies result for batch_id ' . $batch['id'] . ': ' . json_encode($uhidResult, JSON_PRETTY_PRINT)); + $updateBatchFileStatus('success'); + + return [ + 'status' => true, + 'message' => 'UHID details fetched.', + 'data' => [ + 'batch_file_id' => $batch['id'], + 'request' => $uhidResult['request'] ?? [], + 'response' => $uhidResult['response'] ?? [], + 'new_status' => $uhidResult['new_status'] ?? 'FAILED', + 'uhid_updated_count' => $uhidResult['updatedCount'] ?? 0, + ], + ]; + } catch (\Throwable $th) { + $errorData = [ + 'message' => $th->getMessage(), + 'file' => $th->getFile(), + 'line' => $th->getLine(), + 'code' => $th->getCode(), + 'trace' => $th->getTraceAsString(), + 'trace_array' => $th->getTrace(), + ]; + + if (!empty($param['file_id'])) { + $catchFileModel = new BatchFileModel(); + $catchFileModel->where('id', $param['file_id'])->set('status', 'failed-8')->update(); + log_message('error', "ICICI - fetchUHIDDetails | batch_files.status updated in catch for file_id {$param['file_id']} => failed-8"); + } + + log_message('error', 'ICICI - Exception in fetchUHIDDetails: ' . json_encode($errorData, JSON_PRETTY_PRINT)); + + return [ + 'status' => false, + 'message' => 'UHID details fetched failed.', + 'data' => $errorData, + ]; + } + } + + public function formatPolicyData($data, $flagStatus = "A") { // Helper to format date as DD-MMM-YYYY (e.g. 7-JUL-1993) $formatDate = function ($date) { @@ -473,24 +791,589 @@ class ICICILombardController extends AdminController "Relationship" => strtoupper((string) $row['Relationship']), "Gender" => $mapGender($row['Gender'] ?? ''), "DOC" => $formatDate($row['DOC']), + "DOL" => isset($row['DOL']) ? $formatDate($row['DOL']) : null, "SumInsured" => $row['SumInsured'], "EmailId" => $row['EmailId'], - "FlagStatus" => "A" + "FlagStatus" => $flagStatus ]; } // Final body return [ "PolicyNumber" => $data[0]['policyNumber'] ?? null, - "CDBGAccountNumber" => $data[0]['CDBGAccountNumber'] ?? env('ICICI_CDBG_ACCOUNT_NUMBER'), + "CDBGAccountNumber" => $data[0]['CDBGAccountNumber'] ?? null, "CorrelationId" => $generateUUID(), "MemberDetails" => $memberDetails ]; } + private function formatPolicyDataForDeletion($data, $policy_id) + { + $client_policy_data = db_connect()->table('client_policy') + ->select('cp.policy_no as policyNumber, cdm.cd_ac_no as CDBGAccountNumber') + ->join('cd_master cdm', 'client_policy.cd_ac_pk = cdm.id') + ->where('client_policy.id', $policy_id) + ->get() + ->getRowArray(); + $formattedData = []; + foreach ($data as $key => $value) { + $formattedData[] = [ + 'policyNumber' => $client_policy_data['policyNumber'] ?? null, + 'CDBGAccountNumber' => $client_policy_data['CDBGAccountNumber'] ?? null, + 'MemberEmpId' => $value['emp_code'] ?? null, + 'DOJ' => change_date_format($value['emp_doj']) ?? null, + 'InsuredName' => $value['emp_name'] ?? null, + 'DOB' => change_date_format($value['emp_dob']) ?? null, + 'Relationship' => $value['emp_relationship'] ?? null, + 'Gender' => $value['emp_gender'] ?? null, + 'DOC' => $value['date_coverage'] ?? null, + 'DOL' => $value['dateofexit'] ?? null, + 'SumInsured' => $value['basic_cover_si'] ?? null, + 'EmailId' => $value['emp_email_c'] ?? null, + ]; + } + + return $formattedData; + } + + private function formatPolicyDataForCorrection($data, $policy_id) + { + $client_policy_data = db_connect()->table('client_policy') + ->select('cp.policy_no as policyNumber, cdm.cd_ac_no as CDBGAccountNumber') + ->join('cd_master cdm', 'client_policy.cd_ac_pk = cdm.id') + ->where('client_policy.id', $policy_id) + ->get() + ->getRowArray(); + $formattedData = []; + foreach ($data as $key => $value) { + $formattedData[] = [ + 'policyNumber' => $client_policy_data['policyNumber'] ?? null, + 'CDBGAccountNumber' => $client_policy_data['CDBGAccountNumber'] ?? null, + 'MemberEmpId' => $value['emp_code'] ?? null, + 'DOJ' => change_date_format($value['emp_doj']) ?? null, + 'InsuredName' => $value['field_name'] == 'name' ? $value['new_value'] : $value['emp_name'] ?? null, + 'DOB' => change_date_format($value['field_name'] == 'dob' ? $value['new_value'] : $value['emp_dob'] ?? null) ?? null, + 'Relationship' => $value['emp_relationship'] ?? null, + 'Gender' => $value['emp_gender'] ?? null, + 'DOC' => $value['date_coverage'] ?? null, + 'SumInsured' => $value['basic_cover_si'] ?? null, + 'EmailId' => $value['field_name'] == 'email_corporate' ? $value['new_value'] : $value['emp_email_c'] ?? null, + ]; + } + + return $formattedData; + } + + private function formatPolicyDataForSIEnhancement($data, $policy_id) + { + $client_policy_data = db_connect()->table('client_policy') + ->select('cp.policy_no as policyNumber, cdm.cd_ac_no as CDBGAccountNumber') + ->join('cd_master cdm', 'client_policy.cd_ac_pk = cdm.id') + ->where('client_policy.id', $policy_id) + ->get() + ->getRowArray(); + $formattedData = []; + foreach ($data as $key => $value) { + $formattedData[] = [ + 'policyNumber' => $client_policy_data['policyNumber'] ?? null, + 'CDBGAccountNumber' => $client_policy_data['CDBGAccountNumber'] ?? null, + 'MemberEmpId' => $value['emp_code'] ?? null, + 'DOJ' => $value['emp_doj'] ?? null, + 'InsuredName' => $value['emp_name'] ?? null, + 'DOB' => $value['emp_dob'] ?? null, + 'Relationship' => $value['emp_relationship'] ?? null, + 'Gender' => $value['emp_gender'] ?? null, + 'DOC' => $value['date_of_coverage'] ?? null, + 'SumInsured' => $value['new_basic_cover_si'] ?? null, + 'EmailId' => $value['emp_email_c'] ?? null, + ]; + } + + return $formattedData; + } + + private function updateAdditionData($employee_id, $clientPolicyId, $uhid) + { + $db = \Config\Database::connect(); + + $db->table('employee_polices') + ->where('employee_id', $employee_id) + ->where('client_policy_id', $clientPolicyId) + ->set('tpa_id', $uhid) + ->update(); + + return true; + } + + private function updateDeletionData($employee_id, $clientPolicyId, $uhid, $endorsement_no) + { + $db = \Config\Database::connect(); + + if(empty($endorsement_no)){ + return null; + } + + // Get policy row (single) + $policy_data = $db->table('employee_polices') + ->where('employee_id', $employee_id) + ->where('client_policy_id', $clientPolicyId) + ->where('tpa_id', $uhid) + ->get() + ->getRowArray(); + + // Get endorsement data + $endorsment_data = $db->table('emp_endorsement') + ->where('table_name', 'employee_polices') + ->where('pk', $policy_data['id'] ?? 0) + ->where('status !=', 'truncated') + ->where('endorsement_no IS NULL', null, false) + ->where('is_active', 1) + ->where('actions', 'd') + ->get() + ->getResultArray(); + + if (empty($endorsment_data)) { + return null; + } + + $result = []; + $group_keys = []; + + foreach ($endorsment_data as $row) { + if (!empty($row['group_key'])) { + $group_keys[] = $row['group_key']; + } + + if (isset($row['field_name']) && isset($row['new_value'])) { + $result[$row['field_name']] = $row['new_value']; + } + } + + // Remove duplicate group keys + $group_keys = array_unique($group_keys); + + // Update endorsement table + if (!empty($group_keys)) { + $db->table('emp_endorsement') + ->whereIn('group_key', $group_keys) + ->set('endorsement_no', $endorsement_no) + ->update(); + } + + // Update employee_polices table + if (!empty($result)) { + $db->table('employee_polices') + ->where('employee_id', $employee_id) + ->where('client_policy_id', $clientPolicyId) + ->where('tpa_id', $uhid) + ->set($result) + ->update(); + } + + return $policy_data['id'] ?? null; + } + + private function updateModificationData($employee, $endorsement_no, $member, $file_data) + { + $db = \Config\Database::connect(); + + if (empty($employee)) { + return null; + } + + if (empty($members)) { + return null; + } + + if (empty($endorsement_no)) { + return null; + } + // update only CORRECTION data + if ($file_data['action'] == 'correction') { + $endorsment_data = $db->table('emp_endorsement') + ->where('table_name', 'employees') + ->where('pk', $employee['id'] ?? 0) + ->where('emp_code', $employee['emp_code'] ?? '') + ->where('status !=', 'truncated') + ->where('endorsement_no IS NULL', null, false) + ->where('is_active', 1) + ->where('actions', 'c') + ->get() + ->getResultArray(); + + $result = []; + $group_keys = []; + + foreach ($endorsment_data as $row) { + if (!empty($row['group_key'])) { + $group_keys[] = $row['group_key']; + } + + if (isset($row['field_name']) && isset($row['new_value'])) { + $result[$row['field_name']] = $row['new_value']; + } + } + + // Remove duplicate group keys + $group_keys = array_unique($group_keys); + + // Update endorsement table + if (!empty($group_keys)) { + $db->table('emp_endorsement') + ->whereIn('group_key', $group_keys) + ->set('endorsement_no', $endorsement_no) + ->update(); + } + + // Update endorsement table + if (!empty($result)) { + $db->table('employees') + ->where('id', $employee['id'] ?? 0) + ->set($result) + ->update(); + } + } + + // update only SI ENHANCEMENT data + if ($file_data['action'] == 'si_enhancement') { + + // Get policy row (single) + $policy_data = $db->table('employee_polices') + ->where('employee_id', $employee['id'] ?? 0) + ->where('client_policy_id', $file_data['client_policy_id'] ?? 0) + ->where('tpa_id', $member['uhid'] ?? '') + ->get() + ->getRowArray(); + + // Get endorsement data + $endorsment_data = $db->table('emp_endorsement') + ->where('table_name', 'employee_polices') + ->where('pk', $policy_data['id'] ?? 0) + ->where('status !=', 'truncated') + ->where('endorsement_no IS NULL', null, false) + ->where('is_active', 1) + ->where('actions', 'si') + ->get() + ->getResultArray(); + + if (empty($endorsment_data)) { + return null; + } + + $result = []; + $group_keys = []; + $old_result = []; + + foreach ($endorsment_data as $row) { + if (!empty($row['group_key'])) { + $group_keys[] = $row['group_key']; + } + + if (isset($row['field_name']) && isset($row['new_value'])) { + $result[$row['field_name']] = $row['new_value']; + $old_result[$row['field_name']] = $row['old_value']; + } + } + + + $si_adjustment = ($old_result['basic_cover_si'] < $result['basic_cover_si']) ? 1 : 2; + + $insertedIds = [ + 'pk' => $endorsment_data['pk'], + 'si_adjustment' => $si_adjustment + ]; + + // Remove duplicate group keys + $group_keys = array_unique($group_keys); + + // Update endorsement table + if (!empty($group_keys)) { + $db->table('emp_endorsement') + ->whereIn('group_key', $group_keys) + ->set('endorsement_no', $endorsement_no) + ->update(); + } + + // Update employee_polices table + if (!empty($result)) { + $db->table('employee_polices') + ->where('employee_id', $employee['id'] ?? 0) + ->where('client_policy_id', $file_data['client_policy_id'] ?? 0) + ->where('tpa_id', $member['uhid'] ?? '') + ->set($result) + ->update(); + } + + return $insertedIds ?? null; + } + } + + public function saveICICILombardAPIData($array) + { + $file_id = $array['file_id']; + $json = file_get_contents($array['json_file_path']); + $records = json_decode($json, true); + // log_message('error','MEDI_ASSIST - saveMediAssitAPIData' . json_encode($array));//die(); + $file_model = new BatchFileModel(); + $file_info = $file_model->where('id', $file_id)->find(); + // dd($file_info); + $tpaApiDataModel = new TpaApiDataModel(); + + // echo $file_id;die(); + //deactivate old data + $tpaApiDataModel->set('is_active', 0)->where('file_id', $file_id)->update(); + + //covert tpa data to our model data + $mappedRows = []; + + foreach ($records as $row) { + + $mappedRows[] = [ + 'file_id' => $file_id, // ← pass from controller + 'emp_code' => trim($row['employeeMemberId'] ?? ''), + + 'name' => trim($row['insuredName'] ?? ''), + 'dob' => !empty($row['DOB']) ? date('Y-m-d', strtotime(str_replace('/', '-', $row['DOB']))) : null, + + 'relation' => trim($row['Relationship'] ?? null), + 'gender' => strtoupper($row['Gender'] ?? null), + 'self' => strtolower($row['Relationship'] ?? '') === 'self' ? 1 : 0, + + 'si' => $row['SumInsured'] ?? null, + 'doj' => isset($row['DOC']) ? date('Y-m-d', strtotime(str_replace('/', '-', $row['DOC']))) : null, + + + 'tpa_id' => trim($row['uhid'] ?? null), + 'age' => null, + + 'is_active' => 1, + 'created_by' => $file_info[0]['created_by'] ?? null, + + 'endorsement_no' => trim($row['endorsementNumber'] ?? null), + 'action_flag_status' => trim($row['flagStatus'] ?? null), + + ]; + } + // log_message('error','MEDI_ASSIST - COUNT' . count($mappedRows)); + // print_rr($mappedRows);//die(); + $result = $tpaApiDataModel->insertBatchWithChunkLog($mappedRows,500,('FILE_ID_'.$file_id)); + // unlink($file_array['json_file_path']); // delete temp json file + } + + + // ------------------------------------------------------------------------------------------------------------- + // For testing purpose only - to trigger batch creation API with sample data without going through the entire flow of file upload and processing. This can be removed later. + // ------------------------------------------------------------------------------------------------------------- + + public function createEnrollmentBatch() + { + $client_id = $this->request->getGet('client_id'); + $client_branch_id = $this->request->getGet('client_branch_id'); + $policy_id = $this->request->getGet('policy_id'); + $event = $this->request->getGet('event'); + + //fetch token + $tokenResponse = $this->generateAuthToken(); + if (!$tokenResponse || empty($tokenResponse['data']['access_token'])) { + return $this->response->setJSON([ + 'status' => false, + 'message' => 'Token generation failed.', + 'data' => $tokenResponse + ]); + } + $token = $tokenResponse['data']['access_token']; + + + $url = env('ICICI_BASE_URL').'/batchcreation'; + $headers = [ + 'Authorization: Bearer ' . $token, + 'Content-Type: application/json', + ]; + + + //Prepare body data + // $db = \Config\Database::connect(); + // $data = $db->table('employee_polices ep') + // ->select('cp.policy_no as policyNumber, cp.cd_ac_no as CDBGAccountNumber, + // e.id,e.emp_code as MemberEmpId, e.doj as DOJ, e.name as InsuredName, e.dob as DOB, e.relationship as Relationship, + // e.gender as Gender, ep.date_coverage as DOC,ep.basic_cover_si as SumInsured, e.email_corporate as EmailId + // ') + // ->join('employees e', 'e.id = ep.employee_id') + // ->join('client_policy cp', 'ep.client_policy_id = cp.id') + // ->where('ep.client_policy_id', $policy_id) + // ->where('ep.status', 'active') + // ->where('ep.is_active', 1) + // // ->where('ep.uhid', null) + // ->get() + // ->getResultArray(); + + // $body = $this->formatPolicyData($data); + // dd($body); + + + // $body = [ + // "PolicyNumber" => "4016/PPN/A/O/53167743/00/000", + // "CDBGAccountNumber" => "CD-MUM-0026", + // "CorrelationId" => "550e8400-e29b-41d4-a716-446655440016", + // "MemberDetails" => [ + // [ + // "MemberEmpId" => "EMPID3625562", + // "DOJ" => "21-MAR-2019", + // "InsuredName" => "Jeeva", + // "DOB" => "7-JUL-1993", + // "Relationship" => "SELF", + // "Gender" => "MALE", + // "DOC" => '28-Oct-2025', + // "SumInsured" => "500000", + // "EmailId" => "Jeeva@GMAIL.COM", + // "FlagStatus" => "A" + // ], + // [ + // "MemberEmpId" => "EMPID3625562", + // "DOJ" => "21-MAR-2019", + // "InsuredName" => "Muthu", + // "DOB" => "8-AUG-1970", + // "Relationship" => "MOTHER", + // "Gender" => "FEMALE", + // "DOC" => '28-Oct-2025', + // "EmailId" => "Muthu@GMAIL.COM", + // "FlagStatus" => "A" + // ], + // ] + // ]; + + + $body = [ + "PolicyNumber" => "4016/PPN/A/O/53185987/00/000", + "CDBGAccountNumber" => "CD-MUM-0026", + "CorrelationId" => "550e8400-e29b-41d4-a716-446655440026", + "MemberDetails" => [ + [ + "MemberEmpId" => "EMPID3625567", + "DOJ" => "21-MAR-2019", + "InsuredName" => "sanjeev", + "DOB" => "7-JUL-1993", + "Relationship" => "SELF", + "Gender" => "MALE", + "DOC" => '10-Mar-2026', + "SumInsured" => "500000", + "EmailId" => "sanjeev@GMAIL.COM", + "FlagStatus" => "A" + ], + [ + "MemberEmpId" => "EMPID3625567", + "DOJ" => "21-MAR-2019", + "InsuredName" => "bhavya", + "DOB" => "8-AUG-1970", + "Relationship" => "MOTHER", + "Gender" => "FEMALE", + "DOC" => '10-Mar-2026', + "EmailId" => "bhavya@GMAIL.COM", + "FlagStatus" => "A" + ], + ] + ]; + + $response = call_third_party_api($url, 'POST', $headers, $body, true); // true = raw body mode + // print_rr(json_encode($response));die(); + return $this->response->setJSON(['API'=>$url,'headers'=>$headers,'body'=>$body,'response'=>$response]); + } + + public function getEnrollmentBatchStatusOld() + { + helper('api'); + + //fetch token + $tokenResponse = $this->generateAuthToken(); + if (!$tokenResponse || empty($tokenResponse['data']['access_token'])) { + return $this->response->setJSON([ + 'status' => false, + 'message' => 'Token generation failed.', + 'data' => $tokenResponse + ]); + } + $token = $tokenResponse['data']['access_token']; + + + $url = env('ICICI_BASE_URL').'/batchstatus'; + $headers = [ + 'Authorization: Bearer ' . $token, + 'Content-Type: application/json' + ]; + + // dd($headers); + + $body = [ + "PolicyNumber" => "4016/PPN/A/O/53185987/00/000", + "BatchId" => "3746145", + "CorrelationId" => "550e8400-e29b-41d4-a716-446655440026" + ]; + + $response = call_third_party_api($url, 'POST', $headers, $body, true); + + return $this->response->setJSON(['API'=>$url,'headers'=>$headers,'body'=>$body,'response'=>$response]); + } + + public function fetchUHIDDetailsOld() + { + helper('api'); + + //fetch token + $tokenResponse = $this->generateAuthToken('esbgpauhid'); + // dd($tokenResponse); + if (!$tokenResponse || empty($tokenResponse['data']['access_token'])) { + return $this->response->setJSON([ + 'status' => false, + 'message' => 'Token generation failed.', + 'data' => $tokenResponse + ]); + } + $token = $tokenResponse['data']['access_token']; + + // print_rr($token); + + $url = env('ICICI_BASE_URL').'/fetchuhid'; + $headers = [ + 'Authorization: Bearer ' . $token, + 'Content-Type: application/json' + ]; + + $body = [ + "PolicyNumber" => "4016/PPN/A/O/53185987/00/001", + "IMID" => "201580517901", + "CorrelationId" => "550e8400-e29b-41d4-a716-446655440022" + ]; + + $response = call_third_party_api($url, 'POST', $headers, $body, true); + + // dd($response); + + return $this->response->setJSON(['API'=>$url,'headers'=>$headers,'body'=>$body,'response'=>$response]); + } + + + + + // data": { + // "policyNumber": "4016/PPN/A/O/53185987/00/000", + // "batchId": "3746144", + // "message": "Data Dumped Successfully", + // "status": true, + // "statusMessage": "SUCCESS", + // "correlationId": "550e8400-e29b-41d4-a716-446655440025" + // }, + + // "data": { + // "policyNumber": "4016/PPN/A/O/53185987/00/000", + // "batchId": "3746145", + // "message": "Data Dumped Successfully", + // "status": true, + // "statusMessage": "SUCCESS", + // "correlationId": "550e8400-e29b-41d4-a716-446655440026" + // }, diff --git a/app/Controllers/JobWorker.php b/app/Controllers/JobWorker.php index a8d12fac..f6d9f2eb 100755 --- a/app/Controllers/JobWorker.php +++ b/app/Controllers/JobWorker.php @@ -191,6 +191,10 @@ class JobWorker extends AdminController 'type' => 'CC', // Handler Category 'handler' => 'App\Controllers\VidalApiController', ], + 'VidalGetBenefDetailsV2' => [ + 'type' => 'CC', // Handler Category + 'handler' => 'App\Controllers\VidalApiController', + ], 'saveVidalAPIData' => [ 'type' => 'CC', // Handler Category 'handler' => 'App\Controllers\VidalApiController', @@ -254,6 +258,26 @@ class JobWorker extends AdminController 'ICICIPushEmployeeDetails' => [ 'type' => 'CC', // Handler Category 'handler' => 'App\Controllers\ICICILombardController', + ], + 'getEnrollmentBatchStatus' => [ + 'type' => 'CC', // Handler Category + 'handler' => 'App\Controllers\ICICILombardController', + ], + 'fetchUHIDDetails' => [ + 'type' => 'CC', // Handler Category + 'handler' => 'App\Controllers\ICICILombardController', + ], + 'saveICICILombardAPIData' => [ + 'type' => 'CC', // Handler Category + 'handler' => 'App\Controllers\ICICILombardController', + ], + 'updateEmployeeDataFromTpa' => [ + 'type' => 'CC', // Handler Category + 'handler' => 'App\Controllers\EmployeeController', + ], + 'updateTpaIdForNotInNhance' => [ + 'type' => 'CC', // Handler Category + 'handler' => 'App\Controllers\EmployeeController', ] ]; diff --git a/app/Controllers/LeadsController.php b/app/Controllers/LeadsController.php index 12f9ed38..9384b60d 100644 --- a/app/Controllers/LeadsController.php +++ b/app/Controllers/LeadsController.php @@ -506,7 +506,7 @@ class LeadsController extends BaseController 'errors' => ['required' => 'Claim Year is required for all entries.', 'regex_match' => 'Year must be in format YYYY-YYYY.'], ]; $rules['first_policy_type_.*'] = [ - 'rules' => 'required|regex_match[/^[a-zA-Z0-9_-]+$/]', + 'rules' => 'required|regex_match[/^[a-zA-Z0-9 _-]+$/]', 'errors' => ['required' => 'Policy Type is required in Claim History.', 'regex_match' => 'Policy Type only letters, numbers, space, hyphens and underscores are allowed', ], @@ -517,7 +517,7 @@ class LeadsController extends BaseController 'regex_match' => 'Date of Loss must be inValid format.'], ]; $rules['first_cause_of_loss.*'] = [ - 'rules' => 'required|regex_match[/^[a-zA-Z0-9\s_-]+$/]', + 'rules' => 'required|regex_match[/^[a-zA-Z0-9 _-]+$/]', 'errors' => [ 'required' => 'Cause of Loss is required.', 'regex_match' => 'Cause of Loss only letters, numbers, space, hyphens and underscores are allowed', @@ -6802,67 +6802,79 @@ class LeadsController extends BaseController public function handleMemberDataGPATotalSumInsurerFromExcel($params) { - $lead_id = $params['lead_id']; - $lead_data = $this->leadsModel->find((int) $lead_id); - // dd($lead_data); - $file_name_with_path = WRITEPATH . "/uploads/lead_files/" . $lead_data['file_name']; - // dd($file_name_with_path); + try { + $lead_id = $params['lead_id']; + $lead_data = $this->leadsModel->find((int) $lead_id); - if (! $lead_data) { - return ['status' => 'failed', 'message' => 'Opportunity data not found']; - } - - if ($lead_data['file_name']) { - - //check physical file - if (! file_exists($file_name_with_path)) { - - $message = "Lead Physcial file not found"; - $this->myLogger->logme('error', ($message . ' for file ' . $file_name_with_path)); - return ['status' => 'failed', 'message' => 'no physical file']; + if (! $lead_data) { + return ['status' => 'failed', 'message' => 'Opportunity data not found']; } - $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file_name_with_path); + $file_name_with_path = WRITEPATH . "/uploads/lead_files/" . $lead_data['file_name']; - //get members data - $members_sheet = $spreadsheet->getSheet(0); - $highestRowAndColumn = $members_sheet->getHighestRowAndColumn(); - // dd($highestRowAndColumn); + if ($lead_data['file_name']) { - $uncleaned_members = $members_sheet->rangeToArray('A1:' . $highestRowAndColumn['column'] . $highestRowAndColumn['row']); - // dd($uncleaned_members); + //check physical file + if (! file_exists($file_name_with_path)) { - $members = ExcelSanitizeHelper::sanitizeArrayData($uncleaned_members); - // dd($members); - - // Check column headings - $members_heading = $members[0]; - $available_col = []; - - $lower_headers = array_map('strtolower', $members_heading); - foreach ($lower_headers as $index => $header) { - if (preg_match('/^(sa\s*-\s*option|proposed\s+sum\s+insured)\s+\d+$/i', $header)) { - $column_name = $members_heading[$index]; - $sum = 0; - - for ($i = 1; $i < count($members); $i++) { - $cell_raw = $members[$i][$index] ?? ''; - $cell_clean = preg_replace('/[^0-9.\-]/', '', $cell_raw); // remove non-numeric chars - - if ($cell_clean !== '' && is_numeric($cell_clean)) { - $sum += (float) $cell_clean; - } - } - - $available_col[] = $sum; + $message = "Lead Physcial file not found"; + $this->myLogger->logme('error', ($message . ' for file ' . $file_name_with_path)); + return ['status' => 'failed', 'message' => 'no physical file']; } + + $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file_name_with_path); + + //get members data + $members_sheet = $spreadsheet->getSheet(0); + $highestRowAndColumn = $members_sheet->getHighestRowAndColumn(); + + // Read raw values and skip formula evaluation to avoid Calculation exceptions from malformed formulas. + $uncleaned_members = $members_sheet->rangeToArray( + 'A1:' . $highestRowAndColumn['column'] . $highestRowAndColumn['row'], + null, + false, + true, + false + ); + + $members = ExcelSanitizeHelper::sanitizeArrayData($uncleaned_members); + + // Check column headings + $members_heading = $members[0]; + $available_col = []; + + $lower_headers = array_map('strtolower', $members_heading); + foreach ($lower_headers as $index => $header) { + if (preg_match('/^(sa\s*-\s*option|proposed\s+sum\s+insured)\s+\d+$/i', $header)) { + $sum = 0; + + for ($i = 1; $i < count($members); $i++) { + $cell_raw = $members[$i][$index] ?? ''; + $cell_clean = preg_replace('/[^0-9.\-]/', '', $cell_raw); // remove non-numeric chars + + if ($cell_clean !== '' && is_numeric($cell_clean)) { + $sum += (float) $cell_clean; + } + } + + $available_col[] = $sum; + } + } + + return $available_col; } - // dd($available_col); - return $available_col; - } + return []; + } catch (\Throwable $e) { + log_message('error', 'Exception in handleMemberDataGPATotalSumInsurerFromExcel: {message}', [ + 'message' => $e->getMessage(), + ]); + log_message('error', 'Trace: {trace}', [ + 'trace' => $e->getTraceAsString(), + ]); - return []; + return []; + } } public function generateDemographyDataTable($param = []) diff --git a/app/Controllers/MasterController.php b/app/Controllers/MasterController.php index 4087b301..75fd9800 100755 --- a/app/Controllers/MasterController.php +++ b/app/Controllers/MasterController.php @@ -420,7 +420,7 @@ class MasterController extends AdminController 'state' => [ 'label' => 'State', - 'rules' => 'required|regex_match[/^[a-zA-Z\s\-]+$/]', + 'rules' => 'required|regex_match[/^[a-zA-Z0-9\/\-\_\.\s]+$/]', 'errors' => [ 'required' => 'State is required.', 'regex_match' => 'State name can only contain letters, spaces, and hyphens.' @@ -661,7 +661,7 @@ class MasterController extends AdminController 'state' => [ 'label' => 'State', - 'rules' => 'required|regex_match[/^[a-zA-Z\s\-]+$/]', + 'rules' => 'required|regex_match[/^[a-zA-Z0-9\/\-\_\.\s]+$/]', 'errors' => [ 'required' => 'State is required.', 'regex_match' => 'State name can only contain letters, spaces, and hyphens.' @@ -1057,7 +1057,7 @@ class MasterController extends AdminController 'state' => [ 'label' => 'State', - 'rules' => 'required|regex_match[/^[a-zA-Z\s\-]+$/]', + 'rules' => 'required|regex_match[/^[a-zA-Z0-9\/\-\_\.\s]+$/]', 'errors' => [ 'required' => 'State is required.', 'regex_match' => 'State name can only contain letters, spaces, and hyphens.' @@ -1370,7 +1370,7 @@ class MasterController extends AdminController 'state' => [ 'label' => 'State', - 'rules' => 'required|regex_match[/^[a-zA-Z\s\-]+$/]', + 'rules' => 'required|regex_match[/^[a-zA-Z0-9\/\-\_\.\s]+$/]', 'errors' => [ 'required' => 'State is required.', 'regex_match' => 'State name can only contain letters, spaces, and hyphens.' @@ -3590,7 +3590,7 @@ class MasterController extends AdminController ], 'state' => [ 'label' => 'State', - 'rules' => 'required|regex_match[/^[a-zA-Z\s\-]+$/]', + 'rules' => 'required|regex_match[/^[a-zA-Z0-9\/\-\_\.\s]+$/]', 'errors' => [ 'required' => 'State is required.', 'regex_match' => 'State name can only contain letters, spaces, and hyphens.' diff --git a/app/Controllers/MediAssistApiController.php b/app/Controllers/MediAssistApiController.php index 092ec7c2..3a70329b 100644 --- a/app/Controllers/MediAssistApiController.php +++ b/app/Controllers/MediAssistApiController.php @@ -845,6 +845,7 @@ class MediAssistApiController extends BaseController tm.id, tm.tpa_no as memberId, tm.tpa_claim_push_reference_no as claimRefNo, + tm.doa, cp.policy_no as policyNo, cp.policy_start_date as startDate, cp.policy_end_date as endDate, diff --git a/app/Controllers/TestingController.php b/app/Controllers/TestingController.php index 094ef653..eecbfb45 100644 --- a/app/Controllers/TestingController.php +++ b/app/Controllers/TestingController.php @@ -10,6 +10,7 @@ use App\Models\BatchFileModel; use App\Models\InsurerBranchModel; use App\Models\RFQModel; use App\Models\EmployeeModel; +use App\Libraries\JobStatusService; use CodeIgniter\HTTP\ResponseInterface; use CodeIgniter\API\ResponseTrait; use Dompdf\Dompdf; @@ -48,6 +49,110 @@ class TestingController extends BaseController ]); } + /** + * Get latest job status by job name. + * Supports: + * - GET -> ?job_name=... + * - POST -> job_name in form/json payload + */ + public function jobStatus() + { + $jobName = trim((string) ($this->request->getGet('job_name') ?? '')); + + if ($jobName === '') { + $jobName = trim((string) ($this->request->getPost('job_name') ?? '')); + } + + if ($jobName === '') { + $jsonPayload = $this->request->getJSON(true); + if (is_array($jsonPayload)) { + $jobName = trim((string) ($jsonPayload['job_name'] ?? '')); + } + } + + $service = new JobStatusService(); + $result = $service->getJobStatusByName($jobName); + + $httpCode = 200; + if (($result['success'] ?? false) !== true) { + if ($jobName === '') { + $httpCode = 422; + } elseif (($result['message'] ?? '') === 'No job record found for given name.') { + $httpCode = 404; + } else { + $httpCode = 500; + } + } + + return $this->response->setStatusCode($httpCode)->setJSON($result); + } + + /** + * QA-only: invokes EmployeeController::updateTpaIdForNotInNhance. + * Routed under /util with authMVC — must be logged into the admin app. + * + * GET or POST: batch_file_id (required), file_id (optional, omit or 0 to skip file_id filter). + */ + public function qaUpdateTpaIdForNotInNhance() + { + $batchFileId = $this->request->getGet('batch_file_id'); + if ($batchFileId === null || $batchFileId === '') { + $batchFileId = $this->request->getPost('batch_file_id'); + } + + $fileId = $this->request->getGet('file_id'); + if ($fileId === null || $fileId === '') { + $fileId = $this->request->getPost('file_id'); + } + + if ($batchFileId === null || $batchFileId === '') { + return $this->response->setStatusCode(422)->setJSON([ + 'success' => false, + 'message' => 'batch_file_id is required (query string or POST).', + ]); + } + + $params = [ + 'batch_file_id' => (int) $batchFileId, + 'file_id' => ($fileId !== null && $fileId !== '') ? (int) $fileId : 0, + ]; + + $employeeController = new EmployeeController(); + $employeeController->initController($this->request, $this->response, service('logger')); + $result = $employeeController->updateTpaIdForNotInNhance($params); + + return $this->response->setJSON(array_merge($result, ['params' => $params])); + } + + /** + * QA-only: invokes EmployeeController::updateEmployeeDataFromTpa (Need to Review → DB updates, no Excel). + * Routed under /util with authMVC. + * + * GET or POST: batch_file_id (required). + */ + public function qaUpdateEmployeeDataFromTpa() + { + $batchFileId = $this->request->getGet('batch_file_id'); + if ($batchFileId === null || $batchFileId === '') { + $batchFileId = $this->request->getPost('batch_file_id'); + } + + if ($batchFileId === null || $batchFileId === '') { + return $this->response->setStatusCode(422)->setJSON([ + 'success' => false, + 'message' => 'batch_file_id is required (query string or POST).', + ]); + } + + $employeeController = new EmployeeController(); + $employeeController->initController($this->request, $this->response, service('logger')); + $result = $employeeController->updateEmployeeDataFromTpa([ + 'batch_file_id' => (int) $batchFileId, + ]); + + return $this->response->setJSON($result); + } + public function testcli() { echo "hi"; @@ -1305,7 +1410,7 @@ class TestingController extends BaseController ], 200); } - /** + /** * Test Wellness SSO token generation for Medi Assist (MediBuddy). * * This uses the token-based authentication details shared by Medi Assist: @@ -1609,4 +1714,48 @@ class TestingController extends BaseController ], ]; } + + public function getVidalEnrollmentInfo() + { + helper('api'); + + $url = 'https://devapigw.vidalhealthtpa.com/partner-integration/enrollment/info'; + + $subscriptionKey = getenv('VIDAL_API_SUBSCRIPTION_KEY'); + if (empty($subscriptionKey)) { + return $this->response->setStatusCode(500)->setJSON([ + 'error' => 'Missing VIDAL_API_SUBSCRIPTION_KEY in env', + ]); + } + + $policyNo = '000/VZXSY'; + $startIndex = 1; + $endIndex = 5; + + $body = [ + 'policyNo' => $policyNo, + 'startIndex' => $startIndex, + 'endIndex' => $endIndex, + ]; + + $headers = [ + 'Content-Type: application/json', + 'ocp-apim-subscription-key: ' . $subscriptionKey, + ]; + + $method = "POST"; + + $rawResponse = call_third_party_api($url, $method, $headers, $body); + + return $this->response->setStatusCode(200)->setJSON([ + 'request' => [ + 'url' => $url, + 'method' => $method, + 'headers' => $headers, + 'body' => $body, + ], + 'raw_response' => $rawResponse, + ]); + } + } diff --git a/app/Controllers/TicketController.php b/app/Controllers/TicketController.php index 49d4e615..146b748e 100644 --- a/app/Controllers/TicketController.php +++ b/app/Controllers/TicketController.php @@ -576,7 +576,7 @@ class TicketController extends BaseController ->where('tm.is_active', 1) ->whereNotIn('claim_status_id', [11, 12, 13, 22, 24, 32, 34, 42, 44, 47, 53, 58, 65]) ->orderBy('tm.id', 'DESC') - ->limit(100); + ->limit(500); $data = $query->get()->getResultArray(); @@ -3223,6 +3223,42 @@ class TicketController extends BaseController return $date && $date->format($format) === $value; } + /** + * Claim upload URL row: allow http(s) with path, query, port; bare host with TLD; localhost; IPv4/IPv6. + * Replaces the old strict regex that rejected ?query= and long TLDs. + */ + private function isClaimUploadUrl(string $s): bool + { + $v = trim($s); + if ($v === '' || strlen($v) > 2048) { + return false; + } + if (! preg_match('#^https?://#i', $v)) { + $v = 'https://' . $v; + } + $parts = parse_url($v); + if ($parts === false || empty($parts['host'])) { + return false; + } + $scheme = strtolower($parts['scheme'] ?? ''); + if ($scheme !== 'http' && $scheme !== 'https') { + return false; + } + $host = strtolower($parts['host']); + if ($host === 'localhost') { + return true; + } + $hostForIp = $host; + if (strlen($host) > 2 && $host[0] === '[' && substr($host, -1) === ']') { + $hostForIp = substr($host, 1, -1); + } + if (filter_var($hostForIp, FILTER_VALIDATE_IP)) { + return true; + } + + return strpos($host, '.') !== false; + } + public function upload_url() { @@ -3249,10 +3285,9 @@ class TicketController extends BaseController ], 'url.*' => [ 'label' => 'URL', - 'rules' => 'if_exist|required|regex_match[/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/]', + 'rules' => 'if_exist|required', 'errors' => [ - 'required' => 'URL is required.', - 'regex_match' => 'The URL format is invalid. Example: www.google.com or https://google.com' + 'required' => 'URL is required.', ] ], ]; @@ -3266,6 +3301,22 @@ class TicketController extends BaseController ]); } + if (! empty($data['url']) && is_array($data['url'])) { + foreach ($data['url'] as $idx => $singleUrl) { + $singleUrl = (string) $singleUrl; + if (trim($singleUrl) !== '' && ! $this->isClaimUploadUrl($singleUrl)) { + return $this->response->setStatusCode(400)->setJSON([ + 'status' => false, + 'message' => 'Input validation failed', + 'code' => 400, + 'errors' => [ + 'url.' . $idx => 'The URL format is invalid. Use https://example.com/path?x=1 or example.com', + ], + ]); + } + } + } + $get_file_data = $this->request->getFiles('file_upload') ?? []; $ticket_id = $data['ticket_id_url']; @@ -3840,7 +3891,7 @@ class TicketController extends BaseController ]); } - // YOUR REQUIRED REGEX RULE + // Same charset as claim upload `docs_name.*` / client `ticketdocname` if (!preg_match('/^[a-zA-Z0-9_\- ]+$/', $doc['document_name'])) { return $this->response->setStatusCode(400)->setJSON([ 'status' => false, @@ -3848,7 +3899,7 @@ class TicketController extends BaseController 'message' => 'Input validation failed', 'errors' => [ 'required_docs' => - "Document name '{$doc['document_name']}' can only contain letters, numbers, hyphens and underscores" + "Document Name can only contain letters, numbers, hyphens, and underscores (row " . ($index + 1) . ")" ] ]); } diff --git a/app/Controllers/VidalApiController.php b/app/Controllers/VidalApiController.php index 704dd8d5..23394231 100644 --- a/app/Controllers/VidalApiController.php +++ b/app/Controllers/VidalApiController.php @@ -19,6 +19,14 @@ class VidalApiController extends BaseController protected $claim_type_array; protected $ticketController; + /** + * Vidal `relation` (lowercase) → Nhance relation (lowercase). + * Populated once from {@see self::vidalRelationshipReferenceMap()} (values match public/tmp/relationship.csv; that file is reference only, not read at runtime). + * + * @var array + */ + protected array $vidalRelationshipMap = []; + public function __construct() { $this->db = \Config\Database::connect(); @@ -26,6 +34,8 @@ class VidalApiController extends BaseController $this->ticketController = new TicketController(); $this->claim_type_array = $this->ticketController->claimType; + + $this->vidalRelationshipMap = self::vidalRelationshipReferenceMap(); } @@ -455,6 +465,7 @@ class VidalApiController extends BaseController tm.tpa_no as memberId, tm.tpa_claim_push_reference_no as claimRefNo, tm.tpa_claim_id as claimID, + tm.doa, cp.policy_no as policyNo, cp.policy_start_date as startDate, cp.policy_end_date as endDate, @@ -1022,6 +1033,522 @@ class VidalApiController extends BaseController } } + public function VidalGetBenefDetailsV2($requestData = null) + { + $requestData = is_array($requestData) ? $requestData : []; + $function_calling_type = $requestData['return_type'] ?? 'job'; + + try { + + helper('api'); + + $url = $this->vidalEnrollmentInfoApiUrl(); + $method = 'POST'; + + $subscriptionKey = getenv('VIDAL_API_SUBSCRIPTION_KEY'); + if (empty($subscriptionKey)) { + log_message('error', 'VIDAL V2 - TPA ID Pull | VIDAL_API_SUBSCRIPTION_KEY missing'); + if ($function_calling_type === 'job') { + return ['status' => false, 'message' => 'VIDAL_API_SUBSCRIPTION_KEY required']; + } + + return $this->respond(['status' => false, 'message' => 'VIDAL_API_SUBSCRIPTION_KEY required']); + } + + $headers = [ + 'Content-Type: application/json', + 'ocp-apim-subscription-key: ' . $subscriptionKey, + ]; + + $policyNo = $requestData['policy_no'] ?? null; + $client_policy_id = $requestData['client_policy_id'] ?? null; + + if (empty($policyNo)) { + log_message('error', 'VIDAL V2 - TPA ID Pull | policy_no missing in request'); + if ($function_calling_type === 'job') { + return ['status' => false, 'message' => 'policy_no required']; + } + + return $this->respond(['status' => false, 'message' => 'policy_no required']); + } + + if (empty($client_policy_id)) { + log_message('error', 'VIDAL V2 - TPA ID Pull | client_policy_id missing in request'); + if ($function_calling_type === 'job') { + return ['status' => false, 'message' => 'client_policy_id required']; + } + + return $this->respond(['status' => false, 'message' => 'client_policy_id required']); + } + + log_message('error', "VIDAL V2 - TPA ID Pull | called for policy_no: {$policyNo} , client_policy_id: {$client_policy_id}"); + + $batchFiles = $this->db->table('batch_files f') + ->select('f.created_at') + ->where('f.client_policy_id', $client_policy_id) + ->where('f.insurer_or_tpa', 'tpa') + ->where('f.actions', 'export') + ->get() + ->getResultArray(); + + if (empty($batchFiles)) { + log_message('error', 'VIDAL V2 - TPA ID Pull FAILED | batchFiles is empty for this tpa id pull request'); + if ($function_calling_type === 'job') { + return ['status' => false, 'message' => 'batchFiles not found']; + } + + return $this->respond(['status' => false, 'message' => 'batchFiles not found']); + } + + $pageSize = 100; + $startIndex = 1; + $allBenef = []; + + while (true) { + $endIndex = $startIndex + $pageSize - 1; + $body = [ + 'policyNo' => $policyNo, + 'startIndex' => $startIndex, + 'endIndex' => $endIndex, + ]; + + log_message('error', 'VIDAL V2 - TPA ID Pull | API params ' . json_encode([$url, $method, $headers, $body])); + + $response = call_third_party_api($url, $method, $headers, $body); + + if ($response['status'] !== true) { + if (isset($requestData['file_id']) && !empty($requestData['file_id'])) { + $file_model = new BatchFileModel(); + $file_model->where('id', $requestData['file_id'])->set('status', 'failed-8')->update(); + log_message('error', "VIDAL V2 - TPA ID Pull | Files table status updated for the file id : {$requestData['file_id']}"); + } else { + log_message('error', 'VIDAL V2 - TPA ID Pull | Failed to update file table status.'); + } + + log_message('error', 'VIDAL V2 - TPA ID Pull API FAILED | API failed: ' . json_encode($response)); + + if ($function_calling_type === 'job') { + return ['status' => false, 'message' => 'API call failed', 'data' => $response]; + } + + return $this->respond(['status' => false, 'message' => 'API call failed', 'data' => $response]); + } + + $apiRoot = $response['data'] ?? []; + if (($apiRoot['status'] ?? '') !== 'SUCCESS' + || (array_key_exists('successful', $apiRoot) && $apiRoot['successful'] === false)) { + log_message('error', 'VIDAL V2 - TPA ID Pull API FAILED | envelope: ' . json_encode($apiRoot)); + + if (isset($requestData['file_id']) && !empty($requestData['file_id'])) { + $file_model = new BatchFileModel(); + $file_model->where('id', $requestData['file_id'])->set('status', 'failed-8')->update(); + } + + if ($function_calling_type === 'job') { + return ['status' => false, 'message' => 'API call failed', 'data' => $apiRoot]; + } + + return $this->respond(['status' => false, 'message' => 'API call failed', 'data' => $apiRoot]); + } + + $chunk = $apiRoot['data'] ?? null; + if (!is_array($chunk)) { + log_message('error', 'VIDAL V2 - TPA ID Pull FAILED | data is not an array: ' . json_encode($apiRoot)); + break; + } + + if (count($chunk) === 0) { + if ($startIndex === 1) { + log_message('error', "VIDAL V2 - TPA ID Pull FAILED | empty data on first page"); + if (isset($requestData['file_id']) && !empty($requestData['file_id'])) { + $file_model = new BatchFileModel(); + $file_model->where('id', $requestData['file_id'])->set('status', 'failed-8')->update(); + } + if ($function_calling_type === 'job') { + return ['status' => false, 'message' => 'No enrollment records returned', 'data' => $apiRoot]; + } + + return $this->respond(['status' => false, 'message' => 'No enrollment records returned', 'data' => $apiRoot]); + } + break; + } + + foreach ($chunk as $rec) { + if (is_array($rec)) { + $allBenef[] = $this->normalizeVidalEnrollmentRecordToDependentFormat($rec); + } + } + + log_message('error', 'VIDAL V2 - TPA ID Pull | Fetched ' . count($chunk) . ' records (page startIndex=' . $startIndex . ')'); + + if (count($chunk) < $pageSize) { + break; + } + + $startIndex += $pageSize; + } + + $json = json_encode($allBenef, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); + $filePath = WRITEPATH . 'tmp/' . time() . '_' . $requestData['file_id'] . '.json'; + file_put_contents($filePath, $json); + + Jobs::addJob(['job_name' => 'saveVidalAPIData', 'payload' => ['file_id' => $requestData['file_id'], 'json_file_path' => $filePath]]); + + $employeePolicyModel = new EmployeePolicyModel(); + $employeePolicyData = $employeePolicyModel + ->select(' + employees.*, + employee_polices.id as emp_policy_id, + employee_polices.client_policy_id, + ') + ->join('employees', 'employees.id = employee_polices.employee_id') + ->where('employee_polices.is_active', 1) + ->where('employee_polices.status', 'active') + ->where('employees.is_active', 1) + ->where('employees.emp_status', 'active') + ->where('employee_polices.tpa_id IS NULL') + ->where('employee_polices.client_policy_id', $client_policy_id) + ->findAll(); + $batch_file_success = 'success'; + $updated = 0; + $totalCount = count($employeePolicyData); + $employee_policy_ids = []; + foreach ($employeePolicyData as $policy_data) { + + $hasMatchForThisPolicy = false; + + foreach ($allBenef as $row) { + if ( + strtolower(trim($policy_data['name'] ?? '')) === strtolower(trim($row['name'] ?? '')) && + ($policy_data['emp_code'] ?? '') === ($row['empNo'] ?? '') && + strtolower(trim($policy_data['relationship'] ?? '')) === strtolower(trim(str_replace('-', ' ', $row['relationship'] ?? ''))) && + ($policy_data['gender'] ?? '') === ($row['gender'] ?? '') && + ($policy_data['dob'] ?? '') === (change_date_format($row['dob'], 'Y-m-d H:i:s') ?? '') + ) { + + $hasMatchForThisPolicy = true; + + $sql = 'UPDATE employee_polices + SET tpa_id = :tpa_id: + WHERE id = :emp_policy_id:'; + $this->db->query($sql, ['tpa_id' => $row['enrollmentId'], 'emp_policy_id' => $policy_data['emp_policy_id']]); + + if (strtolower(trim($policy_data['relationship'])) === 'self') { + $employee_policy_ids[] = $policy_data['emp_policy_id']; + } + + if ($this->db->affectedRows() > 0) { + $updated++; + log_message('error', "VIDAL V2 - TPA ID Pull | Updated tpa_id={$row['enrollmentId']} for emp_code={$row['empNo']} policy={$row['policyNumber']}"); + } else { + log_message('error', "VIDAL V2 - TPA ID Pull | No update (already set or not matched) for emp_code={$row['empNo']} policy={$row['policyNumber']}"); + } + + } + + } + + if (!$hasMatchForThisPolicy) { + + $nhanceSideData = [ + 'name' => $policy_data['name'] ?? null, + 'emp_code' => $policy_data['emp_code'] ?? null, + 'relationship' => $policy_data['relationship'] ?? null, + 'gender' => $policy_data['gender'] ?? null, + 'dob' => $policy_data['dob'] ?? null, + ]; + $batch_file_success = 'partially success'; + + log_message( + 'error', + 'VIDAL V2 - TPA ID Pull | No match for Nhance = ' . json_encode($nhanceSideData) + ); + } + + } + + if (!empty($employee_policy_ids)) { + log_message('error', 'sendMailForDownloadingECard JOB PUSHED (V2).'); + Jobs::addJob(['job_name' => 'sendMailForDownloadingECard', 'payload' => ['ids' => $employee_policy_ids, 'client_policy_id' => $client_policy_id]]); + } + + if (isset($requestData['file_id']) && !empty($requestData['file_id'])) { + $file_model = new BatchFileModel(); + + $file_model->where('id', $requestData['file_id'])->set('status', $batch_file_success)->update(); + log_message('error', "VIDAL V2 - Files table status updated for the file id : {$requestData['file_id']}"); + } else { + log_message('error', 'VIDAL V2 - Failed to update file table status.'); + } + + log_message('error', "VIDAL V2 - TPA ID Pull SUCCESS | completed. Total fetched={$totalCount}, updated={$updated}"); + + if ($function_calling_type === 'job') { + return [ + 'status' => true, + 'message' => 'Updated successfully', + 'total_fetched' => $totalCount, + 'total_updated' => $updated, + ]; + } + + return $this->respond([ + 'status' => true, + 'message' => 'Updated successfully', + 'total_fetched' => $totalCount, + 'total_updated' => $updated, + ]); + + } catch (\Throwable $th) { + + if (isset($requestData['file_id']) && !empty($requestData['file_id'])) { + $file_model = new BatchFileModel(); + $file_model->where('id', $requestData['file_id'])->set('status', 'failed-8')->update(); + log_message('error', "VIDAL V2 - Files table status updated for the file id : {$requestData['file_id']}"); + } else { + log_message('error', 'VIDAL V2 - Failed to update file table status.'); + } + + $errorData = [ + 'message' => $th->getMessage(), + 'file' => $th->getFile(), + 'line' => $th->getLine(), + 'code' => $th->getCode(), + 'trace' => $th->getTraceAsString(), + 'trace_array' => $th->getTrace(), + 'function' => $th->getTrace()[0]['function'] ?? null, + 'class' => $th->getTrace()[0]['class'] ?? null, + ]; + + log_message('error', 'VIDAL V2 - Exception thrown while calling GetBenefDetailsV2 API: ' . json_encode($errorData)); + if ($function_calling_type === 'job') { + return ['status' => false, 'message' => 'API call failed', 'data' => $errorData]; + } + + return $this->respond(['status' => false, 'message' => 'API call failed', 'data' => $errorData]); + } + } + + + /** + * Nhance relationship => list of Vidal `relation` labels (any case). Edit the grouped list only; the flat map is built here. + * Reference: public/tmp/relationship.csv (documentation only). + * + * @return array lowercase Vidal label (and hyphen/space variant) => Nhance relation key + */ + private static function vidalRelationshipReferenceMap(): array + { + $relationshipGrouped = [ + + 'self' => [ + 'SELF', + 'EMPLOYER', + 'EMPLOYEE', + 'EMPLOYEES', + ], + + 'spouse' => [ + 'SPOUSE', + 'PARTNER', + 'HUSBAND', + 'HUSBAND (2)', + 'HUSBAND (3)', + 'HUSBAND (4)', + 'HUSBAND (5)', + 'WIFE', + 'WIFE (2)', + 'WIFE (3)', + 'WIFE (4)', + 'WIFE (5)', + ], + + 'father' => [ + 'FATHER', + 'FATHER (2)', + 'FATHER (3)', + 'FATHER (4)', + 'FATHER (5)', + ], + + 'mother' => [ + 'MOTHER', + 'MOTHER (2)', + 'MOTHER (3)', + 'MOTHER (4)', + 'MOTHER (5)', + ], + + 'son' => [ + 'SON', + 'SON (2)', + 'SON (3)', + 'SON (4)', + 'SON (5)', + ], + + 'daughter' => [ + 'DAUGHTER', + 'DAUGHTER (2)', + 'DAUGHTER (3)', + 'DAUGHTER (4)', + 'DAUGHTER (5)', + ], + + 'father in law' => [ + 'FATHER-IN-LAW', + 'FATHER-IN-LAW (2)', + ], + + 'mother in law' => [ + 'MOTHER-IN-LAW', + 'MOTHER-IN-LAW (2)', + ], + ]; + + return self::flattenVidalRelationshipGroupedToLookupMap($relationshipGrouped); + } + + /** + * @param array> $grouped + * + * @return array + */ + private static function flattenVidalRelationshipGroupedToLookupMap(array $grouped): array + { + $map = []; + + foreach ($grouped as $nhanceRelation => $vidalLabels) { + foreach ($vidalLabels as $label) { + $label = trim((string) $label); + if ($label === '') { + continue; + } + + $variants = [ + strtolower($label), + strtolower(str_replace('-', ' ', $label)), + ]; + + foreach (array_unique($variants) as $key) { + $key = trim(preg_replace('/\s+/', ' ', $key)); + if ($key === '') { + continue; + } + $map[$key] = $nhanceRelation; + } + } + } + + return $map; + } + + /** + * Map Vidal enrollment `relation` text to Nhance `employees.relationship` / `tpa_api_data.relation` style (lowercase). + */ + private function mapVidalRelationshipToNhance(?string $vidalRelationDescription): string + { + $raw = trim((string) $vidalRelationDescription); + if ($raw === '') { + return ''; + } + + foreach (self::vidalRelationLookupKeyVariants($raw) as $key) { + if (isset($this->vidalRelationshipMap[$key])) { + return $this->vidalRelationshipMap[$key]; + } + } + + if (strcasecmp($raw, 'Employee') === 0 || strcasecmp($raw, 'Employees') === 0) { + return 'self'; + } + + return strtolower(str_replace('-', ' ', $raw)); + } + + /** + * Keys must stay in sync with {@see self::flattenVidalRelationshipGroupedToLookupMap()}. + * + * @return list + */ + private static function vidalRelationLookupKeyVariants(string $raw): array + { + $base = strtolower(trim($raw)); + $withHyphensAsSpaces = strtolower(str_replace('-', ' ', $base)); + $collapsed = trim(preg_replace('/\s+/', ' ', $withHyphensAsSpaces)); + + return array_values(array_unique(array_filter([$base, $collapsed]))); + } + + private function normalizeVidalEnrollmentDateToYmd($value): ?string + { + if ($value === null || $value === '') { + return null; + } + if (is_numeric($value)) { + return null; + } + $s = trim((string) $value); + $ts = strtotime(str_replace('/', '-', $s)); + + return $ts ? date('Y-m-d', $ts) : null; + } + + /** + * Map Enrollment Dump API row (see public/tmp/Enrollment Dump API.docx) to the dependent + * shape used by VidalGetBenefDetailsV2 matching and saveVidalAPIData. + */ + private function normalizeVidalEnrollmentRecordToDependentFormat(array $row): array + { + $rel = trim((string) ($row['relation'] ?? '')); + $relationship = $this->mapVidalRelationshipToNhance($rel); + + $si = $row['baseSumInsured'] ?? null; + $si = $si !== null && $si !== '' ? trim((string) $si) : null; + + return [ + 'name' => trim((string) ($row['beneficiaryName'] ?? '')), + 'empNo' => trim((string) ($row['employeeNo'] ?? '')), + 'relationship' => $relationship, + 'vidal_relation_raw' => $rel, + 'gender' => $row['gender'] ?? '', + 'dob' => $row['dateOfBirth'] ?? null, + 'enrollmentId' => trim((string) ($row['membershipNo'] ?? '')), + 'policyNumber' => trim((string) ($row['policyNumber'] ?? '')), + 'age' => $row['age'] ?? null, + 'si' => $si, + 'doj' => $this->normalizeVidalEnrollmentDateToYmd($row['dateOfJoining'] ?? null), + 'desc' => $this->buildVidalEnrollmentDescForTpaRow($row), + ]; + } + + /** + * Fills tpa_api_data.desc from enrollment fields (product / remarks / insured name). + */ + private function buildVidalEnrollmentDescForTpaRow(array $row): ?string + { + $chunks = array_filter([ + trim((string) ($row['productName'] ?? '')), + trim((string) ($row['remarks'] ?? '')), + trim((string) ($row['insuredName'] ?? '')), + ], static fn ($v) => $v !== ''); + + if ($chunks === []) { + return null; + } + + return substr(implode(' | ', $chunks), 0, 65000); + } + + private function vidalEnrollmentInfoApiUrl(): string + { + $base = rtrim((string) getenv('VIDAL_API_BASE_URL'), '/'); + if ($base !== '' && preg_match('#/api$#', $base)) { + return preg_replace('#/api$#', '', $base) . '/enrollment/info'; + } + + return 'https://devapigw.vidalhealthtpa.com/partner-integration/enrollment/info'; + } + public function saveVidalAPIData($array) { $file_id = $array['file_id']; @@ -1045,20 +1572,49 @@ class VidalApiController extends BaseController foreach ($records as $row) { + $rawVidalRel = trim((string) ($row['vidal_relation_raw'] ?? '')); + if ($rawVidalRel !== '') { + $relation = $this->mapVidalRelationshipToNhance($rawVidalRel); + } else { + $relation = trim(strtolower((string) ($row['relationship'] ?? ''))); + } + + $si = $row['si'] ?? null; + $si = $si !== null && $si !== '' ? trim((string) $si) : null; + + $doj = null; + if (!empty($row['doj'])) { + $dojRaw = $row['doj']; + if (is_string($dojRaw) && preg_match('/^\d{4}-\d{2}-\d{2}/', $dojRaw)) { + $doj = substr($dojRaw, 0, 10); + } else { + $doj = $this->normalizeVidalEnrollmentDateToYmd($dojRaw); + } + } + + $descPieces = []; + if ($rawVidalRel !== '') { + $descPieces[] = 'Vidal relation: ' . $rawVidalRel; + } + $jsonDesc = trim((string) ($row['desc'] ?? '')); + if ($jsonDesc !== '') { + $descPieces[] = $jsonDesc; + } + $desc = $descPieces !== [] ? substr(implode(' | ', $descPieces), 0, 65000) : null; + $mappedRows[] = [ - 'file_id' => $file_id, // ← pass from controller - 'emp_code' => trim($row['empNo'] ?? ''), - - 'name' => trim($row['name'] ?? ''), - 'dob' => !empty($row['dob'] ?? null) ? date('Y-m-d', strtotime(str_replace('/', '-', $row['dob']))) : null, - - 'relation' => trim(strtolower($row['relationship'] ?? '')), - 'gender' => format_gender_v2($row['gender'] ?? null), - 'self' => strtolower($row['relationship'] ?? '') === 'self' ? 1 : 0, - - 'tpa_id' => trim($row['enrollmentId'] ?? null), - 'age' => is_numeric($row['age'] ?? null) ? (int) $row['age'] : null, - + 'file_id' => $file_id, + 'emp_code' => trim($row['empNo'] ?? ''), + 'name' => trim($row['name'] ?? ''), + 'dob' => !empty($row['dob'] ?? null) ? date('Y-m-d', strtotime(str_replace('/', '-', $row['dob']))) : null, + 'relation' => $relation, + 'gender' => format_gender_v2($row['gender'] ?? null), + 'self' => $relation === 'self' ? 1 : 0, + 'tpa_id' => trim($row['enrollmentId'] ?? null), + 'age' => is_numeric($row['age'] ?? null) ? (int) $row['age'] : null, + 'desc' => $desc, + 'si' => $si, + 'doj' => $doj, 'is_active' => 1, 'created_by' => $file_info[0]['created_by'] ?? null, ]; diff --git a/app/Controllers/VoloApiController.php b/app/Controllers/VoloApiController.php index 16d5f65b..79320a2b 100644 --- a/app/Controllers/VoloApiController.php +++ b/app/Controllers/VoloApiController.php @@ -533,6 +533,12 @@ class VoloApiController extends BaseController $dobYmd = $this->normalizeVoloDobToYmd($dobRaw); } + $dojRaw = $row['DOJ'] ?? $row['doj'] ?? null; + $dojYmd = null; + if ($dojRaw !== null && $dojRaw !== '') { + $dojYmd = $this->normalizeVoloDobToYmd($dojRaw); + } + $rel = trim((string) ($row['relation'] ?? '')); $mappedRows[] = [ 'file_id' => $file_id, @@ -544,6 +550,8 @@ class VoloApiController extends BaseController 'self' => in_array(strtoupper($rel), ['EMPLOYEE', 'SELF'], true) ? 1 : 0, 'tpa_id' => trim((string) ($row['memberId'] ?? '')), 'age' => isset($row['age']) && is_numeric($row['age']) ? (int) $row['age'] : null, + 'si' => $row['sumInsured'] ?? null, + 'doj' => $dojYmd, 'is_active' => 1, 'created_by' => $file_info[0]['created_by'] ?? null, ]; diff --git a/app/Libraries/JobStatusService.php b/app/Libraries/JobStatusService.php new file mode 100644 index 00000000..8c6f14a4 --- /dev/null +++ b/app/Libraries/JobStatusService.php @@ -0,0 +1,100 @@ +jobModel = $jobModel ?? new JobModel(); + } + + public function getJobStatusByName(string $jobName): array + { + $jobName = trim($jobName); + + if ($jobName === '') { + return $this->buildResponse(false, $jobName, 'Job name is required.'); + } + + try { + $job = $this->jobModel + ->where('name', $jobName) + ->orderBy('id', 'DESC') + ->first(); + + if (!$job) { + return $this->buildResponse(false, $jobName, 'No job record found for given name.'); + } + + return [ + 'success' => true, + 'job_name' => $jobName, + 'status' => $job['status'] ?? null, + 'response' => $this->normalizeResponse($job['response'] ?? null), + 'job_id' => isset($job['id']) ? (int) $job['id'] : null, + 'uuid' => $job['uuid'] ?? null, + 'run_time' => $this->normalizeRunTime($job['run_time'] ?? null), + 'message' => 'Job status fetched successfully.', + ]; + } catch (\Throwable $e) { + log_message('error', 'JobStatusService failed for job "{job}": {message}', [ + 'job' => $jobName, + 'message' => $e->getMessage(), + ]); + + return $this->buildResponse(false, $jobName, 'Unable to fetch job status right now.'); + } + } + + protected function normalizeResponse($rawResponse) + { + // dd($rawResponse); + if ($rawResponse === null) { + return null; + } + + if (is_string($rawResponse)) { + $trimmed = trim($rawResponse); + if ($trimmed === '') { + return null; + } + + $decoded = json_decode($trimmed, true); + if (json_last_error() === JSON_ERROR_NONE) { + return $decoded; + } + + return $rawResponse; + } + + return $rawResponse; + } + + protected function normalizeRunTime($runTime) + { + if ($runTime === null || $runTime === '') { + return null; + } + + return is_numeric($runTime) ? (float) $runTime : null; + } + + protected function buildResponse(bool $success, string $jobName, string $message): array + { + return [ + 'success' => $success, + 'job_name' => $jobName, + 'status' => null, + 'response' => null, + 'job_id' => null, + 'uuid' => null, + 'run_time' => null, + 'message' => $message, + ]; + } +} diff --git a/app/Models/EmployeePolicyModel.php b/app/Models/EmployeePolicyModel.php index 70e71f6f..dac8f8d6 100755 --- a/app/Models/EmployeePolicyModel.php +++ b/app/Models/EmployeePolicyModel.php @@ -572,8 +572,12 @@ class EmployeePolicyModel extends Model employee_polices.tpa_id, employees.relationship_code as emp_relationship_code, employees.relationship as emp_relationship, + employees.email_corporate as emp_email_c, 'C' as event_type_data, + employee_polices.date_coverage, + employee_polices.basic_cover_si, + CASE WHEN emp_endorsement.field_name = 'dob' THEN DATE_FORMAT(emp_endorsement.old_value, '%d-%b-%Y') @@ -705,6 +709,7 @@ class EmployeePolicyModel extends Model employee_polices.premium AS old_si_premium, employee_polices.rata_premimum AS old_rata_premium, employee_polices.age_band, + employee_polices.date_coverage, sidata.new_basic_cover_si, sidata.new_si_premium, sidata.old_si_premium, diff --git a/app/Views/claim_files_upload.php b/app/Views/claim_files_upload.php index 9132e7e5..4a86c1bd 100644 --- a/app/Views/claim_files_upload.php +++ b/app/Views/claim_files_upload.php @@ -27,9 +27,11 @@ - +
+
Document Name
@@ -39,17 +41,7 @@
- - - +
@@ -72,7 +64,8 @@
+ enctype="multipart/form-data" novalidate + data-parsley-validation-threshold="0"> @@ -134,7 +127,8 @@