db = db_connect(); $this->claimDumpFileModel = new ClaimDumpFileModel(); } /** * First JOB for insert TPA wise Bulk Upload */ public function runTpaClaimDumpInsert(string $filePath, int $fileId): array { // 1. Start Transaction $this->db->transBegin(); try { $fileData = $this->claimDumpFileModel->where('id', $fileId)->first(); // Determine sheet name logic... if (env('FHPL_PRIMARY_KEY_CONSTANT') == $fileData['tpa_id']) { $rows = $this->readExcelBySheetName($filePath, 'Claims&Preauth'); } else if (env('R_CARE_PRIMARY_KEY_CONSTANT') == $fileData['tpa_id']) { $rows = $this->readExcelBySheetName($filePath, 'CL'); } else { $rows = $this->readExcel($filePath); } if (empty($rows)) { $this->db->transRollback(); // ROLLBACK BEFORE RETURN return ['status' => false, 'message' => 'Excel file contains no data or wrong file upload']; } $tpaInsertData = $this->mapTPAData($rows, $fileId); if (empty($tpaInsertData)) { $this->db->transRollback(); // ROLLBACK BEFORE RETURN return ['status' => false, 'message' => 'These records already exist in the system.']; } $return_res = $this->bulkInsertTPATable($tpaInsertData); if ($return_res !== true) { $this->db->transRollback(); // ROLLBACK BEFORE RETURN return ['status' => false, 'message' => 'TPA Import bulk insert failed']; } // 2. Commit if everything is fine $this->db->transCommit(); return ['status' => true, 'message' => 'File uploaded successfully', 'record_count' => count($tpaInsertData)]; } catch (\Throwable $e) { // 3. Rollback on any crash/exception $this->db->transRollback(); return ['status' => false, 'message' => 'System error : ' . $e->getMessage()]; } } /** * Second JOB for insert Ticket Master table after insert the TPA bulk upload success */ public function runTicketMasterInsert(array $params): array { // 1. Start manual transaction $this->db->transBegin(); try { $file_id = $params['file_id']; $ticketMasterData = $this->mapClaimMasterData($file_id); // Check if mapping failed if (!$ticketMasterData['status']) { $this->db->transRollback(); // ALWAYS rollback before early return return $ticketMasterData; } $message = ''; $hasExecutedTask = false; // Process Mapped Data if (!empty($ticketMasterData['mapped_array'])) { $insert_res = $this->importClaimMaster($ticketMasterData['mapped_array']); if (!$insert_res) { $this->db->transRollback(); return ['status' => false, 'message' => 'Ticket Master Claim bulk insert failed']; } $message .= 'Ticket Master Claim bulk insert success. '; $hasExecutedTask = true; } // Process Rejected Reasons if (!empty($ticketMasterData['rejected_reason_array'])) { $update_res = $this->updateTicketMasterRejectedReasonInTPATable($ticketMasterData['rejected_reason_array']); if (!$update_res) { $this->db->transRollback(); return ['status' => false, 'message' => 'Updating rejected reasons failed']; } $message .= empty($ticketMasterData['mapped_array']) ? 'Those employees not in our system. ' : 'Ticket Master Claim rejected reason updated successfully. '; $hasExecutedTask = true; } // If nothing was processed but no error occurred if (!$hasExecutedTask) { $this->db->transRollback(); return ['status' => false, 'message' => 'No data found to process.']; } // 2. Commit the transaction $this->db->transCommit(); return ['status' => true, 'message' => trim($message)]; } catch (\Throwable $th) { // 3. Rollback on crash $this->db->transRollback(); return [ 'status' => false, 'message' => 'System error during Ticket Master Insert: ' . $th->getMessage() ]; } } /** * Read Excel and return associative rows (header based) */ protected function readExcel(string $filePath): array { helper('excel_util_helper'); if (!file_exists($filePath)) { throw new RuntimeException("File not found: {$filePath}"); } $spreadsheet = IOFactory::load($filePath); $sheet = $spreadsheet->getActiveSheet(); $rows = $sheet->toArray(null, true, true, true); // dd($rows); if (count($rows) < 2) { return []; } // First row is header $headers = array_shift($rows); $headers = array_map('trim', $headers); $data = []; foreach ($rows as $row) { if(check_row_is_empty_or_null($row)){ break; } $item = []; foreach ($headers as $key => $headerName) { if ($headerName !== '') { $item[$headerName] = $row[$key] ?? null; } } $data[] = $item; } return $data; } /** * Read Excel By Sheet name and return associative rows (header based) */ protected function readExcelBySheetName(string $filePath, string $sheetName): array { if (!file_exists($filePath)) { throw new RuntimeException("File not found: {$filePath}"); } $spreadsheet = IOFactory::load($filePath); // Get sheet by name $sheet = $spreadsheet->getSheetByName($sheetName); if ($sheet === null) { throw new RuntimeException("Sheet '{$sheetName}' not found in Excel file"); } $rows = $sheet->toArray(null, true, true, true); // Need at least header + one row if (count($rows) < 2) { return []; } // First row = headers $headers = array_shift($rows); $headers = array_map('trim', $headers); $data = []; foreach ($rows as $row) { // Skip completely empty rows if (!array_filter($row)) { continue; } $item = []; foreach ($headers as $key => $headerName) { if ($headerName !== '') { $item[$headerName] = $row[$key] ?? null; } } $data[] = $item; } return $data; } /** * Dublicate check in the ticket_master table records */ protected function checkDublicateTicketMasterClaim(array $param): bool { $ticketMaster = new TicketMasterModel(); $ticket_master_data = $ticketMaster ->where('doa', $param['doa']) ->where('tpa_no', $param['tpa_no']) ->where('claim_amount', $param['claim_amount']) ->where('emp_code', $param['emp_code']) ->where('is_active', 1) ->findAll(); if(count($ticket_master_data) > 0){ return true; } return false; } /** * Dublicate check in the TPA specific table records */ protected function checkDuplicateTpaClaim(string $table, array $params): bool { return $this->db->table($table) ->where($params) ->where('is_active', 1) ->countAllResults() > 0; } /** * Dublicate check in the TPA specific table records */ protected function getTpaClaimDumpData(string $table, array $params): array { $tpaClaimDumpDataCount = $this->db ->table($table) ->where('is_active', 1) ->where('file_id', $params['file_id']) ->where('ticket_id IS NULL') ->where('master_reject_reason IS NULL') ->countAllResults(); $batch_size = 100; $total_batch = (int) ceil($tpaClaimDumpDataCount / $batch_size); $batch_no = isset($params['batch_no']) ? (int) $params['batch_no'] : null; $last_emp_id = (int) ($params['last_emp_id'] ?? 0); return $this->db ->table($table) ->where('is_active', 1) ->where('file_id', $params['file_id']) ->where('ticket_id IS NULL') ->where('master_reject_reason IS NULL') ->get() ->getResultArray(); } /** * Dublicate check in the TPA specific table records */ public function getEmployeeDetails(int $client_id, int $client_policy_id, string $emp_code, string $relation): array { $EmployeeModel = new EmployeeModel(); $employeeData = $EmployeeModel ->select([ 'employees.id AS emp_id', 'employees.email_corporate AS emp_mail', 'employees.mobile AS emp_mobile', 'employees.name AS emp_name', 'employees.emp_code AS emp_code', // insured employee 'insured.id AS insured_emp_id', 'insured.name AS insured_name' ]) ->join( 'employee_polices', 'employees.id = employee_polices.employee_id' ) ->join( 'employees AS insured', "insured.emp_code = employees.emp_code AND insured.client_id = employees.client_id AND LOWER(insured.relationship) = " . $EmployeeModel->db->escape(strtolower($relation)), 'left' ) ->where('employees.is_active', 1) ->where('employee_polices.is_active', 1) ->where('employee_polices.client_policy_id', $client_policy_id) ->where('employees.client_id', $client_id) ->where('employees.emp_code', $emp_code) ->where('LOWER(employees.relationship)', 'self') ->first(); return $employeeData ?? []; } /** * Map Excel rows to TPA table structure */ abstract protected function mapTPAData(array $rows, $fileId): array; /** * Map DB rows to Ticket Master table structure */ abstract protected function mapClaimMasterData($fileId): array; /** * Insert into TPA-specific table (bulk) */ abstract protected function bulkInsertTPATable(array $data): bool; /** * Insert into Ticket-Master-specific table (bulk) */ abstract protected function importClaimMaster(array $data): bool; /** * Update TPA table with ticket_master primary key */ abstract protected function updateTicketIdInTPATable(): bool; /** * Update TPA table with ticket_master insert rejected reason */ abstract protected function updateTicketMasterRejectedReasonInTPATable(array $data): bool; }