From 5558e9555477f81f6c21e257baa405bfaeb7a4c9 Mon Sep 17 00:00:00 2001 From: velz Date: Fri, 19 Dec 2025 15:19:23 +0530 Subject: [PATCH 1/3] FEAT_TPA_API_DATA_STORE_JOB --- app/Config/Routes.php | 1 + app/Controllers/ApiServiceController.php | 15 + app/Controllers/JobWorker.php | 3 + app/Controllers/MediAssistApiController.php | 79 ++++- app/Helpers/TPADataCompareHelper.php | 239 +++++++++++++ app/Helpers/TPADataCompareHelper2.php | 363 ++++++++++++++++++++ app/Models/TpaApiDataModel.php | 108 ++++++ 7 files changed, 804 insertions(+), 4 deletions(-) create mode 100644 app/Helpers/TPADataCompareHelper.php create mode 100644 app/Helpers/TPADataCompareHelper2.php create mode 100644 app/Models/TpaApiDataModel.php diff --git a/app/Config/Routes.php b/app/Config/Routes.php index b0aded13..cc323406 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -766,6 +766,7 @@ $routes->get('IRSubmission','MediAssistApiController::IRSubmission'); // API service $routes->post("ecardRequest", "ApiServiceController::ecardRequest"); $routes->post("getTPAID", "ApiServiceController::getTPAID"); +// $routes->get("getTPAID", "ApiServiceController::getTPAID"); $routes->get('fileDownload','MediAssistApiController::fileDownload'); diff --git a/app/Controllers/ApiServiceController.php b/app/Controllers/ApiServiceController.php index b22a1470..5f8f17e4 100644 --- a/app/Controllers/ApiServiceController.php +++ b/app/Controllers/ApiServiceController.php @@ -14,6 +14,8 @@ use App\Controllers\ICICILombardController; use App\Controllers\MediAssistApiController; use App\Models\BatchFileModel; use App\Models\FileModel; +use App\Helpers\TPADataCompareHelper; +use App\Helpers\TPADataCompareHelper2; class ApiServiceController extends BaseController { @@ -154,6 +156,19 @@ class ApiServiceController extends BaseController public function getTPAID() { + // helper('TPADataCompareHelper'); + // print_rr(json_decode(file_get_contents(WRITEPATH.'/tmp/medi.json'),true));die(); + // $report = TPADataCompareHelper::compareDbVsMediassist( + // $report = TPADataCompareHelper2::compareDbVsMediassistGrouped( + // json_decode(file_get_contents(WRITEPATH.'/tmp/db.json'),true), + // json_decode(file_get_contents(WRITEPATH.'/tmp/medi.json'),true) + // ); + // print_rr($report); + // die(); + + + + //START OF THE PROGRAM log_message('error', "getTPAID payloads :" . json_encode($this->request->getPost() ?? [])); $tpa_id = $this->request->getPost('tpa_id') ?? null; $policy_no = $this->request->getPost('policy_no') ?? null; diff --git a/app/Controllers/JobWorker.php b/app/Controllers/JobWorker.php index 43935749..c32da5e6 100755 --- a/app/Controllers/JobWorker.php +++ b/app/Controllers/JobWorker.php @@ -190,6 +190,9 @@ class JobWorker extends AdminController 'initiateWellnessOnboardJob' => [ 'type' => 'CC', // Handler Category 'handler' => 'App\Controllers\EmployeeController', + ], 'saveMediAssitAPIData' => [ + 'type' => 'CC', // Handler Category + 'handler' => 'App\Controllers\MediAssistApiController', ], ]; diff --git a/app/Controllers/MediAssistApiController.php b/app/Controllers/MediAssistApiController.php index e293c57f..ba21f694 100644 --- a/app/Controllers/MediAssistApiController.php +++ b/app/Controllers/MediAssistApiController.php @@ -5,10 +5,12 @@ namespace App\Controllers; use App\Controllers\BaseController; use App\Models\BatchFileModel; use App\Models\EmployeePolicyModel; +use App\Models\TpaApiDataModel; use CodeIgniter\HTTP\ResponseInterface; use CodeIgniter\HTTP\IncomingRequest; use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\API\ResponseTrait; +use App\Controllers\Jobs; class MediAssistApiController extends BaseController { @@ -203,8 +205,18 @@ class MediAssistApiController extends BaseController public function GetBenefDetails($requestData) { - helper('api'); + // helper('api'); + // helper('TPADataCompareHelper'); + // $report = EmployeeCompareHelper::compareDbVsMediassist( + // $dbRows, + // $mediassistAPIdata + // ); + // print_rr($report); + // die(); + // print_r($requestData);die(); + + //START OF THE PROGRAM $function_calling_type = $requestData['return_type'] ?? 'job'; try { @@ -266,7 +278,6 @@ class MediAssistApiController extends BaseController return $this->respond(['status' => false, 'message' => 'employeePolicyData not found']); } } - $allBenef = []; $startIndex = 0; $range = 100; @@ -326,6 +337,19 @@ class MediAssistApiController extends BaseController $startIndex += $range; } while ($startIndex < $totalCount); + //save API data as JSON for analysis + $json = json_encode($allBenef, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); + // $filename = time() . '.json'; + $filePath = WRITEPATH . 'tmp/'.time().'_'.$requestData['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' => $requestData['file_id'], + 'json_file_path' => $filePath ]]); + + // now update DB $updated = 0; $employee_policy_ids = []; @@ -334,11 +358,10 @@ class MediAssistApiController extends BaseController $hasMatchForThisPolicy = false; foreach ($allBenef as $row) { - if ( strtolower(trim($policy_data['name'] ?? '')) == strtolower(trim($row['benefName'] ?? '')) && ($policy_data['emp_code'] ?? '') == ($row['priBenefEmpCode'] ?? '') && - strtolower(trim($policy_data['relationship'] ?? '')) == strtolower(trim($row['relName'] ?? '')) && + strtolower(trim($policy_data['relationship'] ?? '')) == strtolower(trim(str_replace('-', ' ', $row['relName'] ?? ''))) && ($policy_data['gender'] ?? '') == ($row['benefSex'] ?? '') && ($policy_data['dob'] ?? '') == (change_date_format($row['benefDOB'], 'd/m/Y H:i:s') ?? '') ) { @@ -721,6 +744,54 @@ class MediAssistApiController extends BaseController ]; } + public function saveMediAssitAPIData($array) + { + $file_id = $array['file_id']; + $json = file_get_contents($array['json_file_path']); + $records = json_decode($json, true); + // log_message('error','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['priBenefEmpCode'] ?? ''), + + 'name' => trim($row['benefName'] ?? ''), + 'dob' => !empty($row['benefDOB']) + ? date('Y-m-d', strtotime(str_replace('/', '-', $row['benefDOB']))) + : null, + + 'relation' => trim($row['relName'] ?? null), + 'gender' => strtoupper($row['benefSex'] ?? null), + 'self' => strtolower($row['relName'] ?? '') === 'self' ? 1 : 0, + + 'tpa_id' => trim($row['benefMediAssistID'] ?? null), + 'age' => is_numeric($row['benefAge'] ?? null) + ? (int) $row['benefAge'] + : null, + + 'is_active' => 1, + 'created_by' => $file_info[0]['created_by'] ?? null, + ]; + } + // log_message('error','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 + } + diff --git a/app/Helpers/TPADataCompareHelper.php b/app/Helpers/TPADataCompareHelper.php new file mode 100644 index 00000000..79907b37 --- /dev/null +++ b/app/Helpers/TPADataCompareHelper.php @@ -0,0 +1,239 @@ +format('Y-m-d'); + } + } + + $ts = strtotime($date); + return $ts ? date('Y-m-d', $ts) : null; + } + + public static function normalizeName(?string $name): ?string + { + if ($name === null) { + return null; + } + + $name = trim($name); + // $name = preg_replace('/\.+/', ' ', $name); + // $name = preg_replace('/\s+/', ' ', $name); + return mb_strtolower($name); + } + + public static function normalizeEmpId(?string $empId): ?string + { + if ($empId === null) { + return null; + } + + $empId = trim($empId); + $empId = preg_replace('/[\s\-\/]/', '', $empId); + return $empId === '' ? null : $empId; + } + + public static function normalizeGender(?string $gender): ?string + { + if ($gender === null) { + return null; + } + + $g = strtoupper(trim($gender)); + return in_array($g, ['M', 'MALE']) ? 'M' + : (in_array($g, ['F', 'FEMALE']) ? 'F' : $g); + } + + public static function normalizeRelation(?string $relation): ?string + { + return $relation === null ? null : strtoupper(trim($relation)); + } + + /* ========================= + Core normalization + ========================= */ + + public static function normalizeEmployees( + array $rows, + array $keyMap, + ?string $pkKey = null + ): array { + $normalized = []; + // print_r($rows);die(); + foreach ($rows as $index => $row) { + // echo "Normalizing record #" . ($index + 1) . "\n"; + $item = [ + 'pk' => $pkKey && isset($row[$pkKey]) ? $row[$pkKey] : null, + '__raw' => $row, + ]; + + foreach ($keyMap as $canonical => $possibleKeys) { + $value = null; + + foreach ($possibleKeys as $key) { + if (isset($row[$key]) && $row[$key] !== '') { + $value = $row[$key]; + break; + } + } + + switch ($canonical) { + case 'emp_id': + $item['emp_id'] = self::normalizeEmpId($value); + break; + case 'name': + $item['name'] = self::normalizeName($value); + break; + case 'dob': + $item['dob'] = self::parseDateToYmd($value); + break; + case 'gender': + $item['gender'] = self::normalizeGender($value); + break; + case 'relation': + $item['relation'] = self::normalizeRelation($value); + break; + default: + $item[$canonical] = $value; + } + } + + if (!empty($item['pk'])) { + $normalized[$item['pk']] = $item; + } else { + $normalized['__no_emp_' . $index] = $item; + } + + // echo "Normalizing record #" . ($index + 1) . "\n"; + } + + return $normalized; + } + + /* ========================= + Main comparison + ========================= */ + + public static function compareDbVsMediassist( + array $dbData, + array $mediassistAPIdata + ): array { + // echo count($dbData) . " records in DB data\n";die(); + $dbKeyMap = [ + 'emp_id' => ['emp_code'], + 'name' => ['name'], + 'dob' => ['dob'], + 'gender' => ['gender'], + 'relation' => ['relationship'], + ]; + + $mediassistKeyMap = [ + 'emp_id' => ['priBenefEmpCode'], + 'name' => ['benefName', 'priBeneficiaryName'], + 'dob' => ['benefDOB'], + 'gender' => ['benefSex'], + 'relation' => ['relName'], + ]; + + $A = self::normalizeEmployees($dbData, $dbKeyMap, 'id'); + + $B = self::normalizeEmployees($mediassistAPIdata, $mediassistKeyMap); + dd($B); + $report = [ + 'summary' => [ + 'total_db' => count($A), + 'total_mediassist' => count($B), + 'matched' => 0, + 'mismatched' => 0, + 'only_in_db' => 0, + 'only_in_mediassist' => 0, + ], + 'exact_matches' => [], + 'field_mismatches' => [], + 'only_in_db' => [], + 'only_in_mediassist' => [], + ]; + + foreach ($A as $empId => $rowA) { + + if (!isset($B[$empId])) { + $report['only_in_db'][] = [ + 'pk' => $rowA['pk'], + 'emp_id' => $empId, + 'data' => $rowA, + ]; + continue; + } + + $rowB = $B[$empId]; + $diff = []; + + foreach (self::COMPARE_FIELDS as $field) { + if (($rowA[$field] ?? null) !== ($rowB[$field] ?? null)) { + $diff[$field] = [ + 'db' => $rowA[$field] ?? null, + 'mediassist' => $rowB[$field] ?? null, + ]; + } + } + + if (empty($diff)) { + $report['exact_matches'][] = [ + 'pk' => $rowA['pk'], + 'emp_id' => $empId, + ]; + $report['summary']['matched']++; + } else { + $report['field_mismatches'][] = [ + 'pk' => $rowA['pk'], + 'emp_id' => $empId, + 'differences' => $diff, + ]; + $report['summary']['mismatched']++; + } + + unset($B[$empId]); + } + + foreach ($B as $empId => $rowB) { + $report['only_in_mediassist'][] = [ + 'pk' => null, + 'emp_id' => $empId, + 'data' => $rowB, + ]; + } + + $report['summary']['only_in_db'] = count($report['only_in_db']); + $report['summary']['only_in_mediassist'] = count($report['only_in_mediassist']); + + return $report; + } +} diff --git a/app/Helpers/TPADataCompareHelper2.php b/app/Helpers/TPADataCompareHelper2.php new file mode 100644 index 00000000..5ff171f3 --- /dev/null +++ b/app/Helpers/TPADataCompareHelper2.php @@ -0,0 +1,363 @@ +format('Y-m-d'); + } + $ts = strtotime($date); + return $ts ? date('Y-m-d', $ts) : null; + } + + public static function normalizeName(?string $name): ?string + { + if ($name === null) return null; + $s = trim($name); + // $s = preg_replace('/\.+/', ' ', $s); + // $s = preg_replace('/\s+/', ' ', $s); + return mb_strtolower($s); + } + + public static function normalizeEmpId(?string $id): ?string + { + if ($id === null) return null; + $s = trim($id); + // $s = preg_replace('/[\s\-\/]/', '', $s); + // $s = preg_replace('/[^\p{L}\p{N}]/u', '', $s); + return $s === '' ? null : $s; + } + + public static function normalizeGender(?string $g): ?string + { + if ($g === null) return null; + $u = strtoupper(trim($g)); + if (in_array($u, ['M','MALE'])) return 'M'; + if (in_array($u, ['F','FEMALE'])) return 'F'; + return $u; + } + + public static function normalizeRelation(?string $r): ?string + { + if ($r === null) return null; + return strtoupper(trim($r)); + } + + /* ------------------------------------- + Normalize rows -> canonical structure + Returns array of items (not keyed), each item contains: + - 'pk' (DB primary key or null) + - 'emp_id' (employee code) + - 'name','dob','gender','relation' (normalized) + - '__raw' original row + - '__rowid' generated unique row id for API rows (if needed) + ------------------------------------- */ + public static function normalizeRows(array $rows, array $keyMap, ?string $pkKey = null): array + { + $out = []; + $idx = 0; + foreach ($rows as $r) { + $item = [ + 'pk' => ($pkKey && isset($r[$pkKey])) ? $r[$pkKey] : null, + '__raw' => $r, + '__rowid' => null, + ]; + + // fill canonical fields + foreach ($keyMap as $canonical => $candidates) { + $val = null; + foreach ($candidates as $k) { + if (is_array($r) && array_key_exists($k, $r) && $r[$k] !== '') { + $val = $r[$k]; + break; + } + } + switch ($canonical) { + case 'emp_id': $item['emp_id'] = self::normalizeEmpId((string)$val); break; + case 'name': $item['name'] = self::normalizeName((string)$val); break; + case 'dob': $item['dob'] = self::parseDateToYmd((string)$val); break; + case 'gender': $item['gender'] = self::normalizeGender((string)$val); break; + case 'relation': $item['relation'] = self::normalizeRelation((string)$val); break; + default: $item[$canonical] = $val; + } + } + + // create a stable row id (for API rows without PK) so they remain unique + $item['__rowid'] = $item['pk'] ?? ('api_row_' . $idx++); + + $out[] = $item; + } + + return $out; + } + + /* ------------------------- + Build grouped index by emp_code: + returns [ emp_code => [ item1, item2, ... ] ] + Use '__no_emp' key for rows without emp_id + ------------------------- */ + public static function groupByEmpCode(array $items): array + { + $groups = []; + foreach ($items as $it) { + $key = $it['emp_id'] ?? '__no_emp'; + if ($key === null || $key === '') $key = '__no_emp'; + $groups[$key][] = $it; + } + return $groups; + } + + /* ------------------------- + Find a match for a DB row inside a mediassist group (array of items). + Matching priority: + 1) unique ids present in mediassist (if db raw has any of those too) + 2) exact name + dob + 3) exact name + relation + 4) fuzzy name + dob (threshold %) + If found, returns index of matched item in $group array; else null. + Note: $group is passed by reference so matched item can be removed by caller. + ------------------------- */ + public static function findMatchInGroup(array $dbRow, array $group, int $fuzzyThreshold = 85): ?int + { + // 1) match on unique ids if DB row contains any of those (rare) + // foreach (self::MEDIASSIST_UNIQUE_IDS as $uidField) { + // $dbVal = $dbRow['__raw'][$uidField] ?? null; + // if ($dbVal) { + // foreach ($group as $i => $gItem) { + // $gVal = $gItem['__raw'][$uidField] ?? null; + // if ($gVal && (string)$gVal === (string)$dbVal) return $i; + // } + // } + // } + + // 2) match exact name + dob (both normalized) + if (!empty($dbRow['name']) && !empty($dbRow['dob'])) { + foreach ($group as $i => $gItem) { + if (!empty($gItem['name']) && !empty($gItem['dob']) + && $dbRow['name'] === $gItem['name'] + && $dbRow['dob'] === $gItem['dob']) { + return $i; + } + } + } + + // 3) match exact name + relation (if dob missing or unreliable) + if (!empty($dbRow['name']) && !empty($dbRow['relation'])) { + foreach ($group as $i => $gItem) { + if (!empty($gItem['name']) && !empty($gItem['relation']) + && $dbRow['name'] === $gItem['name'] + && $dbRow['relation'] === $gItem['relation']) { + return $i; + } + } + } + + // 4) fuzzy name + dob (if dob present) + if ($fuzzyThreshold > 0 && !empty($dbRow['name'])) { + foreach ($group as $i => $gItem) { + if (empty($gItem['name'])) continue; + $score = 0.0; + similar_text($dbRow['name'], $gItem['name'], $score); // percent + $dobMatches = (!empty($dbRow['dob']) && !empty($gItem['dob']) && $dbRow['dob'] === $gItem['dob']); + // require DOB match OR higher threshold if dob missing + if ($dobMatches && $score >= max(60, $fuzzyThreshold - 10)) { // slightly relaxed + return $i; + } + if (!$dobMatches && $score >= $fuzzyThreshold) { + // if names are very similar even w/o dob, accept (cautious) + return $i; + } + } + } + + // no match + return null; + } + + /* ------------------------- + Main comparison routine (grouped matching) + Options: + - fuzzy_threshold (default 85) + - try_global_search_if_emp_missing (bool, default false) + ------------------------- */ + public static function compareDbVsMediassistGrouped( + array $dbRows, + array $mediassistAPIdata, + string $dbPkKey = 'id', + array $options = [], + array $dbKeyMap = null, + array $mediassistKeyMap = null, + ): array { + + + $dbKeyMap = [ + 'emp_id' => ['emp_code'], + 'name' => ['name'], + 'dob' => ['dob'], + 'gender' => ['gender'], + 'relation' => ['relationship'], + ]; + + $mediassistKeyMap = [ + 'emp_id' => ['priBenefEmpCode'], + 'name' => ['benefName', 'priBeneficiaryName'], + 'dob' => ['benefDOB'], + 'gender' => ['benefSex'], + 'relation' => ['relName'], + ]; + + + $fuzzyThreshold = $options['fuzzy_threshold'] ?? 85; + $tryGlobalSearch = $options['try_global_search_if_emp_missing'] ?? false; + + // normalize to lists + $normDb = self::normalizeRows($dbRows, $dbKeyMap, $dbPkKey); + $normApi = self::normalizeRows($mediassistAPIdata, $mediassistKeyMap, null); + // dd($normApi); + // group by emp_code + $dbGroups = self::groupByEmpCode($normDb); + $apiGroups = self::groupByEmpCode($normApi); + + // prepare report + $report = [ + 'summary' => [ + 'total_db' => count($normDb), + 'total_mediassist' => count($normApi), + 'matched' => 0, + 'mismatched' => 0, + 'only_in_db' => 0, + 'only_in_mediassist' => 0, + ], + 'exact_matches' => [], + 'field_mismatches' => [], + 'only_in_db' => [], + 'only_in_mediassist' => [], + ]; + + // For each db group (emp_code), try match each dbRow with api group entries + foreach ($dbGroups as $empCode => $dbItems) { + $apiItems = $apiGroups[$empCode] ?? []; + + // We'll mutate a local copy of apiItems to mark matched items (so we can remove) + $remainingApi = $apiItems; + + foreach ($dbItems as $dbRow) { + $matchedIndex = null; + if (!empty($empCode) && !empty($remainingApi)) { + $matchedIndex = self::findMatchInGroup($dbRow, $remainingApi, $fuzzyThreshold); + } + + // If empCode not present in API and global search allowed, try searching all API rows (costly) + if ($matchedIndex === null && $tryGlobalSearch && empty($apiItems)) { + // attempt global search across all api groups (can be heavy) + foreach ($apiGroups as $gKey => $gList) { + $mi = self::findMatchInGroup($dbRow, $gList, $fuzzyThreshold); + if ($mi !== null) { + // found in another group + $matchedIndex = $mi; + // use that group as remainingApi reference so we can remove matched later + $remainingApi = $apiGroups[$gKey]; + break; + } + } + } + + if ($matchedIndex !== null) { + // found match — use that api row + $apiMatch = $remainingApi[$matchedIndex]; + + // compare fields + $diff = []; + foreach (self::COMPARE_FIELDS as $f) { + $vDb = $dbRow[$f] ?? null; + $vApi = $apiMatch[$f] ?? null; + if ($vDb !== $vApi) { + $diff[$f] = ['db' => $vDb, 'mediassist' => $vApi]; + } + } + + if (empty($diff)) { + $report['exact_matches'][] = [ + 'pk' => $dbRow['pk'], + 'emp_id' => $dbRow['emp_id'], + 'db_rowid' => $dbRow['__rowid'], + 'api_rowid' => $apiMatch['__rowid'], + ]; + $report['summary']['matched']++; + } else { + $report['field_mismatches'][] = [ + 'pk' => $dbRow['pk'], + 'emp_id' => $dbRow['emp_id'], + 'db_rowid' => $dbRow['__rowid'], + 'api_rowid' => $apiMatch['__rowid'], + 'differences' => $diff + ]; + $report['summary']['mismatched']++; + } + + // remove matched api item from remainingApi (so it's not matched again) + array_splice($remainingApi, $matchedIndex, 1); + } else { + // no match found for this dbRow inside api group => only_in_db + $report['only_in_db'][] = [ + 'pk' => $dbRow['pk'], + 'emp_id' => $dbRow['emp_id'], + 'db_rowid' => $dbRow['__rowid'], + 'data' => $dbRow + ]; + } + } // end each dbRow + + // after processing all dbRows in this empCode group, any remainingApi are only_in_mediassist + foreach ($remainingApi as $leftApi) { + $report['only_in_mediassist'][] = [ + 'pk' => null, + 'emp_id' => $leftApi['emp_id'], + 'api_rowid' => $leftApi['__rowid'], + 'data' => $leftApi + ]; + } + } // end each emp group + + // Also handle any api groups whose emp_code does not exist in DB at all + foreach ($apiGroups as $empCode => $apiItems) { + if (isset($dbGroups[$empCode])) continue; // already handled + foreach ($apiItems as $ai) { + $report['only_in_mediassist'][] = [ + 'pk' => null, + 'emp_id' => $ai['emp_id'], + 'api_rowid' => $ai['__rowid'], + 'data' => $ai + ]; + } + } + + // summary counts + $report['summary']['only_in_db'] = count($report['only_in_db']); + $report['summary']['only_in_mediassist'] = count($report['only_in_mediassist']); + + return $report; + } +} diff --git a/app/Models/TpaApiDataModel.php b/app/Models/TpaApiDataModel.php new file mode 100644 index 00000000..5df68cc2 --- /dev/null +++ b/app/Models/TpaApiDataModel.php @@ -0,0 +1,108 @@ + 'required|integer', + // 'temp_code' => 'required|string|max_length[50]', + // 'tname' => 'required|string|max_length[150]', + // 'tgender' => 'permit_empty|in_list[M,F,O]', + // 'tage' => 'permit_empty|integer' + // ]; + + protected $validationMessages = []; + protected $skipValidation = false; + + + + + public function insertBatchWithChunkLog( array $rows,int $chunkSize = 500,?string $logRef = null) + { + if (empty($rows)) { + return [ + 'status' => false, + 'inserted' => 0, + 'failed_batches' => 0, + 'message' => 'No data' + ]; + } + + $db = \Config\Database::connect(); + $this->skipValidation(true); + + $inserted = 0; + $failedBatches = 0; + $batchNo = 0; + + foreach (array_chunk($rows, $chunkSize) as $chunk) { + $batchNo++; + + try { + $db->transStart(); + + $this->insertBatch($chunk); + + if ($db->transStatus() === false) { + throw new \RuntimeException('DB transaction failed'); + } + + $db->transComplete(); + $inserted += count($chunk); + + } catch (\Throwable $e) { + $db->transRollback(); + $failedBatches++; + + // 🔴 Batch-level error log + log_message('error', json_encode([ + 'type' => 'BATCH_INSERT_FAILED', + 'table' => $this->table, + 'batch_no' => $batchNo, + 'batch_size'=> count($chunk), + 'ref' => $logRef, + 'error' => $e->getMessage() + ])); + } + } + + return [ + 'status' => $failedBatches === 0, + 'inserted' => $inserted, + 'failed_batches' => $failedBatches, + 'total_batches' => $batchNo + ]; + } + +} From 0a5b9c1547521ba6534d10c51b6ea1e0107e6d1e Mon Sep 17 00:00:00 2001 From: velz Date: Fri, 19 Dec 2025 15:19:39 +0530 Subject: [PATCH 2/3] FEAT_PRE_CONTD --- app/Models/TpaApiDataModel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Models/TpaApiDataModel.php b/app/Models/TpaApiDataModel.php index 5df68cc2..50958fac 100644 --- a/app/Models/TpaApiDataModel.php +++ b/app/Models/TpaApiDataModel.php @@ -29,7 +29,7 @@ class TpaApiDataModel extends Model ]; // protected $useTimestamps = true; - protected $createdField = 'create_at'; + // protected $createdField = 'create_at'; protected $updatedField = null; // protected $dateFormat = 'datetime'; From d0bef9119b50864fe9cd312aa7c7d8cd71412bb1 Mon Sep 17 00:00:00 2001 From: "sanjeev.p" Date: Fri, 19 Dec 2025 15:23:23 +0530 Subject: [PATCH 3/3] FIX_Claims Date Filter implemented --- .../AppContentManagementController.php | 19 ++- app/Controllers/EmployeeRestController.php | 2 +- app/Controllers/TicketController.php | 34 +++++- app/Views/layout/header.php | 2 +- app/Views/ticket_list.php | 15 ++- app/Views/ticket_search.php | 114 +++++++++++++++++- 6 files changed, 168 insertions(+), 18 deletions(-) diff --git a/app/Controllers/AppContentManagementController.php b/app/Controllers/AppContentManagementController.php index 0dc36282..9b660788 100755 --- a/app/Controllers/AppContentManagementController.php +++ b/app/Controllers/AppContentManagementController.php @@ -263,17 +263,24 @@ class AppContentManagementController extends AdminController $id = $this->request->getGet('faq_id'); if (!empty($id)) { - // $row = $this->faqModel->where('is_active', 1)->find($id); - $row = $this->faqModel->find($id); + if($returnType === 'web'){ + $row = $this->faqModel->find($id); + }else{ + $row = $this->faqModel->where('is_active', 1)->find($id); + } + $data['faq_list'] = $row ? [$row] : []; } else { - // $data['faq_list'] = $this->faqModel->where('is_active', 1)->orderBy('id', 'desc')->findAll(); - $data['faq_list'] = $this->faqModel->orderBy('id', 'desc')->findAll(); + if($returnType === 'web'){ + $data['faq_list'] = $this->faqModel->orderBy('id', 'desc')->findAll(); + }else{ + $data['faq_list'] = $this->faqModel->where('is_active', 1)->orderBy('id', 'desc')->findAll(); + } } if ($returnType === 'web') { - $data['tab_name'] = "FAQ's"; - $data['page_name'] = "FAQ's"; + $data['tab_name'] = "FAQ"; + $data['page_name'] = "FAQ"; // print_r($data);die; return $this->loadLayout('faq_list', $data); } diff --git a/app/Controllers/EmployeeRestController.php b/app/Controllers/EmployeeRestController.php index a672bf8f..bb64f69e 100755 --- a/app/Controllers/EmployeeRestController.php +++ b/app/Controllers/EmployeeRestController.php @@ -3164,7 +3164,7 @@ class EmployeeRestController extends AdminController { try { - $feContentData = $this->feContentModel->findAll(); + $feContentData = $this->feContentModel->where('is_active',1)->findAll(); if (count($feContentData) > 0) { return $this->respond(['status' => 'success', 'code' => 200, 'data' => $feContentData], 200); diff --git a/app/Controllers/TicketController.php b/app/Controllers/TicketController.php index ac104bf3..73997e99 100644 --- a/app/Controllers/TicketController.php +++ b/app/Controllers/TicketController.php @@ -371,6 +371,11 @@ class TicketController extends BaseController $data['insurer_list'] = $this->insurerModel->where('is_active', 1)->findAll(); $data['tpa_list'] = $this->TPAModel->where('is_active', 1)->findAll(); $data['ticket_data'] = $this->ticketSearch(1); + $data['date_type'] = [ + 'ticket_created_date' => 'Created Date', + 'ticket_updated_date' => 'Updated Date', + ]; + return $this->loadLayout('ticket_search', $data); } else { @@ -401,6 +406,7 @@ class TicketController extends BaseController } else{ $data['ticket_data'] = $this->ticketSearch(); + // print_r($data['ticket_data']);die; $html = view('ticket_list', $data); return $this->respond(['status' => true, 'html' => $html], 200); } @@ -411,6 +417,7 @@ class TicketController extends BaseController public function ticketSearch($action = null) { $db = db_connect(); + $rawWhere = []; // log_message('error', 'Ticket Search Action: ' . $action); $subquery = $db->table('ticket_master tm') ->select([ @@ -464,6 +471,7 @@ class TicketController extends BaseController 'tm.insured_name', 'c.short_name', 'DATE_FORMAT(tm.created_at, "%d-%m-%Y") AS ticket_created_date', + 'DATE_FORMAT(tm.updated_at, "%d-%m-%Y") AS ticket_updated_date', 'COALESCE(tat_category.tat, "0-6 Days") AS tat', 'tm.claim_status_id', @@ -557,14 +565,24 @@ class TicketController extends BaseController } else { $search_data = $this->request->getPost(); // print_r($search_data); die() - $where = []; + $where = []; foreach ($search_data as $search_objects => $key) { if ($key != null && $key != '' && $key != 0 && $search_objects != 'is_dashboard') { - $where[$search_objects] = $key; + + if($search_objects == "date_type" && $search_data[$search_objects] === 'ticket_created_date'){ + $startDate = date('Y-m-d 00:00:00', strtotime($search_data['start_date'])); + $endDate = date('Y-m-d 23:59:59', strtotime($search_data['end_date'])); + $rawWhere[] = "tm.created_at BETWEEN '$startDate' AND '$endDate'"; + } + elseif($search_objects == "date_type" && $search_data[$search_objects] === 'ticket_updated_date'){ + $startDate = date('Y-m-d 00:00:00', strtotime($search_data['start_date'])); + $endDate = date('Y-m-d 23:59:59', strtotime($search_data['end_date'])); + $rawWhere[] = "tm.updated_at BETWEEN '$startDate' AND '$endDate'"; + }elseif($search_objects != "date_type" && $search_objects != "start_date" && $search_objects != "end_date"){ + $where[$search_objects] = $key; + } } } - // print_rr($where); - } $query = $db->table('ticket_master tm') ->select([ @@ -584,6 +602,7 @@ class TicketController extends BaseController 'tm.insured_name', 'c.short_name', 'DATE_FORMAT(tm.created_at, "%d-%m-%Y") AS ticket_created_date', + 'DATE_FORMAT(tm.updated_at, "%d-%m-%Y") AS ticket_updated_date', 'COALESCE(tat_category.tat, "0-6 Days") AS tat', '(SELECT first_name FROM user_profiles WHERE user_profiles.id = tm.acm_id) AS acm_name', @@ -641,9 +660,14 @@ class TicketController extends BaseController ->where('tm.is_active', 1) ->where($where) ->orderBy('tm.id', 'DESC'); + if (!empty($rawWhere)) { + foreach ($rawWhere as $condition) { + $query->where($condition, null, false); // raw SQL + } + } $data = $query->get()->getResultArray(); - // dd($db->getLastQuery()->getQuery()); + // dd($db->getLastQuery()->getQuery());die; // dd($data); if ($action == 5){ diff --git a/app/Views/layout/header.php b/app/Views/layout/header.php index 62a6f880..2ed7e44e 100755 --- a/app/Views/layout/header.php +++ b/app/Views/layout/header.php @@ -2099,7 +2099,7 @@ Front-end Content
  • - FAQ's + FAQ
  • diff --git a/app/Views/ticket_list.php b/app/Views/ticket_list.php index 83bd3754..fc467dfb 100644 --- a/app/Views/ticket_list.php +++ b/app/Views/ticket_list.php @@ -25,6 +25,10 @@ table.dataTable tbody td { margin-left: 20px !important; } .dataTables_length label {height: 21px !important;} +.text-custom-grey{ + font-size: 0.65em; + color: #6c757d !important; +}
    -
    +
    -
    +

    @@ -121,6 +121,30 @@

    +
    + + +
    + + +
    Clear Submit @@ -192,6 +216,10 @@ var insurer_id = $('#insurer_id').val(); var tpa_id = $('#tpa_id').val(); + var start_date = $('#startDate').val(); + var end_date = $('#endDate').val(); + var date_type = $('#date_type').val(); + var requestData = { ticket_type_id: ticket_type, pod_no: pod_no, @@ -203,6 +231,9 @@ client_id: client_id, insurer_id: insurer_id, tpa_id: tpa_id, + start_date: start_date, + end_date: end_date, + date_type: date_type, }; let filterData = requestData; @@ -294,12 +325,59 @@ $('#client_id').val(filterData.client_id); $('#insurer_id').val(filterData.insurer_id); $('#tpa_id').val(filterData.tpa_id); - + $('#date_type').val(filterData.date_type); + if(filterData.date_type == '0'){ + $('#date_div').hide(); + }else{ + $('#date_div').show(); + } } }) \ No newline at end of file