nhance/app/Libraries/TPAClaimsImportServices/BaseTpaClaimImportService.php

361 lines
11 KiB
PHP

<?php
namespace App\Libraries\TPAClaimsImportServices;
use CodeIgniter\Database\BaseConnection;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use App\Models\TicketMasterModel;
use App\Models\EmployeeModel;
use App\Models\ClaimDumpFileModel;
use App\Models\ClaimsDumpFhplModel;
use RuntimeException;
abstract class BaseTpaClaimImportService
{
protected BaseConnection $db;
protected $claimDumpFileModel;
public function __construct()
{
$this->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;
$status = true;
// 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;
}else{
$status = false;
}
// 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 employee or dependent 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' => $status, '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
{
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 id',
'employees.email_corporate AS emp_mail',
'employees.mobile AS emp_mobile',
'employees.name AS 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;
}