diff --git a/.env.sample b/.env.sample index e834a822..ceb7085a 100755 --- a/.env.sample +++ b/.env.sample @@ -120,3 +120,4 @@ FHPL_USER_NAME = FHPL_PASSWORD = FHPL_GRANT_TYPE = +METABASE_SECRET_KEY= \ No newline at end of file diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 7b40d4db..d9bb6ea9 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -22,6 +22,7 @@ $routes->get('/swagger', 'SwaggerController::index', ['filter' => 'authMVC']); $routes->get('/fedeploy', 'DeployController::fedeploy_view', ['filter' => 'authMVC']); $routes->post('/fedeploy', 'DeployController::fedeploy', ['filter' => 'authMVC']); $routes->get('/visitOffBoardCheck', 'EmployeeController::visitOffBoardCheck'); +$routes->get('/metaDashboardDemo', 'TestingController::metaDashboardDemo'); // Reminder Mail Notification @@ -36,7 +37,6 @@ $routes->get("view", "EmployeeController::viewECard/$1"); $routes->get("checkWellnessOnboardStatus/(:any)", "EmployeeController::checkWellnessOnboardStatus/$1"); $routes->get("initiateWellnessOnboard/(:any)", "EmployeeController::initiateWellnessOnboard/$1"); $routes->get("exportQCRandRFQ/(:any)", "LeadsController::exportQCRandRFQ/$1"); -$routes->get("smapletest", "ClientController::smapletest"); $routes->get("testMailAttachments", "ClientController::testMailAttachments"); $routes->get("updatePolicyTermsKey", "ClientController::updatePolicyTermsKey"); $routes->get("updateRemainderDate", "ClientController::updateRemainderDate"); @@ -216,6 +216,9 @@ $routes->group("/employee", ["filter" => "authMVC"], function ($routes) { $routes->post("retail-endorsement-save", "EmployeeController::retailendorsementsave"); $routes->get("getTPADataVariationReport/(:num)", "EmployeeController::getTPADataVariationReport/$1"); $routes->get("bulkGenerateEcardAndStoreinS3", "EmployeeController::bulkGenerateEcardAndStoreinS3"); + $routes->get('clearCdSession', 'EmployeeController::clearCdSession'); + $routes->get('checkSessionStatus', 'EmployeeController::checkSessionStatus'); + }); @@ -556,6 +559,10 @@ $routes->group("/api", ["filter" => [ 'ratelimit' , 'authJWT']], function ($rout $routes->get("getSSORedirectUrl", "ApiServiceController::getSSORedirectUrl"); $routes->get("getEmployeePolicy", "EmployeeRestController::getEmployeePolicy"); +$routes->get("downloadCdSplitUpFile", "EmployeeRestController::downloadCdSplitUpFile"); +$routes->get("downloadFileTableFile/(:any)", "EmployeeController::downloadFileList/$1"); + + $routes->group("employeeRest", ['filter' => ['ratelimit' , 'appSignature'] ], function ($routes) { @@ -600,7 +607,7 @@ $routes->group("employeeRest", ['filter' => ['ratelimit' , 'appSignature'] ], fu }); -$routes->group("employeeRest", ["filter" => [ 'ratelimit' , 'appSignature' , 'authJWT']], function ($routes) { +$routes->group("employeeRest", ["filter" => ['GlobalPostFileUploadGuard', 'ratelimit' , 'appSignature', 'authJWT']], function ($routes) { $routes->post('logout', 'RestAuthenticationController::logout'); @@ -652,6 +659,7 @@ $routes->group("employeeRest", ["filter" => [ 'ratelimit' , 'appSignature' , 'au $routes->get("hrFileDownload", "EmployeeRestController::hrFileDownload"); $routes->post("hrFileUpload", "EmployeeRestController::hrFileUpload"); $routes->post("updateHrFileUploadData", "EmployeeRestController::updateHrFileUploadData"); + $routes->post("getHrDashboad", "EmployeeRestController::getHrDashboad"); //thz_master's @@ -682,7 +690,10 @@ $routes->group("employeeRest", ["filter" => [ 'ratelimit' , 'appSignature' , 'au // get insurer and policy type $routes->get("getPolicyTypeAndInsurer", "EmployeeRestController::getPolicyTypeAndInsurer"); - + $routes->get("getExcelFileErrors/(:any)", "EmployeeController::getExcelFileErrors/$1"); + $routes->get("getPolicyAndEndorsementFiles", "EmployeeRestController::getPolicyAndEndorsementFiles"); + $routes->get("downloadPolicyFiles", "EmployeeRestController::downloadPolicyFiles"); + $routes->post("bulkEcardDownloadAsZip", "EmployeeRestController::bulkEcardDownloadAsZip"); }); $routes->get("hrFileDownload", "EmployeeRestController::hrFileDownload"); diff --git a/app/Controllers/ClientController.php b/app/Controllers/ClientController.php index c16c20eb..09f34f77 100755 --- a/app/Controllers/ClientController.php +++ b/app/Controllers/ClientController.php @@ -141,6 +141,7 @@ class ClientController extends AdminController $isDuplicate = $this->clientModel->isDuplicateByClientBranch($value, $field, $clientId, $branchId); return $this->response->setJSON(['isDuplicate' => $isDuplicate]); } + public function checkDuplicateTableFieldValue() { $table = $this->request->getPost('table'); @@ -162,35 +163,6 @@ class ClientController extends AdminController return $this->response->setJSON(['isDuplicate' => $isDuplicate]); } - public function smapletest() - { - $headers = [ - 'S.No', - 'NAME OF EMP/DEP', - 'EMP ID', - // 'EMP/DEP TYPE', - // 'RELATIONSHIP CODE', - 'DOB', - 'GENDER', - 'PRE EXISTING AILMENTS', - 'BASIC COVER SI', - 'DATE OF COVERAGE', - 'AGE', - 'RELATIONSHIP', - 'REMARKS', - 'POLICY END DATE', - 'NO OF DAYS', - 'TPA ID', - 'UHID', - // 'PREMIUM', - 'PRO RATA PREMIUM', - 'GST', - 'TOTAL AMOUNT' - ]; - $filePath = generateExcelWithHeader($headers); - echo "Excel file created at: $filePath"; - } - public function testMailAttachments($email = 'venkateshraman786@gmail.com') { $message = '

Request for Quotation (RFQ)

Dear {{RECIPIENT_NAME}},

We are reaching out to request a quotation for the following insurance coverage. Please review the details below and provide your quote at your earliest convenience.

RFQ Details

Client name{{CLIENT_NAME}}
Coverage Type{{POLICY_LONG_NAME}}
Policy Start Date{{POLICY_START_DATE}}
Policy Duration{{DURATION}}
Please note: Additional terms and details are included in the attachment for your reference.

Please feel free to reach out if you require any further information to prepare the quote. We look forward to receiving your proposal.

Best regards,

Nhance India Pvt Ltd

'; @@ -510,7 +482,6 @@ class ClientController extends AdminController // $this->loadLayout('client_onboarding', $data); } - public function typeList($id = null) { try { @@ -547,7 +518,6 @@ class ClientController extends AdminController } } - public function updateEmpAndPolicyStatus() { $return = $this->clientPolicyModel->updateStatus(); @@ -678,7 +648,7 @@ class ClientController extends AdminController // echo "
";
         // print_r($data); die;
-        $data['placeHolders'] = ['member_name', 'nhance_logo', 'tpa_id', 'ecard_download_link', 'client_logo', 'policy_no', 'member_summary', 'app_link', 'post_enrollment_app_link', 'client_name'];
+        $data['placeHolders'] = ['hr_name', 'member_name', 'nhance_logo', 'tpa_id', 'ecard_download_link', 'client_logo', 'policy_no', 'member_summary', 'app_link', 'post_enrollment_app_link', 'client_name'];
 
         // dd($data['placeHolders']);
 
@@ -982,7 +952,7 @@ class ClientController extends AdminController
                 }, $rawList)) : [];
         $editData['client_policy']['role'] = get_role_id();
         $editData['notification'] = $this->notificationModel->select('template_name,enabled')->where('client_id', $id)->findAll();
-        $editData['placeHolders'] = ['member_name', 'member_mobile', 'nhance_logo', 'tpa_id', 'ecard_download_link', 'client_logo', 'policy_no', 'member_summary', 'app_link', 'post_enrollment_app_link', 'client_name'];
+        $editData['placeHolders'] = ['hr_name', 'member_name', 'member_mobile', 'nhance_logo', 'tpa_id', 'ecard_download_link', 'client_logo', 'policy_no', 'member_summary', 'app_link', 'post_enrollment_app_link', 'client_name'];
         $editData['api_data'] = $this->clientApi->where("client_id", $id)->where("is_active", 1)->first();
         // dd($editData);
 
@@ -1641,7 +1611,7 @@ class ClientController extends AdminController
     }
 
 
-    public function createClientBranch()
+    public function createClientBranchNew()
     {
 
         $this->myLogger->logme('error', 'Client branch CREATE function called');
@@ -1826,7 +1796,7 @@ class ClientController extends AdminController
         }
     }
 
-    public function editClientBranch()
+    public function editClientBranchNew()
     {
 
         $this->myLogger->logme('error', 'Client branch EDIT function called');
@@ -1946,11 +1916,9 @@ class ClientController extends AdminController
             $level_contact_data = [];
 
             if (!empty($level_contact_data_raw)) {
-                $level_contact_data_decoded = json_decode($level_contact_data_raw, true);
+                $level_contact_data_decoded = json_decode($level_contact_data_raw ?? '{}', true);
 
-                if (json_last_error() === JSON_ERROR_NONE && is_array($level_contact_data_decoded)) {
                     $level_contact_data = sanitizeInputArrayAdvanced($level_contact_data_decoded);
-                }
             }
 
             if (!empty($level_contact_data)) {
@@ -1979,6 +1947,367 @@ class ClientController extends AdminController
         }
     }
 
+    public function saveLevelContactsNew($level_contact_data, $branch_id)
+    {
+        if (!empty($level_contact_data) && is_array($level_contact_data)) {
+            foreach ($level_contact_data as $value) {
+                if (!empty($value['id'])) {
+                    $id = $value['id'];
+                    unset($value['id']);
+                    $this->levelContactModel->update($id, $value);
+                } else {
+                    unset($value['id']);
+                    $value['contact_type'] = "client";
+                    $value['ref_id'] = $branch_id ?? null;
+                    $this->levelContactModel->insert($value);
+                }
+            }
+        }
+    }
+
+    public function removeLevelContactsNew()
+    {
+        $id = $this->request->getGet('id');
+        try {
+            if (empty($id)) {
+                return $this->respond([
+                    'status'  => false,
+                    'message' => 'Invalid ID provided. ID is empty',
+                    'data' => $id
+                ], 400);
+            }
+
+            $updated = $this->levelContactModel->update($id, ['is_active' => 0]);
+
+            if ($updated === false) {
+                return $this->respond([
+                    'status'  => false,
+                    'message' => 'Failed to remove contact'
+                ], 500);
+            }
+
+            return $this->respond([
+                'status'  => true,
+                'message' => 'Contact removed successfully'
+            ]);
+        } catch (\Exception $e) {
+            return $this->respond([
+                'status'  => false,
+                'message' => 'An error occurred: ' . $e->getMessage()
+            ], 500);
+        }
+    }
+
+
+    
+    public function createClientBranch()
+    {
+
+        $this->myLogger->logme('error', 'Client branch CREATE function called');
+
+        $rules = [
+            'branch_name' => [
+                'rules' => 'required',
+                'errors' => [
+                    'required' => 'Branch Name is required',
+                ]
+            ],
+            'branch_code' => [
+                'rules' => 'required',
+                'errors' => [
+                    'required' => 'Branch Code is required',
+                ]
+            ],
+            'address1' => [
+                'rules' => 'required',
+                'errors' => [
+                    'required' => 'Address Line 1 is required',
+                ]
+            ],
+            'state' => [
+                'rules' => 'required',
+                'errors' => [
+                    'required' => 'State is required',
+                ]
+            ],
+            'district' => [
+                'rules' => 'required',
+                'errors' => [
+                    'required'    => 'District is required.',
+                ]
+            ],
+            'city' => [
+                'rules' => 'required',
+                'errors' => [
+                    'required'    => 'City is required.',
+                ]
+            ],
+            'pincode' => [
+                'rules' => 'required',
+                'errors' => [
+                    'required'    => 'Pincode is required.',
+                ]
+            ],
+            'gst' => [
+                'rules'  => 'required|regex_match[/^\d{2}[A-Z]{5}\d{4}[A-Z]{1}[A-Z\d]{1}Z[A-Z\d]{1}$/]',
+                'errors' => [
+                    'required'    => 'GST number is required',
+                    'regex_match' => 'Invalid GST Number. Example: 12ABCDE1234F5Z6'
+                ]
+            ],
+            'name.*' => [
+                'rules'  => 'required|alpha_space',
+                'errors' => [
+                    'required'    => 'Contact name is required',
+                    'alpha_space' => 'Contact name may contain only letters and spaces'
+                ]
+            ],
+            'designation.*' => [
+                'rules'  => 'required|alpha_space',
+                'errors' => [
+                    'required'    => 'Designation is required',
+                    'alpha_space' => 'Designation may contain only letters and spaces'
+                ]
+            ],
+            'email.*' => [
+                'rules'  => 'required|valid_email',
+                'errors' => [
+                    'required'    => 'Email is required',
+                    'valid_email' => 'Please enter a valid email address'
+                ]
+            ],
+            'mobile.*' => [
+                'rules'  => 'required|numeric|exact_length[10]',
+                'errors' => [
+                    'required'      => 'Mobile number is required',
+                    'numeric'       => 'Mobile number must contain digits only',
+                    'exact_length'  => 'Mobile number must be exactly 10 digits'
+                ]
+            ],
+        ];
+
+        if (!$this->validate($rules)) {
+            return $this->response->setStatusCode(400)->setJSON([
+                'status' => false,
+                'message' => 'Input validation failed',
+                'code' => 400,
+                'errors' => $this->validator->getErrors()
+            ]);
+        }
+
+        $data = $this->request->getPost();
+        $data = sanitizeInputArrayAdvanced($data);
+
+
+        if (!isset($data['sez'])) {
+            $data['sez'] = 0;
+        } elseif ($data['sez']) {
+            $data['sez'] = 1;
+        }
+
+        $units = json_decode($data['units'], true) ?? [];
+
+        if (!is_array($units) || empty($units)) {
+            $client_data = $this->clientModel->where('id', $data['client_id'])->first();
+            $default_unit = trim(($client_data['short_name'] ?? '') . '-' . ($data['branch_code'] ?? ''), '-');
+            $data['units'] = json_encode([$default_unit]);
+        }
+
+        $data['created_by'] = get_session_userid();
+
+        
+        // before updating check if pre_branch_id is already existing in the current db
+
+        if(isset($data['pre_branch_id']) && !empty($data['pre_branch_id']))
+        {
+            $existing_pre_branch = $this->clientBranchModel
+                                    ->where('pre_branch_id',$data['pre_branch_id'])
+                                    //->where('id !=',$post_branch_id)
+                                    ->first();
+
+            if($existing_pre_branch)
+            {
+                return $this->respond([
+                    'status' => false,
+                    'code' => 409,
+                    'message' => 'The  branch  is already mapped with another branch. Please check.',
+                ], 409);
+            }
+        }
+
+
+
+        $insert = $this->clientBranchModel->insert($data);
+
+        $post_branch_id = $insert;
+
+        if ($insert) {
+            $level_contact_data = $this->request->getPost('level_contect_data');
+            $level_contact_data = !empty($level_contact_data) ? json_decode($level_contact_data, true) : null;
+            $this->saveLevelContacts($level_contact_data, $insert);
+        }
+
+        if($post_branch_id && isset($data['pre_branch_id']) && !empty($data['pre_branch_id']))
+        {
+            // need to update the client_branch in the pre
+            $result = $this->updatePreClientBranch($data['pre_branch_id'],$post_branch_id , "create");
+
+            log_message('error','Pre client_branch update result for pre_branch_id '.$data['pre_branch_id'].' and post_branch_id '.$post_branch_id.' is '.json_encode($result));
+        }
+
+        if ($insert) {
+            $branchData = $this->clientBranchModel->where('client_id', $this->request->getPost('client_id'))->findAll();
+            $branchData['role'] = get_role_id();
+            return $this->respond([
+                'status' => true,
+                'code' => 200,
+                'data' => $branchData,
+                'message' => 'Client branch created successfully',
+            ], 200);
+        } else {
+            return $this->respond([
+                'status' => false,
+                'code' => 404,
+                'message' => 'Failed to create client branch ',
+            ], 200);
+        }
+    }
+
+    public function editClientBranch()
+    {
+
+        $this->myLogger->logme('error', 'Client branch EDIT function called');
+        $id     = $this->request->getPost('branch_id_primarykey');
+        $client_id     = $this->request->getPost('client_id');
+        $pre_branch_id = $this->request->getPost('pre_branch_id') ?? '';
+
+        $data   = $this->request->getPost();
+        $data = sanitizeInputArrayAdvanced($data);
+        $data['pre_branch_id']  = $pre_branch_id;
+
+        $units   = $this->request->getPost('units');
+
+        $emp_unit_count = 0;
+        $rr_unit_count  = 0;
+        $rr_unit_count2 = 0;
+        $total_count    = 0;
+
+        $list_of_branch_units = $this->clientBranchModel->find((int)$id);
+        $units = json_decode($list_of_branch_units['units']);
+
+        if (!is_array($units) || empty($units)) {
+            $client_data = $this->clientModel->where('id', $data['client_id'])->first();
+            $default_unit = trim(($client_data['short_name'] ?? '') . '-' . ($data['branch_code'] ?? ''), '-');
+            $data['units'] = json_encode([$default_unit]);
+        }
+
+        if (!empty($units)) {
+            foreach ($units as $unit) {
+                $emp_unit_count += $this->employeeModel->where('unit', $unit)->countAllResults();
+                $rr_unit_count += $this->policyPremium2Model->where('unit', $unit)->countAllResults();
+                $rr_unit_count2 += $this->policyPremium1Model->where('unit', $unit)->countAllResults();
+            }
+
+            $total_count = $emp_unit_count + $rr_unit_count + $rr_unit_count2;
+        }
+
+        $uncommonValues = [];
+
+        if ($total_count > 0) {
+            $units = (string) $this->request->getPost('units'); // Assuming 'units' is an array
+
+            $list_of_branch_units = $this->clientBranchModel->find((int)$id);
+            $branch_units = json_decode($list_of_branch_units['units'], true);
+            $units = json_decode($units);
+
+            $uncommonValues = array_diff($branch_units, $units);
+
+            if (count($uncommonValues) > 0) {
+
+                $branchData = $this->clientBranchModel->where('client_id', $client_id)->findAll();
+
+                return $this->respond([
+                    'status' => false,
+                    'code' => 404,
+                    'message' => "Deleted unit(s) in use. couldn't complete this operation.",
+                    'uncommonValues' => $uncommonValues,
+                    'data' => $branchData,
+                ], 200);
+            }
+        }
+
+        if (!isset($data['sez'])) {
+            $data['sez'] = 0;
+        } elseif ($data['sez']) {
+            $data['sez'] = 1;
+        }
+
+        $data['updated_by'] = get_session_userid();
+
+        $post_branch_id = $id;
+
+        // before updating check if pre_branch_id is already existing in the current db
+
+        if(isset($data['pre_branch_id']) && !empty($data['pre_branch_id']))
+        {
+            $existing_pre_branch = $this->clientBranchModel
+                                    ->where('pre_branch_id',$data['pre_branch_id'])
+                                    ->where('id !=',$post_branch_id)
+                                    ->first();
+
+            if($existing_pre_branch)
+            {
+                return $this->respond([
+                    'status' => false,
+                    'code' => 409,
+                    'message' => 'The  branch  is already mapped with another branch. Please check.',
+                ], 409);
+            }
+        }
+
+        $insert = $this->clientBranchModel->update($id, $data);
+
+
+
+        if($post_branch_id && isset($data['pre_branch_id']) && !empty($data['pre_branch_id']))
+        {
+            // need to update the client_branch in the pre
+            $result = $this->updatePreClientBranch($data['pre_branch_id'],$post_branch_id , "update");
+
+            log_message('error','Pre client_branch update result for pre_branch_id '.$data['pre_branch_id'].' and post_branch_id '.$post_branch_id.' is '.json_encode($result));
+        }
+
+
+        $this->myLogger->logme('error', 'Client branch EDITED by {data}', ['data' => get_session_userid()]);
+
+
+        if ($insert) {
+
+            $level_contact_data = $this->request->getPost('level_contect_data');
+            $level_contact_data = !empty($level_contact_data) ? json_decode($level_contact_data, true) : null;
+            $this->saveLevelContacts($level_contact_data, $id);
+        }
+
+        if ($insert) {
+            $branchData = $this->clientBranchModel->where('client_id', $client_id)->findAll();
+            return $this->respond([
+                'status' => true,
+                'code' => 200,
+                'data' => $branchData,
+                'emp_unit_count' => $emp_unit_count,
+                'rr_unit_count' => $rr_unit_count,
+                'list_of_branch_units' => $list_of_branch_units,
+                'total_count' => $total_count,
+                'uncommonValues' => $uncommonValues,
+                'message' => 'Client branch updated successfully',
+                'response_data' => $this->request->getPost()
+
+            ], 200);
+        } else {
+            return $this->respond(['status' => false, 'code' => 404, 'message' => 'Failed to update client branch'], 200);
+        }
+    }
+
     public function saveLevelContacts($level_contact_data, $branch_id)
     {
         if (!empty($level_contact_data) && is_array($level_contact_data)) {
@@ -2088,6 +2417,7 @@ class ClientController extends AdminController
         $sanitized_post_data['enrolment_visibility']               = $sanitized_post_data['enrolment_visibility'] ?? null ? 1 : 0;
         $sanitized_post_data['is_lgbtq']                           = $sanitized_post_data['is_lgbtq'] ?? null ? 1 : 0;
         $sanitized_post_data['wellness_vendor_id']                 = !empty($sanitized_post_data['wellness_vendor_id']) ? $sanitized_post_data['wellness_vendor_id'] : null;
+        $sanitized_post_data['cd_ac_pk']                           = $sanitized_post_data['cd_ac_no']  ?? null;
 
 
         if ($policy_type_id == 1 || $policy_type_id == 2 || $policy_type_id == 6 || $policy_type_id == 7) {
@@ -2126,6 +2456,8 @@ class ClientController extends AdminController
 
         $insert = $this->clientPolicyModel->insert($sanitized_post_data);
         if ($insert) {
+            // this function to create a policy transaction entry at the time of client policy create
+            $this->createPolicyTransactionInceptionEntry($insert, $sanitized_post_data);
             $clientPoliceData =  $this->clientPolicyModel->getClientPolicyByClientId($sanitized_post_data['client_id']);
             $clientPoliceData['role'] = get_role_id();
             return $this->respond(['status' => true, 'code' => 200, 'data' => $clientPoliceData, 'client_id' => $client_id, 'method' => 'CERATE', 'post_data' => $insert], 200);
@@ -2310,6 +2642,29 @@ class ClientController extends AdminController
         }
     }
 
+    public function createPolicyTransactionInceptionEntry($client_policy_id, $data)
+    {   
+        $data['action_type'] = 'inception';
+        $data['client_policy_id'] = $client_policy_id;
+        $data['entry_from'] = 3;
+        $data['issuer_branch'] = 1;
+        $data['issuer'] = 2;
+        $data['status'] = 'completed';
+        $data['renewal_date'] = $data['policy_end_date'];
+        $data['bro_payable_by'] = 1;
+        $insert = $this->policyTransactionModel->insert($data);
+
+        if($insert){
+
+            $pcsd_data['pt_id'] = $insert;
+            $pcsd_data['insurer_id'] = $data['insurer_id'] ?? null;
+            $pcsd_data['insurer_branch_id'] = $data['insurer_branch_id'] ?? null;
+
+            $this->PTCOShareDetailsModel->insert($pcsd_data);
+        }
+        return $insert;
+    }
+
 
 
     // Save Rack Rate function
@@ -2843,7 +3198,6 @@ class ClientController extends AdminController
         }
     }
 
-
     private function updatePTCoShareTableEntry($policy_transaction_data, $old_client_policy_data, $data)
     {
         $updated_ids = [];
@@ -2889,9 +3243,6 @@ class ClientController extends AdminController
         ];
     }
 
-
-
-
     public function uploadVehicleFile($params = null)
     {
         $this->myLogger->logme('error', 'uploadVehicleFile function called');
@@ -3611,194 +3962,6 @@ class ClientController extends AdminController
         }
     }
 
-    // public function enrollmentGMCDisplayValueTransform()
-    // {
-    //     $data = [];
-
-    //     if ($this->request->getPost("waiverofpreexistingdiseases_display")) {
-    //         $data['Waiver of Pre-existing Diseases'] = $this->request->getPost("waiverofpreexistingdiseases");
-    //     }
-
-    //     if ($this->request->getPost("waiverof1234thyearexclusions_display")) {
-    //         $data['Waiver of 1, 2, 3 & 4th year Exclusions'] = $this->request->getPost("waiverof1,2,3&4thyearexclusions");
-    //     }
-
-    //     if ($this->request->getPost("waiverof30dayswaitingperiod_display")) {
-    //         $data['Waiver of 30 days waiting period'] = $this->request->getPost("waiverof30dayswaitingperiod");
-    //     }
-
-    //     if ($this->request->getPost("suminsuredenhancement_display")) {
-    //         $data['Sum Insured Enhancement'] = $this->request->getPost("suminsuredenhancement");
-    //     }
-
-    //     if ($this->request->getPost("waiver_of_90_days_waiting_period_display")) {
-    //         $data['Waiver of 90 Days Waiting Period'] = $this->request->getPost("waiver_of_90_days_waiting_period");
-    //     }
-
-    //     if ($this->request->getPost("waiver_of_other_waiting_periods_display")) {
-    //         $data['Waiver of Other Waiting Periods'] = $this->request->getPost("waiver_of_other_waiting_periods");
-    //     }
-
-    //     if ($this->request->getPost("maternity_benefit_display")) {
-    //         $data['Maternity Benefit'] = $this->request->getPost("maternity_benefit");
-    //     }
-
-    //     if ($this->request->getPost("9monthwaitingperiodwaived_display")) {
-    //         $data['9-month waiting Period - waived'] = $this->request->getPost("9monthwaitingperiodwaived");
-    //     }
-
-    //     if ($this->request->getPost("maternitycoverage_display")) {
-    //         $data['Maternity Coverage'] = $this->request->getPost("maternitycoverage");
-    //     }
-
-    //     if ($this->request->getPost("twindelivery_display")) {
-    //         $data['Twin Delivery'] = $this->request->getPost("twindelivery");
-    //     }
-
-    //     if ($this->request->getPost("well_baby_well_mother_expenses_display")) {
-    //         $data['Well baby / Well Mother Expenses'] = $this->request->getPost("well_baby_well_mother_expenses");
-    //     }
-
-    //     if ($this->request->getPost("preandpostnatal_display")) {
-    //         $data['Pre and Post natal'] = $this->request->getPost("preandpostnatal");
-    //     }
-
-    //     if ($this->request->getPost("infertility_treatment_coverage_display")) {
-    //         $data['Infertility Treatment Coverage'] = $this->request->getPost("infertility_treatment_coverage");
-    //     }
-
-    //     if ($this->request->getPost("babyday1cover_display")) {
-    //         $data['Baby Day 1 Cover'] = $this->request->getPost("babyday1cover");
-    //     }
-
-    //     if ($this->request->getPost("coverfromthedateofjoining_display")) {
-    //         $data['Cover from the date of Joining'] = $this->request->getPost("coverfromthedateofjoining");
-    //     }
-
-    //     if ($this->request->getPost("mid_term_addition_of_new_born_newly_wedded_spouse_display")) {
-    //         $data['Mid Term Addition of New Born / Newly Wedded Spouse'] = $this->request->getPost("mid_term_addition_of_new_born_newly_wedded_spouse");
-    //     }
-
-    //     if ($this->request->getPost("prehospitalizationcover_display")) {
-    //         $data['Pre Hospitalization Cover'] = $this->request->getPost("prehospitalizationcover");
-    //     }
-
-    //     if ($this->request->getPost("posthospitalizationcover_display")) {
-    //         $data['Post Hospitalization Cover'] = $this->request->getPost("posthospitalizationcover");
-    //     }
-
-    //     if ($this->request->getPost("congenitaldiseasesinternal_display")) {
-    //         $data['Congenital Diseases - Internal'] = $this->request->getPost("congenitaldiseasesinternal");
-    //     }
-
-    //     if ($this->request->getPost("congenitaldiseasesexternal_display")) {
-    //         $data['Congenital Diseases - External'] = $this->request->getPost("congenitaldiseasesexternal");
-    //     }
-
-    //     if ($this->request->getPost("copayzonewisecopay_display")) {
-    //         $data['Co-Pay/Zone wise Co Pay'] = $this->request->getPost("copayzonewisecopay");
-    //     }
-
-    //     if ($this->request->getPost("roomrentlimit_display")) {
-    //         $data['Room Rent Limit'] = $this->request->getPost("roomrentlimit");
-    //     }
-
-    //     if ($this->request->getPost("icu_limit_display")) {
-    //         $data['ICU Limit'] = $this->request->getPost("icu_limit");
-    //     }
-
-    //     if ($this->request->getPost("proportionatedeductionclause_display")) {
-    //         $data['Proportionate Deduction Clause'] = $this->request->getPost("proportionatedeductionclause");
-    //     }
-
-    //     if ($this->request->getPost("ailmentcapping_display")) {
-    //         $data['Ailment capping'] = $this->request->getPost("ailmentcapping");
-    //     }
-
-    //     if ($this->request->getPost("ailment_capping_details_display")) {
-    //         $data['Ailment capping Details'] = $this->request->getPost("ailment_capping_details");
-    //     }
-
-    //     if ($this->request->getPost("corporatebuffer_display")) {
-    //         $data['Corporate Buffer'] = $this->request->getPost("corporatebuffer");
-    //     }
-
-    //     if ($this->request->getPost("non_admissible_contingency_corporate_buffer_display")) {
-    //         $data['Non-Admissible / Contingency Corporate Buffer'] = $this->request->getPost("non_admissible_contingency_corporate_buffer");
-    //     }
-
-    //     if ($this->request->getPost("ambulancecharges_display")) {
-    //         $data['Ambulance Charges'] = $this->request->getPost("ambulancecharges");
-    //     }
-
-    //     if ($this->request->getPost("airambulance_display")) {
-    //         $data['Air Ambulance'] = $this->request->getPost("airambulance");
-    //     }
-
-    //     if ($this->request->getPost("reasonableandcustomarycharges_display")) {
-    //         $data['Reasonable and Customary Charges'] = $this->request->getPost("reasonableandcustomarycharges");
-    //     }
-
-    //     if ($this->request->getPost("daycaretreatment_display")) {
-    //         $data['Day Care Treatment'] = $this->request->getPost("daycaretreatment");
-    //     }
-
-    //     if ($this->request->getPost("lasiksurgery_display")) {
-    //         $data['Lasik Surgery'] = $this->request->getPost("lasiksurgery");
-    //     }
-
-    //     if ($this->request->getPost("ayushtreatmentcover_display")) {
-    //         $data['AYUSH treatment cover'] = $this->request->getPost("ayudhtreatmentcover");
-    //     }
-
-    //     if ($this->request->getPost("moderntreatmentsasperirdai_display")) {
-    //         $data['Modern treatments as per IRDAI'] = $this->request->getPost("moderntreatmentsasperirdai");
-    //     }
-
-    //     if ($this->request->getPost("opd_treatment_display")) {
-    //         $data['OPD Treatment'] = $this->request->getPost("opd_treatment");
-    //     }
-
-    //     if ($this->request->getPost("days_of_discharge_display")) {
-    //         $data['Claim Intimation Clause'] = $this->request->getPost("days_of_discharge");
-    //     }
-
-    //     if ($this->request->getPost("days_from_dod_display")) {
-    //         $data['Claim Submission'] = $this->request->getPost("days_from_dod");
-    //     }
-
-    //     if ($this->request->getPost("terrorism_display")) {
-    //         $data['Terrorism'] = $this->request->getPost("terrorism");
-    //     }
-
-    //     if ($this->request->getPost("widower_cover_display")) {
-    //         $data['Widower Cover'] = $this->request->getPost("widower_cover");
-    //     }
-
-    //     if ($this->request->getPost("breavement_cover_display")) {
-    //         $data['Breavement Cover'] = $this->request->getPost("breavement_cover");
-    //     }
-
-    //     if ($this->request->getPost("special_condition_display_value")) {
-
-    //         $specialConditionKeyValue = $this->request->getPost("special_condition_display_value") ?? [];
-    //         $specialConditionKeyValue = json_decode($specialConditionKeyValue, true);
-
-    //         if (is_array($specialConditionKeyValue) && count($specialConditionKeyValue) > 0) {
-    //             $mergedArray = array_merge(...array_map(fn($item) => (array) $item, $specialConditionKeyValue));
-    //             $data = array_merge($data, $mergedArray);
-    //         }
-    //     }
-
-    //     if(isset($data) && !empty($data)){
-    //         return $data;
-    //     }else{
-    //         $data = [];
-    //         return $data;
-    //     }
-
-    // }
-
     public function enrollmentGMCDisplayValueTransform()
     {
         $data = [];
@@ -3873,7 +4036,6 @@ class ClientController extends AdminController
         return $data;
     }
 
-
     public function getterms()
     {
         $client_policy_id = $this->request->getVar('client_policy_id');
@@ -4034,94 +4196,6 @@ class ClientController extends AdminController
         }
     }
 
-    // public function enrollmentGPADisplayValueTransform()
-    // {   
-    //     $data = [];
-
-    //     if ($this->request->getPost("accidentalDeathBenefit_display")) {
-    //         $data['Accidental Death Benefit'] = $this->request->getPost("accidentalDeathBenefit");
-    //     }
-    //     if ($this->request->getPost("permanentTotalDisablement_display")) {
-    //         $data['Permanent Total Disablement'] = $this->request->getPost("permanentTotalDisablement");
-    //     }
-    //     if ($this->request->getPost("permanentPartialDisablement_display")) {
-    //         $data['Permanent Partial Disablement'] = $this->request->getPost("permanentPartialDisablement");
-    //     }
-    //     if ($this->request->getPost("temporaryTotalDisablementBenefit_display")) {
-    //         $data['Temporary Total Disablement Benefit'] = $this->request->getPost("temporaryTotalDisablementBenefit");
-    //     }
-    //     if ($this->request->getPost("medical_expenses_medical_extension_display")) {
-    //         $data['Medical Expenses / Medical Extension (IPD)'] = $this->request->getPost("medical_expenses_medical_extension");
-    //     }
-    //     if ($this->request->getPost("opd_treatment_cover_display")) {
-    //         $data['OPD Treatment Cover'] = $this->request->getPost("opd_treatment_cover");
-    //     }
-    //     if ($this->request->getPost("ambulanceCharges_display")) {
-    //         $data['Ambulance Charges'] = $this->request->getPost("ambulanceCharges");
-    //     }
-    //     if ($this->request->getPost("repatriation_of_mortal_remains_display")) {
-    //         $data['Repatriation of Mortal Remains'] = $this->request->getPost("repatriation_of_mortal_remains");
-    //     }
-    //     if ($this->request->getPost("childrenEducationWelfareFund_display")) {
-    //         $data['Children Education Welfare Fund'] = $this->request->getPost("childrenEducationWelfareFund");
-    //     }
-    //     if ($this->request->getPost("terrorism_display")) {
-    //         $data['Terrorism'] = $this->request->getPost("terrorism");
-    //     }
-    //     if ($this->request->getPost("worldwideCover_display")) {
-    //         $data['Worldwide Cover'] = $this->request->getPost("worldwideCover");
-    //     }
-    //     if ($this->request->getPost("family_transportation_benefits_display")) {
-    //         $data['Family Transportation Benefits'] = $this->request->getPost("family_transportation_benefits");
-    //     }
-    //     if ($this->request->getPost("fractures_dislocation_burns_display")) {
-    //         $data['Fractures / Dislocation / Burns'] = $this->request->getPost("fractures_dislocation_burns");
-    //     }
-    //     if ($this->request->getPost("coma_display")) {
-    //         $data['Coma'] = $this->request->getPost("coma");
-    //     }
-    //     if ($this->request->getPost("carriageofDeadBody_display")) {
-    //         $data['Carriage of Dead Body'] = $this->request->getPost("carriageOfDeadBody");
-    //     }
-    //     if ($this->request->getPost("compassionateVisitExpenses_display")) {
-    //         $data['Compassionate Visit Expenses'] = $this->request->getPost("compassionateVisitExpenses");
-    //     }
-    //     if ($this->request->getPost("travel_expenses_for_medical_treatment_display")) {
-    //         $data['Travel expenses for Medical Treatment'] = $this->request->getPost("travel_expenses_for_medical_treatment");
-    //     }
-    //     if ($this->request->getPost("daily_cash_allowance_display")) {
-    //         $data['Daily cash Allowance'] = $this->request->getPost("daily_cash_allowance");
-    //     }
-    //     if ($this->request->getPost("artifical_limb_and_prosthesis_display")) {
-    //         $data['Artifical Limb and Prosthesis'] = $this->request->getPost("artifical_limb_and_prosthesis");
-    //     }
-    //     if ($this->request->getPost("animalSnakeInsectBite_display")) {
-    //         $data['Animal/Snake/Insect Bite'] = $this->request->getPost("animalSnakeInsectBite");
-    //     }
-    //     if ($this->request->getPost("air_ambulance_display")) {
-    //         $data['Air Ambulance'] = $this->request->getPost("air_ambulance");
-    //     }
-
-    //     if ($this->request->getPost("gpa_special_condition_display_value")) {
-
-    //         $specialConditionKeyValue = $this->request->getPost("gpa_special_condition_display_value") ?? [];
-    //         $specialConditionKeyValue = json_decode($specialConditionKeyValue, true);
-
-    //         if (is_array($specialConditionKeyValue) && count($specialConditionKeyValue) > 0) {
-    //             $mergedArray = array_merge(...array_map(fn($item) => (array) $item, $specialConditionKeyValue));
-    //             $data = array_merge($data, $mergedArray);
-    //         }
-    //     }
-    //     // print_r($data); die;
-
-    //     if (isset($data) && !empty($data)) {
-    //         return $data;
-    //     } else {
-    //         $data = [];
-    //         return $data;
-    //     }
-    // }
-
     public function enrollmentGPADisplayValueTransform()
     {
         $data = [];
@@ -6613,7 +6687,23 @@ class ClientController extends AdminController
     }
 
     public function sendextraparam()
-    {              
+    {      
+        // $zipService = new \App\Libraries\ZipService();
+        // $source = WRITEPATH . 'uploads/hr_files';
+        // $destination = WRITEPATH . 'tmp/archive_' . date('Ymd') . '.zip';
+
+        // $result = $zipService->createLocalZip($source, $destination);
+
+        // if ($result['status']) {
+        //     echo "File is ready at: " . $result['path'];
+        // } else {
+        //     echo "Error creating zip: " . $result['message'];
+        // }
+
+        // die;
+
+        // $cd = $this->view_Deposit(2, 'rest', ['client_id' => 58, 'cd_ac_pk' => 94]);
+        // dd($cd);
         // $return = db_connect()->table('jobs')->where('id', 1677)->get()->getRowArray();
         // $return = $this->updatePolicyTransactionDataWhileClinetPolicyUpdate(json_decode($data['payload'], true));
         // dd($return);
@@ -6626,7 +6716,10 @@ class ClientController extends AdminController
         // $res = $medi_assist->MediAssistGetBenefDetails(['policy_no' => '97000034240400000030', 'file_id' => 389, 'return_type' => 'job', 'client_policy_id' => 6192 ]); 
         // dd($res);
 
-        // $employeeController = new EmployeeController();
+        $employeeController = new EmployeeController();
+        // $response = $employeeController->getEmployeeEcardFromTmpFolderAndZipToS3(json_decode('{"batch_no":2,"last_emp_policy_id":"13218","folder_name":"bulk_ecards_IOCL-77448855996699885555_2026-02-05_09-32-22","processed_in_this_batch_data_count":7,"pdf_count":0,"hr_id":"1"}', true));
+        // $response = $employeeController->bulkEcardDownloadAsZipFromS3(json_decode('{"client_policy_id":"6066","hr_id":"1"}', true));
+        // dd($response);
         // $employeeController->truncateFileData('633');
         // $res = $this->getHrAccessData(4075); dd($res);
 
@@ -6644,8 +6737,10 @@ class ClientController extends AdminController
         // $response = $ticketServiceController->tpaClaimDumpImporter(["file_id" => 48]); //vidal
         // $response = $ticketServiceController->tpaClaimDumpImporter(["file_id" => 53]); //icici
         // $response = $ticketServiceController->tpaClaimDumpImporter(["file_id" => 54]); //mediassist
-        // $response = $ticketServiceController->tpaClaimDumpToTicketMasterImporters(["file_id" => 48]);
-        // $response = $ticketServiceController->tpaClaimDumpToTicketMasterImporters(["file_id" => 48]);
+        // $response = $ticketServiceController->tpaClaimDumpToTicketMasterImporters(["file_id" => 48]); //vidal
+        // $response = $ticketServiceController->tpaClaimDumpToTicketMasterImporters(["file_id" => 54]); //mediassist
+
+        // $response = $ticketServiceController->tpaClaimDumpToTicketMasterImporters(["file_id" => 4]); //abhi
         // dd($response);
 
         // ---------- TICKET CONTROLLER --------------------------------------------------------------------------------
@@ -6738,7 +6833,7 @@ class ClientController extends AdminController
         // $res = $EmpDataServiceController->importInceptionUpdateTPAandUHID(['file_id' => 310]); dd($res);//for live
         // $res = $EmpDataServiceController->getInceptionBasePremium(["13332","13333","13334","13335","13336"]); dd($res);//for live
         // $res = $EmpDataServiceController->getDeletionBasePremium(["13248","13250","13249","13247"], json_decode('{"employeeIds":["13248","13250","13249","13247"],"client_id":"3927","client_policy_id":"6183","client_branch_id":"1874","cd_ac_no":"CD9751909505","endorsement_no":"END1238","count":4,"event_name":"deletion","policy_name":"GMC","user_id":"48"}', true)); dd($res);//for live
-        // $res = $EmpDataServiceController->makeEntryForBDSPolicyTransaction(json_decode('{"client_policy_id":"6187","endorsement_no":null,"emp_count":5,"action_type":"inception","no_of_insured":3,"no_of_dependent":0}', true)); dd($res);//for live
+        // $res = $EmpDataServiceController->makeEntryForBDSPolicyTransaction(json_decode('{"client_policy_id":"6187","endorsement_no":"000000001","emp_count":5,"action_type":"addition","no_of_insured":3,"no_of_dependent":0, "base_premium" : "1000", "gst" : "180", "policy_issue_date" : "2025-12-31"}', true)); dd($res);//for live
         // $res = $EmpDataServiceController->sendMailForDownloadingECard(['ids' => $ids, 'client_policy_id' => $client_policy_id]);
         // $res = $this->employeePolicyModel->getDeletionEmployeeDataForExportExcel($batch_data, 1); dd($result);
         // $res = $this->employeePolicyModel->getSIEnhancementEmployeesDataForExportExcel($batch_data, 1);
@@ -8026,180 +8121,6 @@ class ClientController extends AdminController
         $combinedHrAccessData = $this->constructHrAccessData($hrAccessData, $client_id ,$pre_client_data['id']);
         return $combinedHrAccessData;
     }
-
-    // do not remove this commented items
-    // public function constructHrAccessData($data, $client_id , $pre_client_id)
-    // {
-    //     // print_rr($data);die;
-
-    //     $preHrs = $data['pre_hr_data'];
-    //     $postHrs = $data['post_hr_data'];
-    //     $hrAccessTableData = $data['hr_access_table_data'];
-    //     $merged = [];
-
-    //     // Merge based on mobile and email
-    //     foreach ($postHrs as $post) {
-    //         $found = false;
-    //         foreach ($preHrs as $index => $pre) {
-
-    //             if ( trim($post['hr_mobile']) == trim($pre['hr_mobile'])  &&  trim($post['hr_mail']) == trim($pre['hr_mail']) ) {
-
-    //                 $merged[] = [
-    //                     'pre_hr_id' => $pre['pre_hr_id'],
-    //                     'post_hr_id' => $post['post_hr_id'],
-    //                     'hr_name' => $post['hr_name'],
-    //                     'hr_mobile' => $post['hr_mobile'],
-    //                     'hr_mail' => $post['hr_mail'],
-    //                     'pre_branch_id' => $pre['pre_branch_id'] ?? null,
-    //                     'post_branch_id'   => $post['post_branch_id'] ?? null,
-    //                     'post_branch_name' => $post['post_branch_name'] ?? null 
-    //                 ];
-    //                 unset($preHrs[$index]); // remove matched pre_hr
-    //                 $found = true;
-    //                 break;
-    //             }
-    //         }
-
-    //         if (!$found) {
-    //             $merged[] = [
-    //                 'pre_hr_id' => null,
-    //                 'post_hr_id' => $post['post_hr_id'],
-    //                 'hr_name' => $post['hr_name'],
-    //                 'hr_mobile' => $post['hr_mobile'],
-    //                 'hr_mail' => $post['hr_mail'],
-    //                 'pre_branch_id' => $pre['pre_branch_id'] ?? null,
-    //                 'post_branch_id' => $post['post_branch_id'] ?? null ,
-    //                 'post_branch_name' => $post['post_branch_name'] ?? null
-    //             ];
-    //         }
-    //     }
-
-    //     // Remaining preHrs (not matched)
-    //     foreach ($preHrs as $pre) {
-
-    //         foreach ($merged as $value) {
-    //             if ( trim($pre['hr_mobile']) == trim($value['hr_mobile'])  &&  trim($pre['hr_mail']) == trim($value['hr_mail']) ) {
-    //                 continue 2; // Skip adding this pre_hr as it's already matched
-    //             }
-    //         }
-            
-    //         $merged[] = [
-    //             'pre_hr_id' => $pre['pre_hr_id'],
-    //             'post_hr_id' => null,
-    //             'hr_name' => $pre['hr_name'],
-    //             'hr_mobile' => $pre['hr_mobile'],
-    //             'hr_mail' => $pre['hr_mail'],
-    //             'pre_branch_id' => $pre['pre_branch_id'] ?? null,
-    //             'post_branch_id' => $post['post_branch_id'] ?? null ,
-    //             'post_branch_name' => $post['post_branch_name'] ?? null
-    //         ];
-    //     }
-
-    //     // dd($merged);
-
-    //     $result = [];
-
-    //     if (empty($hrAccessTableData)) {
-
-    //         // No access data — fill result with hr data and other fields as null
-    //         foreach ($merged as $hr) {
-    //             $result[] = [
-    //                 'hr_access_table_pk' => null,
-    //                 'post_client_id' => $client_id ?? null,
-    //                 'pre_hr_id' => $hr['pre_hr_id'] ?? null,
-    //                 'post_hr_id' => $hr['post_hr_id'] ?? null,
-    //                 'allowed_pre_modules' => [],
-    //                 'allowed_post_modules' => [],
-    //                 'allowed_pre_policies' => [],
-    //                 'allowed_active_policies' => [],
-    //                 'allowed_cd' => [],
-    //                 'hr_name' => $hr['hr_name'] ?? null,
-    //                 'hr_mobile' => $hr['hr_mobile'] ?? null,
-    //                 'hr_mail' => $hr['hr_mail'] ?? null,
-    //                 'pre_branch_id' => $hr['pre_branch_id'] ?? null,
-    //                 'post_branch_id' => $hr['post_branch_id'] ?? null ,
-    //                 'post_branch_name' => $hr['post_branch_name'] ?? null ,
-    //                 'pre_client_id'    => $pre_client_id ?? null
-    //             ];
-    //         }
-    //     } else {
-    //         // First create a map of HR data by post_hr_id for quick lookup
-    //         $hrMap = [];
-    //         foreach ($merged as $hr) {
-    //             $hrMap[$hr['post_hr_id']] = $hr;
-    //         }
-
-    //         // Process access data first
-    //         foreach ($hrAccessTableData as $access) {
-    //             $post_hr_id = $access['post_hr_id'];
-
-    //             // Check if this HR exists in our merged data
-    //             if (isset($hrMap[$post_hr_id])) {
-    //                 $hr = $hrMap[$post_hr_id];
-    //                 $temp_arr_key = $hr['hr_mobile'] . $hr['hr_mail'];
-
-    //                 // Parse allowed modules
-    //                 $allowed_modules = json_decode($access['allowed_modules'], true) ?? null;
-    //                 $allowed_pre_modules = $allowed_modules['pre'] ?? [];
-    //                 $allowed_post_modules = $allowed_modules['post'] ?? [];
-
-    //                 $result[$temp_arr_key] = [
-    //                     'hr_access_table_pk' => $access['id'] ?? null,
-    //                     'post_client_id' => $access['post_client_id'] ?? null,
-    //                     'pre_hr_id' => $hr['pre_hr_id'] ?? null,
-    //                     'post_hr_id' => $hr['post_hr_id'] ?? null,
-    //                     'allowed_pre_modules' => $allowed_pre_modules,
-    //                     'allowed_post_modules' => $allowed_post_modules,
-    //                     'allowed_pre_policies' => json_decode($access['allowed_pre_policies'], true) ?? [],
-    //                     'allowed_active_policies' => json_decode($access['allowed_active_policies'], true) ?? [],
-    //                     'allowed_cd' => json_decode($access['allowed_cd'], true) ?? [],
-    //                     'hr_name' => $hr['hr_name'],
-    //                     'hr_mobile' => $hr['hr_mobile'],
-    //                     'hr_mail' => $hr['hr_mail'],
-    //                     'pre_branch_id' => $hr['pre_branch_id'] ?? null,
-    //                     'post_branch_id' => $hr['post_branch_id'] ?? null ,
-    //                     'post_branch_name' => $hr['post_branch_name'] ?? null ,
-    //                     'pre_client_id'    => $pre_client_id ?? null
-    //                 ];
-
-    //                 // Remove from map so we know it's been processed
-    //                 unset($hrMap[$post_hr_id]);
-    //             }
-    //         }
-
-    //         // Now process any remaining HRs that didn't have access records
-    //         foreach ($hrMap as $hr) {
-    //             $temp_arr_key = $hr['hr_mobile'] . $hr['hr_mail'];
-
-    //             $result[$temp_arr_key] = [
-    //                 'hr_access_table_pk' => null,
-    //                 'post_client_id' => $client_id ?? null,
-    //                 'pre_hr_id' => $hr['pre_hr_id'] ?? null,
-    //                 'post_hr_id' => $hr['post_hr_id'] ?? null,
-    //                 'allowed_pre_modules' => [],
-    //                 'allowed_post_modules' => [],
-    //                 'allowed_pre_policies' => [],
-    //                 'allowed_active_policies' => [],
-    //                 'allowed_cd' => [],
-    //                 'hr_name' => $hr['hr_name'] ?? null,
-    //                 'hr_mobile' => $hr['hr_mobile'] ?? null,
-    //                 'hr_mail' => $hr['hr_mail'] ?? null,
-    //                 'pre_branch_id' => $hr['pre_branch_id'] ?? null,
-    //                 'post_branch_id' => $hr['post_branch_id'] ?? null ,
-    //                 'post_branch_name' => $hr['post_branch_name'] ?? null ,
-    //                 'pre_client_id'    => $pre_client_id ?? null
-    //             ];
-    //         }
-    //     }
-
-
-    //     $resultData['hr_access_data']   = array_values($result);
-    //     $resultData['pre_policy_data']  = $data['pre_policy_data'];
-    //     $resultData['post_policy_data'] = $data['post_policy_data'];
-    //     $resultData['post_cd_data']     = $data['post_cd_data'];
-
-    //     return $resultData;
-    // }    
     
     public function constructHrAccessData($data, $client_id , $pre_client_id)
     {   
@@ -8455,7 +8376,180 @@ class ClientController extends AdminController
             ];
             return ['status' => 'failed', 'code' => 500, 'message' => $th->getMessage(), 'error_data' => $errorData];
         }
-    }       
+    }   
+
+    public function constructHrAccessData_OLD($data, $client_id , $pre_client_id)
+    {
+        // print_rr($data);die;
+
+        $preHrs = $data['pre_hr_data'];
+        $postHrs = $data['post_hr_data'];
+        $hrAccessTableData = $data['hr_access_table_data'];
+        $merged = [];
+
+        // Merge based on mobile and email
+        foreach ($postHrs as $post) {
+            $found = false;
+            foreach ($preHrs as $index => $pre) {
+
+                if ( trim($post['hr_mobile']) == trim($pre['hr_mobile'])  &&  trim($post['hr_mail']) == trim($pre['hr_mail']) ) {
+
+                    $merged[] = [
+                        'pre_hr_id' => $pre['pre_hr_id'],
+                        'post_hr_id' => $post['post_hr_id'],
+                        'hr_name' => $post['hr_name'],
+                        'hr_mobile' => $post['hr_mobile'],
+                        'hr_mail' => $post['hr_mail'],
+                        'pre_branch_id' => $pre['pre_branch_id'] ?? null,
+                        'post_branch_id'   => $post['post_branch_id'] ?? null,
+                        'post_branch_name' => $post['post_branch_name'] ?? null 
+                    ];
+                    unset($preHrs[$index]); // remove matched pre_hr
+                    $found = true;
+                    break;
+                }
+            }
+
+            if (!$found) {
+                $merged[] = [
+                    'pre_hr_id' => null,
+                    'post_hr_id' => $post['post_hr_id'],
+                    'hr_name' => $post['hr_name'],
+                    'hr_mobile' => $post['hr_mobile'],
+                    'hr_mail' => $post['hr_mail'],
+                    'pre_branch_id' => $pre['pre_branch_id'] ?? null,
+                    'post_branch_id' => $post['post_branch_id'] ?? null ,
+                    'post_branch_name' => $post['post_branch_name'] ?? null
+                ];
+            }
+        }
+
+        // Remaining preHrs (not matched)
+        foreach ($preHrs as $pre) {
+
+            foreach ($merged as $value) {
+                if ( trim($pre['hr_mobile']) == trim($value['hr_mobile'])  &&  trim($pre['hr_mail']) == trim($value['hr_mail']) ) {
+                    continue 2; // Skip adding this pre_hr as it's already matched
+                }
+            }
+            
+            $merged[] = [
+                'pre_hr_id' => $pre['pre_hr_id'],
+                'post_hr_id' => null,
+                'hr_name' => $pre['hr_name'],
+                'hr_mobile' => $pre['hr_mobile'],
+                'hr_mail' => $pre['hr_mail'],
+                'pre_branch_id' => $pre['pre_branch_id'] ?? null,
+                'post_branch_id' => $post['post_branch_id'] ?? null ,
+                'post_branch_name' => $post['post_branch_name'] ?? null
+            ];
+        }
+
+        // dd($merged);
+
+        $result = [];
+
+        if (empty($hrAccessTableData)) {
+
+            // No access data — fill result with hr data and other fields as null
+            foreach ($merged as $hr) {
+                $result[] = [
+                    'hr_access_table_pk' => null,
+                    'post_client_id' => $client_id ?? null,
+                    'pre_hr_id' => $hr['pre_hr_id'] ?? null,
+                    'post_hr_id' => $hr['post_hr_id'] ?? null,
+                    'allowed_pre_modules' => [],
+                    'allowed_post_modules' => [],
+                    'allowed_pre_policies' => [],
+                    'allowed_active_policies' => [],
+                    'allowed_cd' => [],
+                    'hr_name' => $hr['hr_name'] ?? null,
+                    'hr_mobile' => $hr['hr_mobile'] ?? null,
+                    'hr_mail' => $hr['hr_mail'] ?? null,
+                    'pre_branch_id' => $hr['pre_branch_id'] ?? null,
+                    'post_branch_id' => $hr['post_branch_id'] ?? null ,
+                    'post_branch_name' => $hr['post_branch_name'] ?? null ,
+                    'pre_client_id'    => $pre_client_id ?? null
+                ];
+            }
+        } else {
+            // First create a map of HR data by post_hr_id for quick lookup
+            $hrMap = [];
+            foreach ($merged as $hr) {
+                $hrMap[$hr['post_hr_id']] = $hr;
+            }
+
+            // Process access data first
+            foreach ($hrAccessTableData as $access) {
+                $post_hr_id = $access['post_hr_id'];
+
+                // Check if this HR exists in our merged data
+                if (isset($hrMap[$post_hr_id])) {
+                    $hr = $hrMap[$post_hr_id];
+                    $temp_arr_key = $hr['hr_mobile'] . $hr['hr_mail'];
+
+                    // Parse allowed modules
+                    $allowed_modules = json_decode($access['allowed_modules'], true) ?? null;
+                    $allowed_pre_modules = $allowed_modules['pre'] ?? [];
+                    $allowed_post_modules = $allowed_modules['post'] ?? [];
+
+                    $result[$temp_arr_key] = [
+                        'hr_access_table_pk' => $access['id'] ?? null,
+                        'post_client_id' => $access['post_client_id'] ?? null,
+                        'pre_hr_id' => $hr['pre_hr_id'] ?? null,
+                        'post_hr_id' => $hr['post_hr_id'] ?? null,
+                        'allowed_pre_modules' => $allowed_pre_modules,
+                        'allowed_post_modules' => $allowed_post_modules,
+                        'allowed_pre_policies' => json_decode($access['allowed_pre_policies'], true) ?? [],
+                        'allowed_active_policies' => json_decode($access['allowed_active_policies'], true) ?? [],
+                        'allowed_cd' => json_decode($access['allowed_cd'], true) ?? [],
+                        'hr_name' => $hr['hr_name'],
+                        'hr_mobile' => $hr['hr_mobile'],
+                        'hr_mail' => $hr['hr_mail'],
+                        'pre_branch_id' => $hr['pre_branch_id'] ?? null,
+                        'post_branch_id' => $hr['post_branch_id'] ?? null ,
+                        'post_branch_name' => $hr['post_branch_name'] ?? null ,
+                        'pre_client_id'    => $pre_client_id ?? null
+                    ];
+
+                    // Remove from map so we know it's been processed
+                    unset($hrMap[$post_hr_id]);
+                }
+            }
+
+            // Now process any remaining HRs that didn't have access records
+            foreach ($hrMap as $hr) {
+                $temp_arr_key = $hr['hr_mobile'] . $hr['hr_mail'];
+
+                $result[$temp_arr_key] = [
+                    'hr_access_table_pk' => null,
+                    'post_client_id' => $client_id ?? null,
+                    'pre_hr_id' => $hr['pre_hr_id'] ?? null,
+                    'post_hr_id' => $hr['post_hr_id'] ?? null,
+                    'allowed_pre_modules' => [],
+                    'allowed_post_modules' => [],
+                    'allowed_pre_policies' => [],
+                    'allowed_active_policies' => [],
+                    'allowed_cd' => [],
+                    'hr_name' => $hr['hr_name'] ?? null,
+                    'hr_mobile' => $hr['hr_mobile'] ?? null,
+                    'hr_mail' => $hr['hr_mail'] ?? null,
+                    'pre_branch_id' => $hr['pre_branch_id'] ?? null,
+                    'post_branch_id' => $hr['post_branch_id'] ?? null ,
+                    'post_branch_name' => $hr['post_branch_name'] ?? null ,
+                    'pre_client_id'    => $pre_client_id ?? null
+                ];
+            }
+        }
+
+
+        $resultData['hr_access_data']   = array_values($result);
+        $resultData['pre_policy_data']  = $data['pre_policy_data'];
+        $resultData['post_policy_data'] = $data['post_policy_data'];
+        $resultData['post_cd_data']     = $data['post_cd_data'];
+
+        return $resultData;
+    }   
 
     public function saveHrAccessData()
     {
@@ -9012,6 +9106,8 @@ class ClientController extends AdminController
         $member_ecard_mail_template              = $this->notificationModel->where('client_id', NULL)->where('template_name', 'member_ecard_mail')->get()->getResultArray()[0] ?? [];
 
         $member_common_mail_template             = $this->notificationModel->where('client_id', NULL)->where('template_name', 'member_common_mail')->get()->getResultArray()[0] ?? [];
+        
+        $hr_cd_insufficient_balance_mail_template  = $this->notificationModel->where('client_id', NULL)->where('template_name', 'hr_cd_insufficient_balance_mail')->get()->getResultArray()[0] ?? [];
 
         $default_member_welcome_mail_template = [
             'client_id'        => $client_id,
@@ -9083,6 +9179,20 @@ class ClientController extends AdminController
             'mail_content_copy' => null
         ];
 
+        $hr_cd_insufficient_balance_mail_template = [
+            'client_id'        => $client_id,
+            'template_name'    => 'hr_cd_insufficient_balance_mail',
+            'subject'          => $hr_cd_insufficient_balance_mail_template['subject'] ?? '',
+            'mail_content'     => $hr_cd_insufficient_balance_mail_template['mail_content'] ?? '',
+            'mail_content_json' => $hr_cd_insufficient_balance_mail_template['mail_content_json'] ?? '',
+
+            'created_by'       => get_session_userid(),
+            'created_at'       => date('Y-m-d H:i:s'),
+            'updated_by'       => null,
+            'updated_at'       => date('Y-m-d H:i:s'),
+            'mail_content_copy' => null
+        ];
+
         $this->myLogger->logme('error', 'Default Mail Template Data ' . json_encode([
             $default_member_welcome_mail_template,
             $default_member_remainder_mail_template,
@@ -9096,24 +9206,14 @@ class ClientController extends AdminController
             $default_member_remainder_mail_template,
             $default_member_review_and_summary_mail_template,
             $default_member_ecard_mail_template,
-            $default_member_common_mail_template
+            $default_member_common_mail_template,
+            $hr_cd_insufficient_balance_mail_template,
         ]);
 
 
         return $default_templates_inserted ? true : false;
     }
 
-    // public function downloadClientKycDocs_2() 
-    // {
-        
-    //     $file = WRITEPATH . 'uploads/client_kyc_documents/' . $file_name; // Example file path
-
-    //     if (file_exists($file)) {
-    //         return $this->response->download($file, null)->setFileName($file_name);
-    //     } else {
-    //         return "File not found.";
-    //     }
-    // }
     public function downloadClientKycDocs_2($file_name = null) 
     {
         if (!$file_name) {
diff --git a/app/Controllers/EmpDataServiceController.php b/app/Controllers/EmpDataServiceController.php
index 8d75b095..4a4e9faf 100755
--- a/app/Controllers/EmpDataServiceController.php
+++ b/app/Controllers/EmpDataServiceController.php
@@ -209,24 +209,23 @@ class EmpDataServiceController extends BaseController
         //check CD amt insufficient only insurer, not tpa // DO NOT REMOVE THIS
         if($export_data['insurer_or_tpa'] == 'insurer')
         {
-            if (!empty($cash_balance)) {
-                clear_cd_balance_session();
-                if ((int) $cash_balance['balance'] == (int) $totals) {
-                    $this->myLogger->logme('error', 'Inception export failed due to insufficient deposit amount.');
-                    $this->myLogger->logme('error', 'Inception export failed due to insufficient deposit amount.  CASH BALANCE : {balance}  and  TOTAL AMOUNT : {total}', ['balance' => $cash_balance['balance'], 'total' => $totals]);
-                    
-                    $cd_session_data = json_encode(['cd_balance' => false, 'cd_amount' => $cash_balance['balance'], 'excel_file_amt' => $totals]);
-                    session()->set('cd_balance_info', $cd_session_data);
-                    session()->set('cd_balance', false);
-
-                     $hr_data = $this->getHrdataForInsufficientMailSend($export_data['client_branch_id']);
-                     $session_data = json_encode(['client_id' => $export_data['client_id'], 'hr_data' => $hr_data]);
-                     session()->set('hr_data', $session_data);
-
-                }else{
-                     session()->set('cd_balance', true);
-                   
-                }
+            if ((int) $cash_balance['balance'] < (int) $totals) {
+                clear_cd_balance_session(); // Clear old junk first
+                
+                $cd_session_data = json_encode([
+                    'cd_balance' => false, 
+                    'cd_amount' => $cash_balance['balance'], 
+                    'excel_file_amt' => $totals
+                ]);
+                
+                session()->set('cd_balance_info', $cd_session_data);
+                session()->set('cd_balance', 'insufficient'); // Use a string status for clarity
+                
+                $hr_data = $this->getHrdataForInsufficientMailSend($export_data['client_branch_id']);
+                session()->set('hr_data', json_encode(['client_id' => $export_data['client_id'], 'hr_data' => $hr_data]));
+            }else{
+                session()->set('cd_balance', 'sufficient'); // Use a string status for clarity
+                session()->set('cd_balance_info', null);
             }
         }
 
@@ -735,17 +734,23 @@ class EmpDataServiceController extends BaseController
         if($export_data['insurer_or_tpa'] == 'insurer')
         {
             if (!empty($cash_balance)) {
-                if ((int) $cash_balance['balance']  < (int) $rounded_totals) {
-                    $this->myLogger->logme('error', 'Inception export failed due to insufficient deposit amount.');
-                    $this->myLogger->logme('error', 'Inception export failed due to insufficient deposit amount.  CASH BALANCE : {balance}  and  TOTAL AMOUNT : {total}', ['balance' => $cash_balance['balance'], 'total' => $totals]);
-                    session()->set('cd_balance', false);
-                    session()->set('cd_amount', $cash_balance['balance']);
-                    session()->set('excel_file_amt', $rounded_totals);
+                if ((int) $cash_balance['balance'] < (int) $totals) {
+                    clear_cd_balance_session(); // Clear old junk first
+                    
+                    $cd_session_data = json_encode([
+                        'cd_balance' => false, 
+                        'cd_amount' => $cash_balance['balance'], 
+                        'excel_file_amt' => $totals
+                    ]);
+                    
+                    session()->set('cd_balance_info', $cd_session_data);
+                    session()->set('cd_balance', 'insufficient'); // Use a string status for clarity
+                    
+                    $hr_data = $this->getHrdataForInsufficientMailSend($export_data['client_branch_id']);
+                    session()->set('hr_data', json_encode(['client_id' => $export_data['client_id'], 'hr_data' => $hr_data]));
                 }else{
-                    session()->set('cd_balance', true);
-                    session()->set('cd_amount', $cash_balance['balance']);
-                    session()->set('excel_file_amt', $rounded_totals);
-
+                    session()->set('cd_balance', 'sufficient'); // Use a string status for clarity
+                    session()->set('cd_balance_info', null);
                 }
             }
         }
@@ -1066,17 +1071,23 @@ class EmpDataServiceController extends BaseController
             if($export_data['insurer_or_tpa'] != 'tpa')// check overal emp premium amt with cd balance only for insurer export, not tpa export
             { 
                 if (!empty($cash_balance)) {
-                    if ((int) $cash_balance['balance']  < (int) $totals) {
-                        $this->myLogger->logme('error', 'Inception export failed due to insufficient deposit amount.');
-                        $this->myLogger->logme('error', 'Inception export failed due to insufficient deposit amount.  CASH BALANCE : {balance}  and  TOTAL AMOUNT : {total}', ['balance' => $cash_balance['balance'], 'total' => $totals]);
-                        session()->set('cd_balance', false);
-                        session()->set('cd_amount', $cash_balance['balance']);
-                        session()->set('excel_file_amt', $totals);
+                    if ((int) $cash_balance['balance'] < (int) $totals) {
+                        clear_cd_balance_session(); // Clear old junk first
+                        
+                        $cd_session_data = json_encode([
+                            'cd_balance' => false, 
+                            'cd_amount' => $cash_balance['balance'], 
+                            'excel_file_amt' => $totals
+                        ]);
+                        
+                        session()->set('cd_balance_info', $cd_session_data);
+                        session()->set('cd_balance', 'insufficient'); // Use a string status for clarity
+                        
+                        $hr_data = $this->getHrdataForInsufficientMailSend($export_data['client_branch_id']);
+                        session()->set('hr_data', json_encode(['client_id' => $export_data['client_id'], 'hr_data' => $hr_data]));
                     }else{
-                        session()->set('cd_balance', true);
-                        session()->set('cd_amount', $cash_balance['balance']);
-                        session()->set('excel_file_amt', $totals);
-
+                        session()->set('cd_balance', 'sufficient'); // Use a string status for clarity
+                        session()->set('cd_balance_info', null);
                     }
                 }
             }
@@ -2195,6 +2206,7 @@ class EmpDataServiceController extends BaseController
                 'event_name' => $file['event_type'],
                 'policy_name' => $policy_name['policy_name'],
                 'user_id' => $user_id,
+                'file_id' => $file_id,
             ]]);
 
             $r = Jobs::addJob(['job_name' => 'makeEntryForBDSPolicyTransaction', 'payload' => [
@@ -2218,7 +2230,7 @@ class EmpDataServiceController extends BaseController
         //send ecard mail if the event is tpa only
         if ($file['insurer_or_tpa'] == 'tpa') {
 
-            if ($get_policy_type['policy_type_id'] != 1) {
+            if (in_array($get_policy_type['policy_type_id'], [2, 3])) {
 
                 // generate e-card and store S3
                 $r = Jobs::addJob(['job_name' => 'bulkGenerateEcardAndStoreinS3', 'payload' => ['client_policy_id' => $client_policy_id]]);
@@ -2634,7 +2646,7 @@ class EmpDataServiceController extends BaseController
             'status' =>  $status_val,
         ]);
 
-        if($client_policy_data['policy_type_id'] != 1){
+        if(in_array($client_policy_data['policy_type_id'], [2, 3])){
             // re-generate e-card and store S3
             $r = Jobs::addJob(['job_name' => 'bulkGenerateEcardAndStoreinS3', 'payload' => ['client_policy_id' => $client_policy_id]]);
         }
@@ -3378,6 +3390,7 @@ class EmpDataServiceController extends BaseController
                 'event_name' => $file['event_type'],
                 'policy_name' => $policy_name['policy_name'],
                 'user_id' => $user_id,
+                'file_id' => $file_id,
             ]]);
 
             $r = Jobs::addJob(['job_name' => 'makeEntryForBDSPolicyTransaction', 'payload' => [
@@ -3889,6 +3902,7 @@ class EmpDataServiceController extends BaseController
                 'event_name' => $file['event_type'],
                 'policy_name' => $policy_name['policy_name'],
                 'user_id' => $user_id,
+                'file_id' => $file_id,
             ]]);
 
             $r = Jobs::addJob(['job_name' => 'makeEntryForBDSPolicyTransaction', 'payload' => [
@@ -4373,7 +4387,8 @@ class EmpDataServiceController extends BaseController
                         'updated_by' => $arrayData['user_id'],
                         'event_name' => $arrayData['event_name'],
                         'is_active' => 1,
-                        'cd_ac_pk'  => $cd_ac_pk['cd_ac_pk']
+                        'cd_ac_pk'  => $cd_ac_pk['cd_ac_pk'],
+                        'file_id' => $arrayData['file_id'],
                     ];
 
                     $response = DepositHelper::saveDeposit($data,  $arrayData['user_id']);
@@ -4510,7 +4525,8 @@ class EmpDataServiceController extends BaseController
                         'updated_by' => $arrayData['user_id'],
                         'event_name' => $arrayData['event_name'],
                         'is_active' => 1,
-                        'cd_ac_pk'  => $policy_data['cd_ac_pk']
+                        'cd_ac_pk'  => $policy_data['cd_ac_pk'],
+                        'file_id' => $arrayData['file_id'],
                     ];
 
                     DepositHelper::saveDeposit($data, $arrayData['user_id']);
@@ -4540,7 +4556,8 @@ class EmpDataServiceController extends BaseController
                         'updated_by' => $arrayData['user_id'],
                         'event_name' => $arrayData['event_name'],
                         'is_active' => 1,
-                        'cd_ac_pk'  => $policy_data['cd_ac_pk']
+                        'cd_ac_pk'  => $policy_data['cd_ac_pk'],
+                        'file_id' => $arrayData['file_id'],
                     ];
 
                     DepositHelper::saveDeposit($data, $arrayData['user_id']);
@@ -4652,7 +4669,8 @@ class EmpDataServiceController extends BaseController
                         'updated_by' => $arrayData['user_id'],
                         'event_name' => $arrayData['event_name'],
                         'is_active' => 1,
-                        'cd_ac_pk'  => $insurer_id['cd_ac_pk']
+                        'cd_ac_pk'  => $insurer_id['cd_ac_pk'],
+                        'file_id' => $arrayData['file_id'],
                     ];
 
                     $response = DepositHelper::saveDeposit($data, $arrayData['user_id']);
@@ -5418,7 +5436,7 @@ class EmpDataServiceController extends BaseController
             $this->myLogger->logme("error", "Policy transaction inserted successfully: " . json_encode(['insert_id' => $insert_id]));
 
             //do not remove this commented item
-            $coShareDetails = $this->ConstructPTShareData($policy_data, $insert_id, $params, $lead_data);
+            $coShareDetails = $this->ConstructPTShareData($policy_data, $insert_id, $params, $lead_data, $params['action_type']);
             $pt_co_share_id = $this->PTCOShareDetailsModel->insert($coShareDetails);
             $this->myLogger->logme("error", "PT Co share data inserted successfully: " . json_encode(['pt_co_share_id' => $pt_co_share_id]));
 
@@ -5550,7 +5568,46 @@ class EmpDataServiceController extends BaseController
         return $policyTransactionData;
     }
 
-    private function ConstructPTShareData($policy_data, $pt_id, $params, $lead_data)
+    private function ConstructPTShareData($policy_data, $pt_id, $params, $lead_data, $action_type)
+    {   
+        $policyTypeModel = new PolicyTypeModel();
+        $policy_type_data = $policyTypeModel->where('is_active', 1)->where('id', $policy_data['policy_type_id'])->first();
+
+        // Determine if we should negate the values
+        $multiplier = (strtolower($action_type) === 'deletion') ? -1 : 1;
+
+        $coShareData = [
+            'pt_id' => $pt_id,
+            'insurer_id' => $policy_data['insurer_id'],
+            'insurer_branch_id' => $policy_data['insurer_branch_id'],
+            'bp_amt' => ($params['base_premium'] ?? 0) * $multiplier,
+            'cop_amt' => ($params['base_premium'] ?? 0) * $multiplier,
+            'bp_gst_amt' => ($params['gst'] ?? 0) * $multiplier,
+            'bp_sgst' => 9, // Usually tax percentages remain positive, but multiply if this is an amount
+            'bp_cgst' => 9,
+            'co_share_type' => 1,
+            'co_share_per' => 100,
+            'standerd_bp_per' => $policy_type_data['ebp'],
+            'pt_policy_issue_date' => $params['policy_issue_date'] ?? null,
+            'amount' => (($params['base_premium'] ?? 0) + ($params['gst'] ?? 0)) * $multiplier,
+        ];
+
+        if(isset($policy_data['gst']) && $policy_data['gst'] != null){
+            $coShareData['bp_igst'] = $policy_data['gst'] ?? 0;
+            $coShareData['bp_sgst'] = 0;
+            $coShareData['bp_cgst'] = 0;
+        }
+
+        // Calculate exp_amt logic
+        $agreed_per = $lead_data['agreed_percentage'] ?? $policy_type_data['ebp'] ?? 0;
+        $coShareData['exp_amt'] = ((($params['base_premium'] ?? 0) * $agreed_per) / 100) * $multiplier;
+
+        $this->myLogger->logme("error", "Constructed PT co-share data: " . json_encode($coShareData));
+
+        return $coShareData;
+    }
+
+    private function ConstructPTShareDataOld($policy_data, $pt_id, $params, $lead_data, $action_type = null)
     {   
         $policyTypeModel = new PolicyTypeModel();
         $policy_type_data = $policyTypeModel->where('is_active', 1)->where('id', $policy_data['policy_type_id'])->first();
diff --git a/app/Controllers/EmployeeController.php b/app/Controllers/EmployeeController.php
index edcae43c..b279f1f2 100755
--- a/app/Controllers/EmployeeController.php
+++ b/app/Controllers/EmployeeController.php
@@ -31,6 +31,7 @@ use App\Models\UserModel;
 use App\Models\PartnerEndorsementRequestModel;
 use App\Models\TpaApiDataModel;
 use App\Models\LevelContactModel;
+use App\Models\NotificationModel;
 
 
 use App\Controllers\Jobs;
@@ -335,7 +336,7 @@ class EmployeeController extends AdminController
                     //endof validation process
                     if (isset($result['error_summary']) && count($result['error_summary'])) {
                         if(!empty($post_data)){
-                            return ['status' => true, 'message' => 'file rejected with errors', 'file_id' => $file_id];
+                            return ['status' => false, 'message' => 'file rejected with errors', 'file_id' => $file_id];
                         }else{
                             return $this->respond(['dataStatus' => false, 'code' => 404, 'message' => 'file rejected with errors'], 200);
                         }
@@ -445,6 +446,7 @@ class EmployeeController extends AdminController
                          batch_files.amount, 
                          batch_files.status,
                          batch_files.client_branch_id,
+                         DATE_FORMAT(batch_files.policy_issue_date, '%d/%m/%Y') AS policy_issue_date,
 
                         CASE 
                             WHEN batch_files.status IN ('partially success', 'in-progress-partially', 'failed-7') 
@@ -483,7 +485,35 @@ class EmployeeController extends AdminController
     }
 
     public function getExcelFileErrors($file_id, $retun_type = null)
-    {
+    {   
+
+        $file_data = $this->fileModel->where('id', $file_id)->first();
+        $error = json_decode($file_data['reason'] ?? '{}', true);
+        if(!empty($error) && $retun_type == 'api'){
+            $send = isset($error['error_summary'][5]) || isset($error['error_summary'][6]) ? true : false;
+            if($send){
+
+
+                $string = $error['error_data'] ?? 'System error';
+
+                $errorMap = [
+                    "Column order conflict" => "Invalid file format. Please use the sample file.",
+                ];
+
+                $message = $string; // Default to the original error
+
+                foreach ($errorMap as $keyword => $friendlyMessage) {
+                    if (strpos($string, $keyword) !== false) {
+                        $message = $friendlyMessage;
+                        break; // Stop looking once we find a match
+                    }
+                }
+
+
+                return $this->respond(['status' => false, 'code' => 404,  'message' => $message, 'data' => []], 200);
+            }
+        }
+
         // $file_id = $this->request->uri->getSegment(3);
         $empServiceController = new EmployeeServiceController();
 
@@ -4434,7 +4464,7 @@ class EmployeeController extends AdminController
          * 4. SEQUENTIAL RE-QUEUE (SAFE)
          * --------------------------------------------------------- */
         if ($execution_mode === 'sequential' && $rowCount === $batch_size) {
-            $this->myLogger->logme('info', "$log_search_context"."Re-queueing next batch - " .  json_encode([
+            $this->myLogger->logme('error', "$log_search_context"."Re-queueing next batch - " .  json_encode([
                 'next_batch' => $batch_no + 1,
                 'last_emp_id' => $new_last_emp_id
             ]));
@@ -4543,7 +4573,6 @@ class EmployeeController extends AdminController
         }
     }
 
-
     public function insufficientCdBalanceHrMailSend()
     {
         $post_data = $this->request->getJson(true);
@@ -4554,29 +4583,38 @@ class EmployeeController extends AdminController
 
         $client_data = $this->clientModel->where('is_active', 1)->where('id', $post_data['client_id'])->first();
 
-        $common['mail_type'] = "insufficient_cd_balance_by_hr";
+        if(empty($client_data)){
+            return $this->respond(['status' => false, 'code' => 404, 'message' => 'No client found'], 200);
+        }
+
+        $notificationModal = new NotificationModel();
+        $notification_data = $notificationModal
+                ->where('client_id', $post_data['client_id'])
+                ->where('template_name', 'hr_cd_insufficient_balance_mail')
+                ->first();
+
+        if(empty($notification_data)){
+            return $this->respond(['status' => false, 'code' => 404, 'message' => 'No template found'], 200);
+        }
+
+        if(empty($notification_data['subject']) || empty($notification_data['mail_content'])){
+            return $this->respond(['status' => false, 'code' => 404, 'message' => 'Template subject or mail content is empty'], 200);
+        }
+    
+        if(empty($notification_data['enabled']) || $notification_data['enabled'] != 1){
+            return $this->respond(['status' => false, 'code' => 404, 'message' => 'Template is disabled'], 200);
+
+        }
+
+        $common['mail_type'] = "hr_cd_insufficient_balance_mail";
         $common['client_id'] = $post_data['client_id'];
-        $subject = 'Insufficient CD Balance Notification';
-        $mail_content = '
-            Dear {{HR_NAME}},
-
-            Greetings from Nhance.
-
-            We would like to inform you that the CD balance for {{CLIENT_NAME}} is currently low / insufficient, which may impact further processing of insurance-related activities.
-
-            Kindly request you to credit the required amount at the earliest to avoid any service disruption.
-
-            Please let us know once the amount is credited, or if you need any clarification from our end.
-
-            Thank you for your support and cooperation.
-        ';
-
+        $subject = $notification_data['subject'];
+        $mail_content = $notification_data['mail_content'];
 
         foreach ($post_data['mails'] as $hr_id => $hr_data) {
 
-            $mail_content = str_ireplace('{{HR_NAME}}', $hr_data['name'], $mail_content);
-            $mail_content = str_ireplace('{{CLIENT_NAME}}', $client_data['client_name'], $mail_content);
-
+            $mail_content = str_ireplace('{{hr_name}}', $hr_data['name'], $mail_content);
+            $mail_content = str_ireplace('{{client_name}}', $client_data['client_name'], $mail_content);
             $res = MailHelper::send_email(['mail' => $hr_data['mail'], 'subject' => $subject, 'message' => $mail_content, 'common' => $common]);
         }
 
@@ -4584,6 +4622,217 @@ class EmployeeController extends AdminController
 
     }
 
+    public function clearCdSession() 
+    {
+        clear_cd_balance_session();
+        return $this->response->setJSON(['status' => 'cleared']);
+    }
 
+    public function checkSessionStatus()
+    {
+        // Uses your existing get_cd_balance() helper
+        $data = get_cd_balance();
+
+        // Return as JSON so JavaScript can read it
+        return $this->response->setJSON($data);
+    }
+
+    public function bulkEcardDownloadAsZipFromS3($params)
+    {
+        try {
+            $limit = $params['limit'] ?? 100;
+            $batch_no = $params['batch_no'] ?? 1;
+            $last_id = $params['last_emp_policy_id'] ?? 0;
+
+            // Fetch batch data
+            $employee_data = $this->employeePolicyModel->getEmployeeDataWithPolicyUsingClientPolicyIdOrEmployeePolicyIds($params, $limit, $last_id);
+
+            if (empty($employee_data)) {
+
+                if(!empty($last_id)){
+                    $this->myLogger->logme('error', "bulkEcardDownloadAsZipFromS3 - No more records after last_emp_policy_id: {$last_id}");
+                    $this->myLogger->logme('error', "getEmployeeEcardFromTmpFolderAndZipToS3 - Queuing ZIP creation for folder: " . ($params['folder_name'] ?? 'N/A'));
+                    $r = Jobs::addJob(['job_name' => 'getEmployeeEcardFromTmpFolderAndZipToS3', 'payload'  => $params]);
+                }
+
+                return ['status' => true, 'message' => 'Proceeding to Zip'];
+            }
+
+            // Use a consistent folder name across batches (passed in params)
+            $folderName = $params['folder_name'] ?? 'bulk_ecards_' . $employee_data[0]['policy_no'] . '_' . date('Y-m-d_H-i-s');
+            $tempPath = FCPATH . 'tmp/' . $folderName . '/';
+
+            if (!is_dir($tempPath)) {
+                mkdir($tempPath, 0777, true);
+            }
+
+            $s3 = \Config\Services::getS3Service();
+            $pdf_count = 0;
+            $current_last_id = end($employee_data)['emp_policy_id'];
+
+            foreach ($employee_data as $emp_value) {
+                // Track the last ID in this batch
+                $current_last_id = $emp_value['emp_policy_id'];
+
+                $s3_key = 'ecard_' . $emp_value['name'] . '(' . $emp_value['emp_code'] . ')' . '_' . $emp_value['tpa_id'] . '.pdf';
+                $s3_key = $this->sanitizeFilePart($s3_key);
+
+                if ($s3->exists($s3_key)) {
+                    $s3_url = $s3->getPresignedUrl($s3_key);
+                    $pdf_content = file_get_contents($s3_url['url']);
+
+                    if ($pdf_content !== false) {
+                        file_put_contents($tempPath . $s3_key, $pdf_content);
+                        $pdf_count++;
+                    }
+                }
+            }
+
+            $hasMore = count($employee_data) == $limit;
+
+            $payload = [
+                'batch_no' => $batch_no + 1,
+                'last_emp_policy_id' => $current_last_id,
+                'folder_name' => $folderName,
+                'processed_in_this_batch_data_count' => count($employee_data),
+                'pdf_count' => $pdf_count,
+                'hr_id' => $params['hr_id'] ?? null
+            ];
+
+            if ($hasMore) {
+                $this->myLogger->logme('error', "bulkEcardDownloadAsZipFromS3 - Queuing next batch: " . json_encode($payload));
+                $r = Jobs::addJob(['job_name' => 'bulkEcardDownloadAsZipFromS3', 'payload'  => $payload]);
+                $message = "Queuing next batch";
+            } else {
+                $this->myLogger->logme('error', "bulkEcardDownloadAsZipFromS3 - No more records after this batch. Next proceeding with getEmployeeEcardFromTmpFolderAndZipToS3");
+                $r = Jobs::addJob(['job_name' => 'getEmployeeEcardFromTmpFolderAndZipToS3', 'payload'  => $payload]);
+                $message = "All batch completed. Next proceeding with getEmployeeEcardFromTmpFolderAndZipToS3";
+            }
+
+            return ['status' => true, 'message' => $message];
+
+        } catch (\Throwable $e) {
+
+            $mail_response = $this->sendMailToHrWithZipAttachments($params);
+
+            $context = [
+                'error_message' => $e->getMessage(),
+                'exception_class' => get_class($e),
+                'file' => $e->getFile(),
+                'line' => $e->getLine(),
+                'trace' => $e->getTraceAsString(),
+                'mail_response' => $mail_response,
+                'params' => $params,
+            ];
+
+            // Log detailed context for debugging
+            $this->myLogger->logme('error', 'bulkEcardDownloadAsZipFromS3 - Exception' . json_encode($context, JSON_PRETTY_PRINT));
+
+            // Return a detailed, structured error response
+            return [
+                'status'  => false,
+                'message' => 'Exception occurred during bulk e-card download and ZIP creation.',
+                'error'   => $context,
+            ];
+        }
+    }
+
+    public function getEmployeeEcardFromTmpFolderAndZipToS3($params)
+    {
+        try {
+
+            $zipService = new \App\Libraries\ZipService();
+
+            $source = FCPATH . 'tmp/' . $params['folder_name'];
+            $destination = '/';
+            $zipName = $params['folder_name'] . '.zip' ?? '';
+
+            $result = $zipService->zipAndUploadS3($source, $destination, $zipName);
+
+            if($result['status'] === false){
+                $this->myLogger->logme('error', "getEmployeeEcardFromTmpFolderAndZipToS3 - ZIP creation/upload failed: " . json_encode($result));
+                $params['url'] = null; // Indicate failure
+            }else{
+                $params['url'] = $result['presigned_url']['url'] ?? null;
+            }
+
+
+
+
+            $mail_response = $this->sendMailToHrWithZipAttachments($params);
+
+            return ['zip_responce' => $result, 'mail_response' => $mail_response];
+
+        } catch (\Throwable $e) {
+
+            $mail_response = $this->sendMailToHrWithZipAttachments($params);
+
+            $context = [
+                'error_message' => $e->getMessage(),
+                'exception_class' => get_class($e),
+                'file' => $e->getFile(),
+                'line' => $e->getLine(),
+                'trace' => $e->getTraceAsString(),
+                'mail_response' => $mail_response,
+                'params' => $params,
+            ];
+
+            // Log detailed context for debugging
+            $this->myLogger->logme('error', 'getEmployeeEcardFromTmpFolderAndZipToS3 - Exception' . json_encode($context, JSON_PRETTY_PRINT));
+
+            // Return a detailed, structured error response
+            return [
+                'status'  => false,
+                'message' => 'Exception occurred during bulk e-card download and ZIP creation.',
+                'error'   => $context,
+            ];
+
+        }
+    }
+
+    public function sendMailToHrWithZipAttachments($params)
+    {
+        $hr_id = $params['hr_id'] ?? null;
+        $url = $params['url'] ?? null;
+
+        if (empty($hr_id)) {
+            $this->myLogger->logme('error', "sendMailToHrWithZipAttachments - No HR ID provided.");
+            return ['status' => false, 'message' => 'No HR ID provided.'];
+        }
+
+        $hr_data = $this->LevelContactModel->where('id', $hr_id)->where('is_active', 1)->first();
+
+        if (empty($hr_data) || empty($hr_data['email'])) {
+            $this->myLogger->logme('error', "sendMailToHrWithZipAttachments - No valid HR data found for ID: {$hr_id}");
+            return ['status' => false, 'message' => 'No valid HR data found for ID: ' . $hr_id];
+        }
+
+        if(empty($url)){
+            $subject = "Employee Bulk E-Card Download Failed";
+            $message = "Dear {$hr_data['name']},

We were unable to generate the bulk e-card ZIP file. Please re-initialize the process or contact support to retry."; + }else{ + $subject = "Employee Bulk E-Cards Download"; + $message = "Dear {$hr_data['name']},

Please find the employee e-cards attached below.

Download Link: Download E-Cards

Note : This link valid for 2 days only."; + } + + $bbc = 'venkateshraman786@gmail.com'; + + $mail_response = MailHelper::send_email([ + 'mail' => $hr_data['email'], + 'subject' => $subject, + 'message' => $message, + 'bcc' => $bbc, + 'common' => [ + 'mail_type' => 'employee_bulk_ecard_download_by_hr', + ] + ]); + + $this->myLogger->logme('error', "sendMailToHrWithZipAttachments - Email sent to HR ID: {$hr_id}, Email Response: " . json_encode($mail_response)); + return $mail_response; + } + + public function downloadZip(){ + + } } diff --git a/app/Controllers/EmployeeRestController.php b/app/Controllers/EmployeeRestController.php index 379fe023..7ca38900 100755 --- a/app/Controllers/EmployeeRestController.php +++ b/app/Controllers/EmployeeRestController.php @@ -40,6 +40,9 @@ use App\Models\HRAccessControlModel; use App\Models\InsurerModel; use App\Models\HrFileUploadModel; use App\Models\EmployeeRetailPolicy; +use App\Models\BatchFileModel; +use App\Models\ClientDepositModel; +use App\Models\PTFileModel; @@ -66,6 +69,8 @@ use Kreait\Firebase\Messaging\CloudMessage; use Kreait\Firebase\Messaging\Notification; use Kreait\Firebase\Exception\MessagingException; +use Firebase\JWT\JWT; + class EmployeeRestController extends AdminController { @@ -100,6 +105,7 @@ class EmployeeRestController extends AdminController protected $hrFileUploadModel; protected $ticketMailTemplateModel; protected $employeeRetailPolicy; + protected $batchFileModel; public function __construct() @@ -134,6 +140,7 @@ class EmployeeRestController extends AdminController $this->insurerModel = new InsurerModel(); $this->hrFileUploadModel = new HrFileUploadModel(); $this->ticketMailTemplateModel = new TicketMailTemplateModel(); + $this->batchFileModel = new BatchFileModel(); } @@ -599,6 +606,7 @@ class EmployeeRestController extends AdminController public function getEmployeeAndDependenceByClientId() { try { + $empData = $this->employeePolicyModel->getEmployeePolicy(client_id: $this->request->getGet('client_id'), policy_id: $this->request->getGet('client_policy_id'), status: 0, branch_id: $this->request->getGet('client_branch_id')); if ($empData) { @@ -2369,6 +2377,8 @@ class EmployeeRestController extends AdminController $value['totalMembersCount'] = count($employeeDetails); $value['membersCountOfActive'] = $activeCount; $value['membersCountOfInactive'] = $inactiveCount; + $value['is_ecard_bulk_download'] = 0; + $value['is_ecard_bulk_download_for_employee'] = 0; array_push($result, $value); @@ -2494,11 +2504,12 @@ class EmployeeRestController extends AdminController $client_id = isset($search_data['client_id']) ? (int) $search_data['client_id'] : 0; unset($search_data['client_id']); unset($search_data['client_branch_id']); + $policy_number = isset($search_data['policy_no']) ? $search_data['policy_no'] : null; $from_date = isset($search_data['from_date']) ? $search_data['from_date'] : null; $to_date = isset($search_data['to_date']) ? $search_data['to_date'] : null; $claim_status_id = isset($search_data['claim_status_id']) ? $search_data['claim_status_id'] : null; - unset($search_data['from_date'], $search_data['to_date'], $search_data['claim_status_id']); + unset($search_data['from_date'], $search_data['to_date'], $search_data['claim_status_id'], $search_data['policy_no']); $where = []; @@ -2618,6 +2629,10 @@ class EmployeeRestController extends AdminController $builder->whereIn('claim_status_id', $claim_status_ids); } + if (!empty($policy_number)) { + $builder->where('cp.policy_no', $policy_number); + } + $builder->orderBy('tm.id', 'DESC'); $data = $builder->get()->getResultArray(); @@ -3622,6 +3637,12 @@ class EmployeeRestController extends AdminController $get_docs_name = $this->request->getPost('claim_doc_names') ?? []; $policy_transaction_id = $this->request->getPost('policy_transaction_id') ?? null; + + if (is_string($received_data['client_id']) && preg_match('/^[a-f0-9]{32}$/i', $received_data['client_id'])) { + $client_data = $this->clientModel->where('MD5(id)', $received_data['client_id'])->first(); + $received_data['client_id'] = $client_data['id'] ?? null; + } + $client_policy_data = $this->clientPolicyModel->where('id', $received_data['client_policy_id'] ?? null)->first(); $isduplicate = checkDuplicateClaim([ @@ -3909,10 +3930,14 @@ class EmployeeRestController extends AdminController log_message('error', 'Ticket validation | Ticket ID: ' . $ticket_id . ' | Matching active tickets with NULL TPA reference: ' . $count); if ($count > 0 && $pdf_exist_in_the_file && $tpa_claim_push == true) { - // this call for TPA integration - $apiServiceController = new ApiServiceController(); - $apiServiceController->pushClaims($ticket_id); - log_message('error', "pushClaims function called with Ticket ID: {$ticket_id}, In Employee Rest Controller"); + try { + // this call for TPA integration + $apiServiceController = new ApiServiceController(); + $apiServiceController->pushClaims($ticket_id); + log_message('error', "pushClaims function called with Ticket ID: {$ticket_id}, In Employee Rest Controller"); + } catch (\Throwable $e) { + log_message('error', "Error in TPA Claim Push via Benifits or HR : ApiServiceController pushClaims function call for Ticket ID: {$ticket_id}. Error: " . $e->getMessage() . " Trace: " . $e->getTraceAsString()); + } } else { if($tpa_claim_push == false){ log_message('error', 'Skip the TPA claim push for IR DOCUMENTS'); @@ -4506,11 +4531,12 @@ class EmployeeRestController extends AdminController $post_data = [ 'client_id' => $this->request->getPost('client_id') ?? null, - 'client_branch_id' => $this->request->getPost('client_branch_id'), - 'policy_id' => $this->request->getPost('policy_id'), - 'file_action' => $this->request->getPost('file_action'), - 'created_by' => $this->request->getPost('created_by'), - 'file_name' => $this->request->getFile('file_name') + 'client_branch_id' => $this->request->getPost('client_branch_id') ?? null, + 'policy_id' => $this->request->getPost('policy_id') ?? null, + 'file_action' => $this->request->getPost('file_action') ?? null, + 'created_by' => $this->request->getPost('created_by') ?? null, + 'file_name' => $this->request->getFile('file_name') ?? null, + 'policy_no' => $this->request->getPost('policy_no') ?? null, ]; // print_r($post_data); die; @@ -4521,6 +4547,7 @@ class EmployeeRestController extends AdminController // Handle raw client_id vs MD5 if (is_string($post_data['client_id']) && preg_match('/^[a-f0-9]{32}$/i', $post_data['client_id'])) { $client_data = $this->clientModel->where('MD5(id)', $post_data['client_id'])->first(); + $post_data['client_id'] = $client_data['id']; } else { $client_data = $this->clientModel->where('id', $post_data['client_id'])->first(); } @@ -4529,10 +4556,6 @@ class EmployeeRestController extends AdminController return $this->respondCreated(['status' => false, 'message' => 'Invalid Client Id', 'data' => []]); } - $post_data['client_id'] = $client_data['id']; - - - // print_r($client_data); die; if($client_data['hr_file_processed_by'] == 1){ @@ -4578,15 +4601,15 @@ class EmployeeRestController extends AdminController // Prepare data $data = [ - 'client_id' => $this->request->getPost('client_id'), - 'client_branch_id' => $this->request->getPost('client_branch_id'), - 'policy_id' => $this->request->getPost('policy_id'), - 'policy_no' => $this->request->getPost('policy_no'), + 'client_id' => $post_data['client_id'], + 'client_branch_id' => $post_data['client_branch_id'], + 'policy_id' => $post_data['policy_id'], + 'policy_no' => $post_data['policy_no'], 'file_name' => $newFileName, - 'file_action' => $this->request->getPost('file_action'), + 'file_action' => $post_data['file_action'], 'status' => 'Yet to start', - 'created_by' => $this->request->getPost('created_by'), - 'updated_by' => $this->request->getPost('created_by'), + 'created_by' => $post_data['created_by'], + 'updated_by' => $post_data['created_by'], ]; // Save into DB @@ -4609,14 +4632,16 @@ class EmployeeRestController extends AdminController $responce = $employeeController->employeesUplodWithEvents($post_data); // print_r($responce); die; - if($responce['status']){ - $file_data = $this->getDataFromHrFilesTable(['file_id' => $responce['file_id']]); - $responce['data'] = $file_data; - return $responce; - }else{ - $responce['data'] = []; - return $responce; - } + return $responce; + + // if(isset($responce['file_id'])){ + // $file_data = $this->getDataFromHrFilesTable(['hr_id' => $responce['created_by']]); + // $responce['data'] = $file_data; + // return $responce; + // }else{ + // $responce['data'] = []; + // return $responce; + // } } private function giveNotificationToClientsAccountManager($data) @@ -4703,28 +4728,40 @@ class EmployeeRestController extends AdminController try { $file_id = $this->request->getGet('id') ?? $id; + $client_id = $this->request->getGet('cliend_id') ?? null; + + $client_data = []; + if(!empty($client_id)){ + if (is_string($client_id) && preg_match('/^[a-f0-9]{32}$/i', $client_id)) { + $client_data = $this->clientModel->where('MD5(id)', $client_id)->first(); + } else { + $client_data = $this->clientModel->where('id', $client_id)->first(); + } + } // Find record - $record = $this->hrFileUploadModel->where('id', (int)$file_id)->find(); - - // print_rr( $record);die; + if($client_data && $client_data['hr_file_processed_by'] == 1){ + $record = $this->fileModel->where('id', (int)$file_id)->find(); + $uploadPath = WRITEPATH . 'uploads/excel/'; + }else{ + $record = $this->hrFileUploadModel->where('id', (int)$file_id)->find(); + $uploadPath = WRITEPATH . 'uploads/hr_files/'; + } if (!$record) { return $this->failNotFound("File record not found"); } - $uploadPath = WRITEPATH . 'uploads/hr_files/'; - $filePath = $uploadPath . $record[0]['file_name']; + $filePath = $uploadPath . $record[0]['file_name']; if (!file_exists($filePath)) { - // return $this->failNotFound("File not found on server"); - $data['message'] = 'The Physical File Not Found'; - return view('errors/404', $data); + return $this->failNotFound("File not found on server"); } // Force file download return $this->response->download($filePath, null) ->setFileName($record[0]['file_name']); + } catch (\Exception $e) { return $this->failServerError($e->getMessage()); } @@ -4783,13 +4820,21 @@ class EmployeeRestController extends AdminController $data = $this->getDataFromHrFileUploadTable($search_data); $table = "hr_file_upload"; }else{ - $client_data = $this->clientModel->where('id', $search_data['client_id'])->first(); + + if (is_string($search_data['client_id']) && preg_match('/^[a-f0-9]{32}$/i', $search_data['client_id'])) { + $client_data = $this->clientModel->where('MD5(id)', $search_data['client_id'])->first(); + $search_data['client_id'] = $client_data['id']; + } else { + $client_data = $this->clientModel->where('id', $search_data['client_id'])->first(); + } + if($client_data['hr_file_processed_by'] == 1){ - $data = $this->getDataFromHrFileUploadTable($search_data); - $table = "hr_file_upload 2"; - }else{ $data = $this->getDataFromHrFilesTable($search_data); $table = "files"; + }else{ + $data = $this->getDataFromHrFileUploadTable($search_data); + $table = "hr_file_upload 2"; + } } @@ -4800,8 +4845,20 @@ class EmployeeRestController extends AdminController 'table' => $table ]); - } catch (\Exception $e) { - return $this->failServerError($e->getMessage()); + } catch (\Exception $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, + ]; + + return $this->failServerError($th->getMessage()); } } @@ -4835,7 +4892,8 @@ class EmployeeRestController extends AdminController THEN hr_file_upload.status ELSE CONCAT(UCASE(LEFT(f.status, 1)), LCASE(SUBSTRING(f.status, 2))) END AS status, - '1' as file_error_status + '0' as file_error_status, + '' as file_error_status ", false) ->join('clients c', 'c.id = hr_file_upload.client_id AND c.is_active = 1', 'left') ->join('client_branch cb', 'cb.id = hr_file_upload.client_branch_id AND cb.is_active = 1', 'left') @@ -4870,6 +4928,7 @@ class EmployeeRestController extends AdminController } // Execute query + $builder->orderBy('hr_file_upload.id', 'DESC'); $data = $builder->get()->getResultArray(); if(!empty($data)){ @@ -4881,7 +4940,7 @@ class EmployeeRestController extends AdminController public function getDataFromHrFilesTable($search_data) { - $file_download_base = base_url('util/download-file-list/'); + $file_download_base = base_url('downloadFileTableFile/'); $builder = $this->fileModel ->select(" files.id, @@ -4890,7 +4949,7 @@ class EmployeeRestController extends AdminController files.policy_id, cp.policy_no, files.file_name, - files.action, + files.action as file_action, files.created_at, files.created_by, files.updated_at, @@ -4924,7 +4983,11 @@ class EmployeeRestController extends AdminController } if (isset($search_data['client_id']) && !empty($search_data['client_id'])) { - $builder->where("files.client_id", $search_data['client_id']); + if (is_string($search_data['client_id']) && preg_match('/^[a-f0-9]{32}$/i', $search_data['client_id'])) { + $builder->where("MD5(files.client_id)", $search_data['client_id']); + } else { + $builder->where("files.client_id", $search_data['client_id']); + } } if (isset($search_data['file_id']) && !empty($search_data['file_id'])) { @@ -4933,6 +4996,7 @@ class EmployeeRestController extends AdminController // Execute query + $builder->orderBy('files.id', 'DESC'); $data = $builder->get()->getResultArray(); if (!empty($data)) { @@ -5369,6 +5433,195 @@ class EmployeeRestController extends AdminController return $claim_status_data_id; } + public function downloadCdSplitUpFile() + { + try { + + $file_id = $this->request->getGet('id'); + + // Find record + $record = $this->batchFileModel->where('id', $file_id)->first();; + if (!$record) { + $data['message'] = 'File record not found'; + return view('errors/404', $data); + } + + $uploadPath = WRITEPATH . 'uploads/import_excel/'; + $filePath = $uploadPath . $record['file_name']; + + if (!file_exists($filePath)) { + // return $this->failNotFound("File not found on server"); + $data['message'] = 'The Physical File Not Found'; + return view('errors/404', $data); + } + + // Force file download + return $this->response->download($filePath, null)->setFileName($record['file_name']); + } catch (\Exception $e) { + $data['message'] = 'File record not found'; + return view('errors/404', $data); + } + } + + + public function getHrDashboad() + { + // $dashboard_id = $this->request->getGet('dashboard_id') ?? null; + $client_id = $this->request->getPost('client_id') ?? null; + $client_policy_id = $this->request->getPost('client_policy_id') ?? null; + $received_data = $this->request->getJSON(true) ?? null; + // 🔐 Move this to .env in real projects + $METABASE_SECRET_KEY = getenv('METABASE_SECRET_KEY'); + + $payload = [ + 'resource' => [ + // 'dashboard' => 1 + 'dashboard' => 2 + ], + 'params' => (object)['client_policy' => $received_data['client_policy_id']], // MUST be object for Metabase + 'exp' => time() + (10 * 60) // 10 minutes + ]; + + $token = JWT::encode($payload, $METABASE_SECRET_KEY, 'HS256'); + + // // You can either return token only + // return $this->response->setJSON([ + // 'token' => $token, + // 'iframe_url' => "https://your-metabase-domain/embed/dashboard/{$token}#bordered=true&titled=true" + // ]); + // if($this->request->getGet('api') == 1) + // { + return $this->respond([ + 'status' => 'success', + 'message' => 'Form data received successfully!', + 'data' => [ + 'metabaseToken' => $token, + 'metabaseUrl' => 'https://nsights.nhanceindia.in'] + ]); + // } + + return view('meta_dashboard_demo_one', [ + 'metabaseToken' => $token, + 'metabaseUrl' => 'https://nsights.nhanceindia.in', + ]); + } + // get policy files + public function getPolicyAndEndorsementFiles() + { + $cd_ac_pk = $this->request->getGet('cd_ac_pk') ?? null; + + $cdModel = new ClientDepositModel(); + $cd_data = $cdModel->where('id', $cd_ac_pk) + ->where('is_active', 1) + ->where('client_policy_id IS NOT NULL') + ->first(); + + if(empty($cd_data)){ + $this->myLogger->logme('error', 'getPolicyAndEndorsementFiles: No Client Deposit data found for cd_ac_pk=' . $cd_ac_pk); + return $this->respond(['status' => false, 'code' => 404, 'message' => 'No file found', 'data' => []], 200); + } + + $client_policy_data = $this->clientPolicyModel + ->where('id', $cd_data['client_policy_id']) + ->where('is_active', 1) + ->first(); + + if(empty($client_policy_data)){ + $this->myLogger->logme('error', 'getPolicyAndEndorsementFiles: No Client Policy data found for client_policy_id=' . $cd_data['client_policy_id']); + return $this->respond(['status' => false, 'code' => 404, 'message' => 'No file found', 'data' => []], 200); + } + + $policyTransactionModel = new PolicyTransactionModel(); + $builder = $policyTransactionModel + ->where('is_active', 1) + ->where('policy_no', $client_policy_data['policy_no']) + ->where('action_type', $cd_data['event_name']); + + if (!empty($cd_data['endorsement_no']) && $cd_data['event_name'] != 'inception') { + $builder->where('endorsement_no', $cd_data['endorsement_no']); + } + + $policy_transaction_data = $builder->findAll(); + + if(empty($policy_transaction_data)){ + $this->myLogger->logme('error', 'getPolicyAndEndorsementFiles: No Policy Transaction data found for policy_no=' . $client_policy_data['policy_no']); + return $this->respond(['status' => false, 'code' => 404, 'message' => 'No file found', 'data' => []], 200); + } + + $policy_transaction_ids = array_column($policy_transaction_data, 'id'); + + + $ptFilesModel = new PTFileModel(); + $pt_files_data = $ptFilesModel->where('is_active', 1)->whereIn('pt_id', $policy_transaction_ids)->findAll(); + + if(empty($pt_files_data)){ + $this->myLogger->logme('error', 'getPolicyAndEndorsementFiles: No PT Files data found for pt_ids=' . implode(',', $policy_transaction_ids)); + return $this->respond(['status' => false, 'code' => 404, 'message' => 'No file found', 'data' => []], 200); + } + + + return $this->respond(['status' => true, 'code' => 200, 'message' => 'Files found', 'data' => $pt_files_data], 200); + + } + + // download policy file + public function downloadPolicyFiles() + { + $pt_file_id = $this->request->getGet('file_id') ?? null; + + if(empty($pt_file_id)){ + return $this->respond(['status' => false, 'code' => 404, 'message' => 'File ID is required'], 200); + } + + $uploadFilePath = WRITEPATH . 'uploads/client_kyc_documents'; + + $ptFilesModel = new PTFileModel(); + $pt_files_data = $ptFilesModel->where('is_active', 1)->where('id', $pt_file_id)->first(); + + if(empty($pt_files_data)){ + return $this->respond(['status' => false, 'code' => 404, 'message' => 'The Physical File Not Found in server'], 200); + } + + $filePath = $uploadFilePath . '/' . $pt_files_data['file_name']; + + if (!file_exists($filePath)) { + return $this->respond(['status' => false, 'code' => 404, 'message' => 'The Physical File Not Found in server'], 200); + } + + // Force file download + return $this->response->download($filePath, null)->setFileName($pt_files_data['file_name']); + } + + public function bulkEcardDownloadAsZip() + { + $received_data = $this->request->getJSON(true) ?? null; + $this->myLogger->logme('error', 'bulkEcardDownloadAsZip: Received payload = ' . json_encode($received_data ?? [])); + + if(empty($received_data['client_policy_id']) && empty($received_data['emp_policy_ids'])){ + return $this->respond(['status' => false, 'code' => 404, 'message' => 'client_policy_id or employee_policy_ids is required'], 200); + } + + if(empty($received_data['hr_id'])){ + return $this->respond(['status' => false, 'code' => 404, 'message' => 'hr_id is required'], 200); + } + + $employee_data = $this->employeePolicyModel->getEmployeeDataWithPolicyUsingClientPolicyIdOrEmployeePolicyIds($received_data); + + if(empty($employee_data)){ + return $this->respond(['status' => false, 'code' => 404, 'message' => 'No employee data found for the policy'], 200); + } + + $received_data['folder_name'] = 'bulk_ecards_' . $employee_data[0]['policy_no'] . '_' . date('Y-m-d_H-i-s'); + + // Dispatch background job to process the bulk e-card download + $r = Jobs::addJob(['job_name' => 'bulkEcardDownloadAsZipFromS3', 'payload' => $received_data]); + $this->myLogger->logme('error', 'bulkEcardDownloadAsZip: Job dispatched with result = ' . json_encode($r ?? [])); + + return $this->respond(['status' => true, 'code' => 200, 'message' => 'Bulk E-card download process started. Link share your mail'], 200); + + } + + } diff --git a/app/Controllers/EmployeeServiceController.php b/app/Controllers/EmployeeServiceController.php index 78bf3162..84761c68 100755 --- a/app/Controllers/EmployeeServiceController.php +++ b/app/Controllers/EmployeeServiceController.php @@ -866,6 +866,14 @@ class EmployeeServiceController extends AdminController // get policy and rack details $policy_details = $this->clientPolicyModel->getPolicyDetails($file['client_id'],$file['policy_id']); + + if(empty($policy_details)){ + $message = "Policy configuration is incomplete. Cannot proceed."; + $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); + } + $policy_terms = json_decode($policy_details[0]->policy_terms); $policy_terms = (array) $policy_terms;// convert obj to array $default_age_ratio = isset($policy_terms['age_ratio']) ? json_decode(json_encode($policy_terms['age_ratio']),true) : []; @@ -876,6 +884,13 @@ class EmployeeServiceController extends AdminController $slab_details = $this->policiesModel->getPolicySlabRatesForEmpOnboard($file['policy_id'],$file['client_id']); // dd($slab_details); + if(empty($slab_details) || (isset($slab_details['slab_rates']) && empty($slab_details['slab_rates']))){ + $message = "Policy configuration is incomplete. Cannot proceed."; + $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); + } + //remove header unset($excel_data[0]); $relationship = $this->general_relationships; diff --git a/app/Controllers/JobWorker.php b/app/Controllers/JobWorker.php index f2020755..d6ae550f 100755 --- a/app/Controllers/JobWorker.php +++ b/app/Controllers/JobWorker.php @@ -213,6 +213,14 @@ class JobWorker extends AdminController 'bulkGenerateEcardAndStoreinS3' => [ 'type' => 'CC', // Handler Category 'handler' => 'App\Controllers\EmployeeController', + ], + 'bulkEcardDownloadAsZipFromS3' => [ + 'type' => 'CC', // Handler Category + 'handler' => 'App\Controllers\EmployeeController', + ], + 'getEmployeeEcardFromTmpFolderAndZipToS3' => [ + 'type' => 'CC', // Handler Category + 'handler' => 'App\Controllers\EmployeeController', ] ]; diff --git a/app/Controllers/MasterController.php b/app/Controllers/MasterController.php index dc6538d4..074b36bc 100755 --- a/app/Controllers/MasterController.php +++ b/app/Controllers/MasterController.php @@ -497,6 +497,9 @@ class MasterController extends AdminController { $this->myLogger->logme('error','Edit Insurer general info function called'); + $postData = $this->request->getPost(); + $logoFile = $this->request->getFile('insurer_logo'); + $rules = [ 'name' => [ 'rules' => 'required', @@ -513,22 +516,30 @@ class MasterController extends AdminController ] ], 'insurer_logo' => [ - 'rules' => 'if_exist|is_image[insurer_logo]|max_size[insurer_logo,200]|ext_in[insurer_logo,jpg,jpeg,png]', + 'rules' => 'permit_empty|is_image[insurer_logo]|max_size[insurer_logo,200]|ext_in[insurer_logo,jpg,jpeg,png]', 'errors' => [ 'is_image' => 'The uploaded file must be an image', 'max_size' => 'File size should not exceed 200 KB', - 'ext_in' => 'Allowed file types: jpg, jpeg, png', + 'ext_in' => 'Only JPG, JPEG, and PNG files are allowed.', ] ], ]; - if (!$this->validate($rules)) { - return $this->response->setStatusCode(400)->setJSON([ - 'status' => false, - 'message' => 'Input validation failed', - 'code' => 400, - 'errors' => $this->validator->getErrors() - ]); + if (!$this->validateData($postData, $rules)) { + $errors = $this->validator->getErrors(); + + $mainMessage = 'Input validation failed'; + + if (isset($errors['insurer_logo']) && (strpos($errors['insurer_logo'], 'Security') !== false || strpos($errors['insurer_logo'], 'Forbidden') !== false)) { + $mainMessage = 'File upload rejected: Security policy violation.'; + } + + return $this->response->setStatusCode(400)->setJSON([ + 'status' => false, + 'message' => $mainMessage, // This will change based on the error + 'code' => 400, + 'errors' => $this->validator->getErrors() + ]); } $uploadFilePath = ROOTPATH . 'public/uploads/logo/'; @@ -2967,6 +2978,7 @@ class MasterController extends AdminController 'files' => WRITEPATH . 'uploads/commission/files', 'rules' => WRITEPATH . 'uploads/commission/rules', 'claim_sample_forms' => ROOTPATH . 'public/claim_sample_forms/', + 'tmp' => ROOTPATH . 'public/tmp/', 'bds_dump_excel' => WRITEPATH . 'uploads/bds_dump_excel/', 'claims_mis' => WRITEPATH . 'uploads/claims_mis/', ]; diff --git a/app/Controllers/NotificationController.php b/app/Controllers/NotificationController.php index b0e5b4cf..8014f0c5 100755 --- a/app/Controllers/NotificationController.php +++ b/app/Controllers/NotificationController.php @@ -94,7 +94,8 @@ class NotificationController extends AdminController 'member_ecard_mail_btn', 'member_review_and_summary_mail_btn', 'account_maneger_summary_mail_btn', - 'client_hr_summary_mail_btn' + 'client_hr_summary_mail_btn', + 'hr_cd_insufficient_balance_mail_btn', ]; $data = []; $emptyTemplate = []; diff --git a/app/Controllers/PolicyTransactionController.php b/app/Controllers/PolicyTransactionController.php index dc57d03f..592e7405 100644 --- a/app/Controllers/PolicyTransactionController.php +++ b/app/Controllers/PolicyTransactionController.php @@ -2273,6 +2273,9 @@ // print_r($data); // die; + $file_data = $this->request->getFiles() ?? null; + $data['file_data'] = $file_data ?? null; + if (!isset($data['policy_with_corr'])) { $data['policy_with_corr'] = 0; } elseif ($data['policy_with_corr']) { @@ -2416,6 +2419,11 @@ $this->handleCompletedStatus($data, $insert); $this->insertOrUpdateCoShareDetails($data, $insert); + // policy file upload + if(isset($data['doc_name']) && isset($data['file_data']) && !empty($data['doc_name']) && !empty($data['file_data'])){ + $this->uploadFile($data['doc_name'], $data['file_data'], $insert); + } + return $this->respond(['status' => true, 'message' => 'Endorsement transaction created successfully'], 200); } @@ -2688,6 +2696,20 @@ // dd(db_connect()->getLastQuery() ,$pt_bp_amt); $data['base_cd_amount'] = $pt_bp_amt['amount'] ?? null; + $ptFileQuery = $this->PTFileModel + ->join('policy_transaction', 'pt_files.pt_id = policy_transaction.id') + ->where('pt_files.pt_id', $id) + ->where('pt_files.is_active', 1); + + if (!in_array(get_role_id(), [1, 5]) && empty(array_intersect(user_team(), [MANAGEMENT_TEAM_ID, FINANCE_TEAM_ID, BUSINESS_TEAM_ID]))) { + + if (get_role_id() == 4 && in_array(POS_TEAM_ID, user_team())) { + $ptFileQuery->where('pt_files.created_by', get_session_userid()); + } + } + + $data['pt_files'] = $ptFileQuery->findAll(); + if ($data) { return $this->respond(['status' => true, 'data' => $data, 'pt_id' => $pt_id], 200); } else { diff --git a/app/Controllers/RestAuthenticationController.php b/app/Controllers/RestAuthenticationController.php index b2d54fbb..c743c82f 100755 --- a/app/Controllers/RestAuthenticationController.php +++ b/app/Controllers/RestAuthenticationController.php @@ -776,7 +776,7 @@ class RestAuthenticationController extends AdminController }else { - return $this->respond(['status' => 'failed','code' => 404,'data' => "" , 'message' => 'User not found' ],200); + return $this->respond(['status' => 'failed','code' => 404,'data' => "" , 'message' => 'Invalid OTP' ],200); } @@ -786,7 +786,7 @@ class RestAuthenticationController extends AdminController } else { - return $this->respond(['status' => 'failed','code' => 404,'data' => "" , 'message' => 'User not found' ],200); + return $this->respond(['status' => 'failed','code' => 404,'data' => "" , 'message' => 'Invalid OTP' ],200); } } catch (\Exception $e) { return $this->respond(['status' => 'failed','code' => 500,'data' => $e->getMessage()],500); diff --git a/app/Controllers/TestingController.php b/app/Controllers/TestingController.php index 75d4d578..7cfc5ab2 100644 --- a/app/Controllers/TestingController.php +++ b/app/Controllers/TestingController.php @@ -17,6 +17,8 @@ use PhpOffice\PhpSpreadsheet\Style\Alignment; use PhpOffice\PhpSpreadsheet\Style\Fill; use PhpOffice\PhpSpreadsheet\Style\Border; +use Firebase\JWT\JWT; + class TestingController extends BaseController { use ResponseTrait; @@ -983,5 +985,46 @@ class TestingController extends BaseController } + public function metaDashboardDemo() + { + + // 🔐 Move this to .env in real projects + $METABASE_SECRET_KEY = getenv('METABASE_SECRET_KEY'); + $policy_id = $this->request->getGet('client_policy'); + $policy_id = $policy_id ? $policy_id : 4687; + $payload = [ + 'resource' => [ + // 'dashboard' => 1 + 'dashboard' => 2 + ], + 'params' => (object)['client_policy' => $policy_id], // MUST be object for Metabase + 'exp' => time() + (10 * 60) // 10 minutes + ]; + // dd($payload); + $token = JWT::encode($payload, $METABASE_SECRET_KEY, 'HS256'); + + // // You can either return token only + // return $this->response->setJSON([ + // 'token' => $token, + // 'iframe_url' => "https://your-metabase-domain/embed/dashboard/{$token}#bordered=true&titled=true" + // ]); + if($this->request->getGet('api') == 1) + { + return $this->respond([ + 'status' => 'success', + 'message' => 'Form data received successfully!', + 'data' => [ + 'metabaseToken' => $token, + 'metabaseUrl' => 'https://nsights.nhanceindia.in'] + ]); + } + + return view('meta_dashboard_demo_one', [ + 'metabaseToken' => $token, + 'metabaseUrl' => 'https://nsights.nhanceindia.in', + ]); + } + + } diff --git a/app/Controllers/TicketController.php b/app/Controllers/TicketController.php index 1dbe0636..abb02e17 100644 --- a/app/Controllers/TicketController.php +++ b/app/Controllers/TicketController.php @@ -1151,9 +1151,9 @@ class TicketController extends BaseController 'errors' => ['required' => 'Employee Email is required'] ], - 'client_name' => [ + 'client_id' => [ 'rules' => 'required', - 'errors' => ['required' => 'Client Name is required'] + 'errors' => ['required' => 'Client ID is required'] ], 'insurer_id' => [ @@ -1335,9 +1335,9 @@ class TicketController extends BaseController 'errors' => ['required' => 'Employee Email is required'] ], - 'client_name' => [ + 'client_id' => [ 'rules' => 'required', - 'errors' => ['required' => 'Client Name is required'] + 'errors' => ['required' => 'Client ID is required'] ], 'insurer_id' => [ diff --git a/app/Controllers/TicketServiceController.php b/app/Controllers/TicketServiceController.php index 14c1b19a..602f0708 100644 --- a/app/Controllers/TicketServiceController.php +++ b/app/Controllers/TicketServiceController.php @@ -9,6 +9,11 @@ use PhpOffice\PhpSpreadsheet\Cell\Coordinate; use Kint\Kint; use App\Libraries\TpaClaimsImportFactory; use App\Libraries\TPAClaimsImportServices\FhplClaimImportService; +use App\Libraries\TPAClaimsImportServices\MediAssistClaimImportService; +use App\Libraries\TPAClaimsImportServices\AbhiClaimImportService; +use App\Libraries\TPAClaimsImportServices\RcareClaimImportService; +use App\Libraries\TPAClaimsImportServices\VidalClaimImportService; +use App\Libraries\TPAClaimsImportServices\IciciClaimImportService; use App\Libraries\TPAClaimsImportServices\BaseTpaClaimImportService; use App\Models\ClaimDumpFileModel; @@ -1858,23 +1863,21 @@ class TicketServiceController extends BaseController public function tpaClaimDumpImporter($params) { - try { + $file_id = $params['file_id'] ?? null; // Move outside try to ensure catch can see it - $file_id = $params['file_id'] ?? null; - $file_path = WRITEPATH . 'uploads/claim_dump_excel/'; + try { + $file_path = WRITEPATH . 'uploads' . DIRECTORY_SEPARATOR . 'claim_dump_excel' . DIRECTORY_SEPARATOR; if (!$file_id) { return ['status' => false, 'message' => 'File ID is missing']; } - $fileData = $this->claimDumpFileModel->where('id', $file_id)->first(); - + $fileData = $this->claimDumpFileModel->find((int)$file_id); if (!$fileData) { return ['status' => false, 'message' => 'Invalid file ID. No file data found']; } $file_full_path = $file_path . $fileData['file_name']; - if (!is_file($file_full_path)) { return ['status' => false, 'message' => 'Claim dump file not found']; } @@ -1882,106 +1885,97 @@ class TicketServiceController extends BaseController $handler = TpaClaimsImportFactory::make($fileData['tpa_id'] ?? 0); $result = $handler->runTpaClaimDumpInsert($file_full_path, $file_id); - // ---------- Prepare update data ---------- - $data = []; - if (!empty($result['status']) && $result['status'] === true) { - $data['status'] = 'success'; - $data['reason'] = null; + Jobs::addJob(['job_name' => 'tpaClaimDumpToTicketMasterImporters', 'payload' => ['file_id' => $file_id]]); } else { - $data['status'] = 'failed'; - - $errorMessage = $result['message'] ?? 'Unknown import error'; - - $reason = [ - 'error_summary' => array_count_values([5]), - 'error_data' => $errorMessage - ]; - - $data['reason'] = json_encode($reason, JSON_UNESCAPED_UNICODE); - } - - // dd($data); - // ---------- Update DB ---------- - $sql = "UPDATE claim_dump_files SET status = ?, reason = ? WHERE id = ?"; - - $updated = db_connect()->query( - $sql, - [ - $data['status'] ?? null, - $data['reason'] ?? null, - $file_id - ] - ); - - if (!$updated) { - $this->myLogger->logme('error', 'Claim dump file update failed for file_id: ' . $file_id); - } - - dd(db_connect()->getLastQuery()->getQuery()); - - if(!empty($result['status']) && $result['status'] === true){ - $r = Jobs::addJob(['job_name' => 'tpaClaimDumpToTicketMasterImporters', 'payload' => ['file_id' => $file_id]]); + // FORCE FAIL LOGIC + $this->markAsFailed($file_id, $result['message'] ?? 'System error contact admin', $fileData['created_by'] ?? null); } return $result; - } catch (\Throwable $th) { + $this->myLogger->logme("error", 'TPA_CLAIM_IMPORTER_JOB : ' . $th->getMessage()); - $this->myLogger->logme( - "error", - 'TPA_CLAIM_IMPORTER_JOB : ' . - $th->getMessage() . ' | Line: ' . $th->getLine() - ); + if (!empty($file_id)) { + $this->markAsFailed($file_id, 'System error contact admin'); + } return [ 'status' => false, 'message' => 'TPA Claim dump import failed', - 'error_data' => [ - 'message' => $th->getMessage(), - 'file' => $th->getFile(), - 'line' => $th->getLine(), - 'trace' => $th->getTraceAsString() - ] + 'error_data' => $th->getMessage() ]; } } + private function markAsFailed($file_id, $message, $user_id = null) + { + $reason = json_encode([ + 'error_summary' => [5 => 1], + 'error_data' => $message + ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + + $data = [ + 'status' => 'failed', + 'reason' => $reason, + 'updated_by' => $user_id + ]; + + // Using the direct update(id, data) method is often more reliable inside try/catch + return $this->claimDumpFileModel->update($file_id, $data); + } + public function tpaClaimDumpToTicketMasterImporters($params) { - try { + $file_id = $params['file_id'] ?? null; + $fileData = null; + + try { + if (!$file_id) { + return ['status' => false, 'message' => 'File ID is missing']; + } - $file_id = $params['file_id'] ?? null; $fileData = $this->claimDumpFileModel->where('id', $file_id)->first(); if (!$fileData) { - return ['status' => false, 'message' => 'Invalid file ID No file data found to import']; + return ['status' => false, 'message' => 'Invalid file ID. No file data found to import']; } $handler = TpaClaimsImportFactory::make($fileData['tpa_id'] ?? 0); $result = $handler->runTicketMasterInsert($params); + if (!empty($result['status']) && $result['status'] === true) { + // Success: Update the status to success + $this->claimDumpFileModel->update($file_id, [ + 'status' => 'success', + 'reason' => null + ]); + } else { + // Logic failure: The runTicketMasterInsert returned status false + $this->markAsFailed( + $file_id, + $result['message'] ?? 'System error contact admin', + $fileData['created_by'] ?? null + ); + } + return $result; - } catch (\Throwable $th) { + // Log the full error + $this->myLogger->logme("error", 'TICKET_MASTER_CLAIM_IMPORTER_JOB :' . $th->getMessage() . ' at line ' . $th->getLine()); - $this->myLogger->logme("error", 'TICKET_MASTER_CLAIM_IMPORTER_JOB :' .($th->getMessage() . ' --- ' . $th->getLine() . '----' . $th->getTraceAsString())); - - $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, - ]; + // CRITICAL: Even if the code crashes, try to mark the file as failed + if ($file_id) { + $this->markAsFailed($file_id, 'Fatal Crash: ' . $th->getMessage(), $fileData['created_by'] ?? null); + } return [ 'status' => false, 'message' => $th->getMessage(), - 'error_data' => json_encode($errorData, JSON_PRETTY_PRINT) + 'error_data' => [ + 'line' => $th->getLine(), + 'file' => $th->getFile() + ] ]; } } diff --git a/app/Controllers/UserController.php b/app/Controllers/UserController.php index daaadb9f..d2a32ac1 100755 --- a/app/Controllers/UserController.php +++ b/app/Controllers/UserController.php @@ -114,13 +114,11 @@ class UserController extends AdminController // Employee Code // ====================== 'emp_code' => [ - 'rules' => 'required|alpha_numeric|min_length[3]|max_length[20]|is_unique[user_profiles.emp_code,id,{PrimaryKey}]', + 'rules' => 'required|min_length[3]|max_length[15]', 'errors' => [ 'required' => 'Employee Code is required', - 'alpha_numeric' => 'Employee Code must be alphanumeric', 'min_length' => 'Employee Code must be at least 3 characters', - 'max_length' => 'Employee Code cannot exceed 20 characters', - 'is_unique' => 'Employee Code already exists' + 'max_length' => 'Employee Code cannot exceed 15 characters', ] ], @@ -141,11 +139,10 @@ class UserController extends AdminController // Email // ====================== 'email' => [ - 'rules' => 'required|valid_email|is_unique[user_profiles.email,id,{PrimaryKey}]', + 'rules' => 'required|valid_email', 'errors' => [ 'required' => 'Email is required', 'valid_email' => 'Please enter a valid email address', - 'is_unique' => 'Email already exists' ] ], @@ -153,11 +150,10 @@ class UserController extends AdminController // Mobile // ====================== 'mobile' => [ - 'rules' => 'required|regex_match[/^[6-9][0-9]{9}$/]|is_unique[user_profiles.mobile,id,{PrimaryKey}]', + 'rules' => 'required|regex_match[/^[6-9][0-9]{9}$/]', 'errors' => [ 'required' => 'Mobile number is required', 'regex_match' => 'Enter a valid 10-digit mobile number starting with 6, 7, 8, or 9', - 'is_unique' => 'Mobile number already exists' ] ], @@ -302,13 +298,11 @@ class UserController extends AdminController // Employee Code // ====================== 'emp_code' => [ - 'rules' => 'required|alpha_numeric|min_length[3]|max_length[20]|is_unique[user_profiles.emp_code,id,{PrimaryKey}]', + 'rules' => 'required|min_length[3]|max_length[15]', 'errors' => [ 'required' => 'Employee Code is required', - 'alpha_numeric' => 'Employee Code must be alphanumeric', 'min_length' => 'Employee Code must be at least 3 characters', - 'max_length' => 'Employee Code cannot exceed 20 characters', - 'is_unique' => 'Employee Code already exists' + 'max_length' => 'Employee Code cannot exceed 15 characters', ] ], @@ -329,11 +323,10 @@ class UserController extends AdminController // Email // ====================== 'email' => [ - 'rules' => 'required|valid_email|is_unique[user_profiles.email,id,{PrimaryKey}]', + 'rules' => 'required|valid_email', 'errors' => [ 'required' => 'Email is required', 'valid_email' => 'Please enter a valid email address', - 'is_unique' => 'Email already exists' ] ], @@ -341,11 +334,10 @@ class UserController extends AdminController // Mobile // ====================== 'mobile' => [ - 'rules' => 'required|regex_match[/^[6-9][0-9]{9}$/]|is_unique[user_profiles.mobile,id,{PrimaryKey}]', + 'rules' => 'required|regex_match[/^[6-9][0-9]{9}$/]', 'errors' => [ 'required' => 'Mobile number is required', 'regex_match' => 'Enter a valid 10-digit mobile number starting with 6, 7, 8, or 9', - 'is_unique' => 'Mobile number already exists' ] ], diff --git a/app/Filters/GlobalPostFileUploadGuard.php b/app/Filters/GlobalPostFileUploadGuard.php index 4cc82ba8..76117240 100644 --- a/app/Filters/GlobalPostFileUploadGuard.php +++ b/app/Filters/GlobalPostFileUploadGuard.php @@ -39,7 +39,7 @@ class GlobalPostFileUploadGuard implements FilterInterface ]; protected array $blockedExtensions = [ - 'php', 'phtml', 'pht', 'phar', 'php3', 'php4', 'php5', 'php7', 'php8', 'phps', + 'php', 'phtml', 'html', 'pht', 'phar', 'php3', 'php4', 'php5', 'php7', 'php8', 'phps', 'cgi', 'fcgi', 'pl', 'py', 'rb', 'lua', 'tcl', 'go', 'rs', 'jar', 'class', 'exe', 'dll', 'com', 'bat', 'cmd', 'msi', 'vbs', 'ps1', 'scr', 'sh', 'bash', 'zsh', 'apk', 'app', 'deb', 'rpm', 'bin', 'run', @@ -100,7 +100,7 @@ class GlobalPostFileUploadGuard implements FilterInterface } // --- 2. Double Extension Attack Check --- - if (preg_match('/\.(php|phtml|phar|exe|sh|bat|cmd|js|jsp|asp|aspx|py|pl)\./i', $originalName)) { + if (preg_match('/\.(php|html|phtml|phar|exe|sh|bat|cmd|js|jsp|asp|aspx|py|pl)\./i', $originalName)) { $this->block("Double extension attack", $clientIp, $uri, $inputName, $originalName, $mime, $extension, $size); } diff --git a/app/Helpers/DepositHelper.php b/app/Helpers/DepositHelper.php index 495797f3..cc8fbde0 100755 --- a/app/Helpers/DepositHelper.php +++ b/app/Helpers/DepositHelper.php @@ -67,7 +67,8 @@ class DepositHelper 'balance' => $newBalance, // Include the new balance in the data array 'cd_ac_pk'=> isset($data['cd_ac_pk'])?$data['cd_ac_pk']:null, 'record_date' => $data['record_date'] ?? null, - 'policy_transaction_id' => $data['pt_id'] ?? null + 'policy_transaction_id' => $data['pt_id'] ?? null, + 'file_id' => $data['file_id'] ?? null, ]; // Insert data and get the insert ID diff --git a/app/Helpers/utility_helper.php b/app/Helpers/utility_helper.php index efec7f1d..178ec18a 100755 --- a/app/Helpers/utility_helper.php +++ b/app/Helpers/utility_helper.php @@ -947,21 +947,37 @@ if (!function_exists('validateExcelFile')) { function validateExcelFile($file) { - $allowed = [ + // 1. Check if the file was uploaded without errors + if (! $file->isValid() || $file->hasMoved()) { + return false; + } + + // 2. Size check (16MB) + if ($file->getSizeByUnit('mb') > 16) { + return false; + } + + // 3. Define allowed types + $allowedMimes = [ 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - 'application/vnd.oasis.opendocument.spreadsheet' + 'application/vnd.oasis.opendocument.spreadsheet', + 'application/zip', + 'application/octet-stream' ]; - // if ($file->getError() !== UPLOAD_ERR_OK) return 'Upload error'; - // if ($file->getSize() > (16 * 1024 * 1024)) return 'File too large'; - // if (!in_array($file->getClientMimeType(), $allowed, true)) return 'Invalid file type'; - - if ($file->getError() !== UPLOAD_ERR_OK) return false; - if ($file->getSize() > (16 * 1024 * 1024)) return false; - if (!in_array($file->getClientMimeType(), $allowed, true)) return false; + $allowedExtensions = ['xls', 'xlsx', 'ods', 'xlsm']; - return true; + // Get the actual values using CI4 methods + $mime = $file->getClientMimeType(); + $extension = $file->getExtension(); // This is the CI4 method + + // 4. Validate + if (in_array($mime, $allowedMimes) || in_array($extension, $allowedExtensions)) { + return true; + } + + return false; } } @@ -1108,6 +1124,7 @@ if (!function_exists('get_cd_balance')) { return [ 'has_cd_balance' => $session->has('cd_balance'), + 'cd_balance' => $session->get('cd_balance') ?? null, 'hr_data' => $session->get('hr_data') ?? [], 'cd_balance_info' => $session->get('cd_balance_info') ?? [], ]; diff --git a/app/Libraries/TPAClaimsImportServices/AbhiClaimImportService.php b/app/Libraries/TPAClaimsImportServices/AbhiClaimImportService.php index 21818613..3ee5c066 100644 --- a/app/Libraries/TPAClaimsImportServices/AbhiClaimImportService.php +++ b/app/Libraries/TPAClaimsImportServices/AbhiClaimImportService.php @@ -86,10 +86,6 @@ class AbhiClaimImportService extends BaseTpaClaimImportService // Employee / Member details 'member_code' => 'emp_code', - 'relation' => 'relationship', - - // Policy / Claim identifiers - 'policy_number' => 'policy_no', 'abhi_claim_no' => 'claim_number', // Dates @@ -114,6 +110,8 @@ class AbhiClaimImportService extends BaseTpaClaimImportService // Misc 'diagnosis' => 'claim_description', 'healthcard_id' => 'tpa_no', + 'claim_type' => 'tpa_claim_type', + ]; protected $statusMapping = [ @@ -174,9 +172,7 @@ class AbhiClaimImportService extends BaseTpaClaimImportService } $ticketMasterModel = new TicketMasterModel(); - $ticketMasterModel->insertBatch($data); - - return true; + return $ticketMasterModel->insertBatch($data); } @@ -187,9 +183,7 @@ class AbhiClaimImportService extends BaseTpaClaimImportService } $builder = $this->db->table('claims_dump_abhi'); - $builder->insertBatch($data); - - return true; + return $builder->updateBatch($data, 'id'); } @@ -200,9 +194,7 @@ class AbhiClaimImportService extends BaseTpaClaimImportService } $builder = $this->db->table('claims_dump_abhi'); - $builder->insertBatch($data); - - return true; + return $builder->updateBatch($data, 'id'); } @@ -307,7 +299,7 @@ class AbhiClaimImportService extends BaseTpaClaimImportService if ($isduplicate) { $reason = "This claim already exists in our system."; - $rejecetd_reason[$row['id']] = ["ticket_master_insert_reject_reason" => $reason]; + $rejecetd_reason[] = ["id" => $row['id'], "master_reject_reason" => $reason]; continue; } @@ -326,23 +318,15 @@ class AbhiClaimImportService extends BaseTpaClaimImportService if (!empty($employee_data)) { $item['emp_id'] = $employee_data['id'] ?? null; $item['emp_name'] = $employee_data['name'] ?? null; + $item['emp_code'] = $employee_data['emp_code'] ?? null; $item['emp_mail'] = $employee_data['email_corporate'] ?? null; $item['emp_mobile'] = $employee_data['mobile'] ?? null; $item['insured_emp_id'] = $employee_data['insured_emp_id'] ?? null; $item['insured_name'] = $employee_data['insured_name'] ?? null; } else { - $reason = sprintf( - 'The policy number "%s" does not exist in our system. ' . - 'Details - Client ID: %s, Client Policy ID: %s, Employee Number: %s, Relationship: %s', - $row['insurer_policy_number'], - $file_data['client_id'], - $file_data['client_policy_id'], - $row['employee_number'], - $item['relationship'] - ); - - $rejecetd_reason[$row['id']] = ["ticket_master_insert_reject_reason" => $reason]; + $reason = 'This employee not exist in our system.'; + $rejecetd_reason[] = ["id" => $row['id'], "master_reject_reason" => $reason]; continue; } @@ -440,41 +424,31 @@ class AbhiClaimImportService extends BaseTpaClaimImportService return null; } - $relation = strtolower($relation); + // trim removes whitespace, strtolower handles case sensitivity + $relation = strtolower(trim($relation)); - if (str_contains($relation, 'self')) { - return 'self'; + // Mapping specific keywords to standardized outputs + // ORDER MATTERS: Specific phrases (in-law) must come before general ones (father) + $map = [ + 'father-in-law' => ['father in law', 'father-in-law', 'fil'], + 'mother-in-law' => ['mother in law', 'mother-in-law', 'mil'], + 'father' => ['father', 'papa', 'dad'], + 'mother' => ['mother', 'mom', 'mummy'], + 'spouse' => ['spouse', 'wife', 'husband', 'hubby'], + 'daughter' => ['daughter', 'daug'], + 'son' => ['son'], + 'self' => ['self', 'employee', 'main'], + ]; + + foreach ($map as $standard => $keywords) { + foreach ($keywords as $keyword) { + if (str_contains($relation, $keyword)) { + return $standard; + } + } } - if (str_contains($relation, 'spouse') || str_contains($relation, 'wife') || str_contains($relation, 'husband')) { - return 'spouse'; - } - - if (str_contains($relation, 'daughter')) { - return 'daughter'; - } - - if (str_contains($relation, 'son')) { - return 'son'; - } - - if (str_contains($relation, 'father in law') || str_contains($relation, 'father-in-law')) { - return 'father-in-law'; - } - - if (str_contains($relation, 'mother in law') || str_contains($relation, 'mother-in-law')) { - return 'mother-in-law'; - } - - if (str_contains($relation, 'father')) { - return 'father'; - } - - if (str_contains($relation, 'mother')) { - return 'mother'; - } - - return null; // unmatched case + return null; } } diff --git a/app/Libraries/TPAClaimsImportServices/BaseTpaClaimImportService.php b/app/Libraries/TPAClaimsImportServices/BaseTpaClaimImportService.php index 1485dee2..f2e94cfa 100644 --- a/app/Libraries/TPAClaimsImportServices/BaseTpaClaimImportService.php +++ b/app/Libraries/TPAClaimsImportServices/BaseTpaClaimImportService.php @@ -27,79 +27,49 @@ abstract class BaseTpaClaimImportService */ public function runTpaClaimDumpInsert(string $filePath, int $fileId): array { - $this->db->transStart(); + // 1. Start Transaction + $this->db->transBegin(); - $fileData = $this->claimDumpFileModel->where('id', $fileId)->first(); + try { + $fileData = $this->claimDumpFileModel->where('id', $fileId)->first(); - 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'); - // $AL = $this->readExcelBySheetName($filePath, 'AL'); - // $rows = array_merge($CL, $AL); - } else { - $rows = $this->readExcel($filePath); - } - // dd($rows); + // 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)) { - return ['status' => false, 'message' => 'Excel file contains no data or wrong file upload']; - } + 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); - // dd($tpaInsertData); + $tpaInsertData = $this->mapTPAData($rows, $fileId); - if (empty($tpaInsertData)) { - return ['status' => false, 'message' => 'These records already exist in the system.']; - } + if (empty($tpaInsertData)) { + $this->db->transRollback(); // ROLLBACK BEFORE RETURN + return ['status' => false, 'message' => 'These records already exist in the system.']; + } - if (env('FHPL_PRIMARY_KEY_CONSTANT') == $fileData['tpa_id']) { - $ClaimsDumpFhplModel = $this->db->table('claims_dump_fhpl'); - $return_res = $ClaimsDumpFhplModel->insertBatch($tpaInsertData); - } else if (env('R_CARE_PRIMARY_KEY_CONSTANT') == $fileData['tpa_id']) { - $ClaimsDumpIciciModel = $this->db->table('claims_dump_reliance'); - $return_res = $ClaimsDumpIciciModel->insertBatch($tpaInsertData); - } else if (env('ICICI_PRIMARY_KEY_CONSTANT') == $fileData['tpa_id']) { - $ClaimsDumpIciciModel = $this->db->table('claims_dump_icici'); - $return_res = $ClaimsDumpIciciModel->insertBatch($tpaInsertData); - } else if (env('ABHI_PRIMARY_KEY_CONSTANT') == $fileData['tpa_id']) { - // $ClaimsDumpAbhiModel = $this->db->table('claims_dump_abhi'); - // $return_res = $ClaimsDumpAbhiModel->insertBatch($tpaInsertData); $return_res = $this->bulkInsertTPATable($tpaInsertData); - } else if (env('VIDAL_PRIMARY_KEY_CONSTANT') == $fileData['tpa_id']) { - $ClaimsDumpVidalModel = $this->db->table('claims_dump_vidal'); - $return_res = $ClaimsDumpVidalModel->insertBatch($tpaInsertData); - } else if (env('MEDI_ASSIST_PRIMARY_KEY_CONSTANT') == $fileData['tpa_id']) { - $ClaimsDumpMediAssistModel = $this->db->table('claims_dump_medi_assist'); - $return_res = $ClaimsDumpMediAssistModel->insertBatch($tpaInsertData); - } else{ + 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()]; } - - // $return_res = $this->bulkInsertTPATable($tpaInsertData); - - if (!$return_res) { - return ['status' => false, 'message' => 'TPA Import bulk insert failed']; - } - - $this->db->transComplete(); - - if ($this->db->transStatus() === false) { - - $error = $this->db->error(); - - $error_data = [ - 'message' => $error['message'] ?: 'Unknown DB error', - 'code' => $error['code'] ?? null, - 'last_query' => (string) $this->db->getLastQuery() - ]; - - // dd($error_data); - // unset($error_data['last_query']); - return ['status' => false, 'message' => 'TPA Import transaction failed', 'error_data' => $error_data]; - } - - return ['status' => true, 'message' => 'File uploaded successfully', 'record_count' => count($tpaInsertData ?? [])]; } /** @@ -107,34 +77,65 @@ abstract class BaseTpaClaimImportService */ public function runTicketMasterInsert(array $params): array { - $this->db->transStart(); + // 1. Start manual transaction + $this->db->transBegin(); - $file_id = $params['file_id']; + try { + $file_id = $params['file_id']; + $ticketMasterData = $this->mapClaimMasterData($file_id); - $ticketMasterData = $this->mapClaimMasterData($file_id); + // Check if mapping failed + if (!$ticketMasterData['status']) { + $this->db->transRollback(); // ALWAYS rollback before early return + return $ticketMasterData; + } - if (!$ticketMasterData['status']) { - 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() + ]; } - - $return_res = $this->importClaimMaster($ticketMasterData['mapped_array']); - - if(!$return_res){ - return ['status' => false, 'message' => 'Ticket Master Claim bulk insert failed']; - } - - $this->updateTicketMasterRejectedReasonInTPATable($ticketMasterData['rejected_reason_array']); - - $this->db->transComplete(); - - if ($this->db->transStatus() === false) { - return ['status' => false, 'message' => 'Ticket Master Claim bulk insert failed']; - } - - - - return ['status' => true, 'message' => 'Ticket Master Claim inserted successfully']; - } /** @@ -273,27 +274,14 @@ abstract class BaseTpaClaimImportService */ 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') - ->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(); - } /** @@ -304,10 +292,11 @@ abstract class BaseTpaClaimImportService $EmployeeModel = new EmployeeModel(); $employeeData = $EmployeeModel ->select([ - 'employees.id AS emp_id', + 'employees.id AS id', 'employees.email_corporate AS emp_mail', 'employees.mobile AS emp_mobile', - 'employees.name AS emp_name', + 'employees.name AS name', + 'employees.emp_code AS emp_code', // insured employee 'insured.id AS insured_emp_id', diff --git a/app/Libraries/TPAClaimsImportServices/FhplClaimImportService.php b/app/Libraries/TPAClaimsImportServices/FhplClaimImportService.php index 72614418..f4410b55 100644 --- a/app/Libraries/TPAClaimsImportServices/FhplClaimImportService.php +++ b/app/Libraries/TPAClaimsImportServices/FhplClaimImportService.php @@ -141,12 +141,8 @@ class FhplClaimImportService extends BaseTpaClaimImportService // Claim / Reference 'claim_id' => 'claim_number', - // Policy - 'policy_no' => 'policy_no', - // Employee / Member 'employee_id' => 'emp_code', - 'relationship' => 'relationship', // Claim Dates 'admission_date' => 'doa', @@ -177,10 +173,7 @@ class FhplClaimImportService extends BaseTpaClaimImportService // Payment 'cheque_no' => 'utr_details', 'uhid_no' => 'tpa_no', - - 'priority' => 1, - 'mode_of_intimation' => 5, - 'ticket_type_id' => 1, + 'claim_type' => 'tpa_claim_type', ]; protected $statusMapping = [ @@ -239,9 +232,7 @@ class FhplClaimImportService extends BaseTpaClaimImportService } $ticketMasterModel = new TicketMasterModel(); - $ticketMasterModel->insertBatch($data); - - return true; + return $ticketMasterModel->insertBatch($data); } @@ -252,9 +243,7 @@ class FhplClaimImportService extends BaseTpaClaimImportService } $builder = $this->db->table('claims_dump_fhpl'); - $builder->insertBatch($data); - - return true; + return $builder->updateBatch($data, 'id'); } @@ -265,9 +254,7 @@ class FhplClaimImportService extends BaseTpaClaimImportService } $builder = $this->db->table('claims_dump_fhpl'); - $builder->insertBatch($data); - - return true; + return $builder->updateBatch($data, 'id'); } @@ -372,7 +359,7 @@ class FhplClaimImportService extends BaseTpaClaimImportService if ($isduplicate) { $reason = "This claim already exists in our system."; - $rejecetd_reason[$row['id']] = ["ticket_master_insert_reject_reason" => $reason]; + $rejecetd_reason[] = ["id" => $row['id'], "master_reject_reason" => $reason]; continue; } @@ -391,23 +378,15 @@ class FhplClaimImportService extends BaseTpaClaimImportService if (!empty($employee_data)) { $item['emp_id'] = $employee_data['id'] ?? null; $item['emp_name'] = $employee_data['name'] ?? null; + $item['emp_code'] = $employee_data['emp_code'] ?? null; $item['emp_mail'] = $employee_data['email_corporate'] ?? null; $item['emp_mobile'] = $employee_data['mobile'] ?? null; $item['insured_emp_id'] = $employee_data['insured_emp_id'] ?? null; $item['insured_name'] = $employee_data['insured_name'] ?? null; } else { - $reason = sprintf( - 'The policy number "%s" does not exist in our system. ' . - 'Details - Client ID: %s, Client Policy ID: %s, Employee Number: %s, Relationship: %s', - $row['insurer_policy_number'], - $file_data['client_id'], - $file_data['client_policy_id'], - $row['employee_number'], - $item['relationship'] - ); - - $rejecetd_reason[$row['id']] = ["ticket_master_insert_reject_reason" => $reason]; + $reason = 'This employee not exist in our system.'; + $rejecetd_reason[] = ["id" => $row['id'], "master_reject_reason" => $reason]; continue; } diff --git a/app/Libraries/TPAClaimsImportServices/IciciClaimImportService.php b/app/Libraries/TPAClaimsImportServices/IciciClaimImportService.php index b89221ae..fb1d731f 100644 --- a/app/Libraries/TPAClaimsImportServices/IciciClaimImportService.php +++ b/app/Libraries/TPAClaimsImportServices/IciciClaimImportService.php @@ -81,7 +81,6 @@ class IciciClaimImportService extends BaseTpaClaimImportService // Employee / Member 'employee_member_id' => 'emp_code', - 'relation_group' => 'relationship', // Claim 'claim_number' => 'claim_number', @@ -100,7 +99,8 @@ class IciciClaimImportService extends BaseTpaClaimImportService 'cheque_number' => 'utr_details', 'uhid' => 'tpa_no', - 'rejected_query_desc' => 'claim_description', + 'rejected_query_desc' => 'claim_description', + 'type_of_claim' => 'tpa_claim_type', ]; protected $statusMapping = [ @@ -168,9 +168,7 @@ class IciciClaimImportService extends BaseTpaClaimImportService } $ticketMasterModel = new TicketMasterModel(); - $ticketMasterModel->insertBatch($data); - - return true; + return $ticketMasterModel->insertBatch($data); } @@ -181,9 +179,7 @@ class IciciClaimImportService extends BaseTpaClaimImportService } $builder = $this->db->table('claims_dump_icici'); - $builder->insertBatch($data); - - return true; + return $builder->upsertBatch($data, 'id'); } @@ -194,9 +190,7 @@ class IciciClaimImportService extends BaseTpaClaimImportService } $builder = $this->db->table('claims_dump_icici'); - $builder->insertBatch($data); - - return true; + return $builder->updateBatch($data, 'id'); } @@ -301,7 +295,7 @@ class IciciClaimImportService extends BaseTpaClaimImportService if ($isduplicate) { $reason = "This claim already exists in our system."; - $rejecetd_reason[$row['id']] = ["ticket_master_insert_reject_reason" => $reason]; + $rejecetd_reason[] = ["id" => $row['id'], "master_reject_reason" => $reason]; continue; } @@ -320,23 +314,15 @@ class IciciClaimImportService extends BaseTpaClaimImportService if (!empty($employee_data)) { $item['emp_id'] = $employee_data['id'] ?? null; $item['emp_name'] = $employee_data['name'] ?? null; + $item['emp_code'] = $employee_data['emp_code'] ?? null; $item['emp_mail'] = $employee_data['email_corporate'] ?? null; $item['emp_mobile'] = $employee_data['mobile'] ?? null; $item['insured_emp_id'] = $employee_data['insured_emp_id'] ?? null; $item['insured_name'] = $employee_data['insured_name'] ?? null; } else { - $reason = sprintf( - 'The policy number "%s" does not exist in our system. ' . - 'Details - Client ID: %s, Client Policy ID: %s, Employee Number: %s, Relationship: %s', - $row['insurer_policy_number'], - $file_data['client_id'], - $file_data['client_policy_id'], - $row['employee_number'], - $item['relationship'] - ); - - $rejecetd_reason[$row['id']] = ["ticket_master_insert_reject_reason" => $reason]; + $reason = 'This employee not exist in our system.'; + $rejecetd_reason[] = ["id" => $row['id'], "master_reject_reason" => $reason]; continue; } diff --git a/app/Libraries/TPAClaimsImportServices/MediAssistClaimImportService.php b/app/Libraries/TPAClaimsImportServices/MediAssistClaimImportService.php index 7326567d..0c68ece9 100644 --- a/app/Libraries/TPAClaimsImportServices/MediAssistClaimImportService.php +++ b/app/Libraries/TPAClaimsImportServices/MediAssistClaimImportService.php @@ -49,7 +49,7 @@ class MediAssistClaimImportService extends BaseTpaClaimImportService ["excel_column" => ["col_name" => "intimation_id", "col_index" => 30], "db_column" => "intimation_id"], ["excel_column" => ["col_name" => "intimation_date", "col_index" => 31], "db_column" => "intimation_date"], ["excel_column" => ["col_name" => "settled_date", "col_index" => 32], "db_column" => "settled_date"], - ["excel_column" => ["col_name" => "ClaimSource", "col_index" => 33], "db_column" => "claim_source"], + ["excel_column" => ["col_name" => "ClaimSource", "col_index" => 33], "db_column" => "ClaimSource"], ["excel_column" => ["col_name" => "claim_mode_of_rcpt", "col_index" => 34], "db_column" => "claim_mode_of_rcpt"], ["excel_column" => ["col_name" => "claim_type", "col_index" => 35], "db_column" => "claim_type"], ["excel_column" => ["col_name" => "claim_sub_type", "col_index" => 36], "db_column" => "claim_sub_type"], @@ -72,16 +72,16 @@ class MediAssistClaimImportService extends BaseTpaClaimImportService ["excel_column" => ["col_name" => "hospital_state", "col_index" => 53], "db_column" => "hospital_state"], ["excel_column" => ["col_name" => "hospital_pincode", "col_index" => 54], "db_column" => "hospital_pincode"], ["excel_column" => ["col_name" => "hospital_address", "col_index" => 55], "db_column" => "hospital_address"], - ["excel_column" => ["col_name" => "Clinic_DoctorName_Hospital", "col_index" => 56], "db_column" => "clinic_doctorname_hospital"], - ["excel_column" => ["col_name" => "OPD_pincode", "col_index" => 57], "db_column" => "opd_pincode"], - ["excel_column" => ["col_name" => "payable_amount_OPD_Consultation", "col_index" => 58], "db_column" => "payable_amount_opd_consultation"], - ["excel_column" => ["col_name" => "payable_amount_Dental", "col_index" => 59], "db_column" => "payable_amount_dental"], - ["excel_column" => ["col_name" => "payable_amount_Diagnostics", "col_index" => 60], "db_column" => "payable_amount_diagnostics"], - ["excel_column" => ["col_name" => "payable_amount_Other", "col_index" => 61], "db_column" => "payable_amount_other"], - ["excel_column" => ["col_name" => "payable_amount_Pharmacy", "col_index" => 62], "db_column" => "payable_amount_pharmacy"], - ["excel_column" => ["col_name" => "payable_amount_Vaccination", "col_index" => 63], "db_column" => "payable_amount_vaccination"], - ["excel_column" => ["col_name" => "payable_amount_Miscellaneous_Charges", "col_index" => 64], "db_column" => "payable_amount_miscellaneous_charges"], - ["excel_column" => ["col_name" => "payable_amount_Health_Checkup", "col_index" => 65], "db_column" => "payable_amount_health_checkup"], + ["excel_column" => ["col_name" => "Clinic_DoctorName_Hospital", "col_index" => 56], "db_column" => "Clinic_DoctorName_Hospital"], + ["excel_column" => ["col_name" => "OPD_pincode", "col_index" => 57], "db_column" => "OPD_pincode"], + ["excel_column" => ["col_name" => "payable_amount_OPD_Consultation", "col_index" => 58], "db_column" => "payable_amount_OPD_Consultation"], + ["excel_column" => ["col_name" => "payable_amount_Dental", "col_index" => 59], "db_column" => "payable_amount_Dental"], + ["excel_column" => ["col_name" => "payable_amount_Diagnostics", "col_index" => 60], "db_column" => "payable_amount_Diagnostics"], + ["excel_column" => ["col_name" => "payable_amount_Other", "col_index" => 61], "db_column" => "payable_amount_Other"], + ["excel_column" => ["col_name" => "payable_amount_Pharmacy", "col_index" => 62], "db_column" => "payable_amount_Pharmacy"], + ["excel_column" => ["col_name" => "payable_amount_Vaccination", "col_index" => 63], "db_column" => "payable_amount_Vaccination"], + ["excel_column" => ["col_name" => "payable_amount_Miscellaneous_Charges", "col_index" => 64], "db_column" => "payable_amount_Miscellaneous_Charges"], + ["excel_column" => ["col_name" => "payable_amount_Health_Checkup", "col_index" => 65], "db_column" => "payable_amount_Health_Checkup"], ["excel_column" => ["col_name" => "deduction_amount_copay", "col_index" => 66], "db_column" => "deduction_amount_copay"], ["excel_column" => ["col_name" => "deduction_amount_excess_ailment", "col_index" => 67], "db_column" => "deduction_amount_excess_ailment"], ["excel_column" => ["col_name" => "deduction_amount_excess_policy", "col_index" => 68], "db_column" => "deduction_amount_excess_policy"], @@ -116,10 +116,8 @@ class MediAssistClaimImportService extends BaseTpaClaimImportService // Employee / Beneficiary details 'pribenef_employee_code' => 'emp_code', - 'benef_relation' => 'relationship', // Policy / Claim identifiers - 'policy_no' => 'policy_no', 'claim_id' => 'claim_number', 'event_id' => 'tpa_no', 'claim_pre_auths' => 'tpa_claim_push_reference_no', @@ -153,6 +151,7 @@ class MediAssistClaimImportService extends BaseTpaClaimImportService // Payment 'utr_no' => 'utr_details', + 'claim_type' => 'tpa_claim_type', ]; protected $statusMapping = [ @@ -166,7 +165,6 @@ class MediAssistClaimImportService extends BaseTpaClaimImportService 'Cashless Document Awaited' => 3, ]; - /** * ABSTRACT FUNCTIONs */ @@ -177,9 +175,8 @@ class MediAssistClaimImportService extends BaseTpaClaimImportService } $builder = $this->db->table('claims_dump_medi_assist'); - $builder->insertBatch($data); + return $builder->insertBatch($data); - return true; } @@ -190,9 +187,7 @@ class MediAssistClaimImportService extends BaseTpaClaimImportService } $ticketMasterModel = new TicketMasterModel(); - $ticketMasterModel->insertBatch($data); - - return true; + return $ticketMasterModel->insertBatch($data); } @@ -216,9 +211,7 @@ class MediAssistClaimImportService extends BaseTpaClaimImportService } $builder = $this->db->table('claims_dump_medi_assist'); - $builder->insertBatch($data); - - return true; + return $builder->updateBatch($data, 'id'); } @@ -319,7 +312,7 @@ class MediAssistClaimImportService extends BaseTpaClaimImportService if ($isduplicate) { $reason = "This claim already exists in our system."; - $rejecetd_reason[$row['id']] = ["ticket_master_insert_reject_reason" => $reason]; + $rejecetd_reason[] = ["id" => $row['id'], "master_reject_reason" => $reason]; continue; } @@ -338,23 +331,15 @@ class MediAssistClaimImportService extends BaseTpaClaimImportService if (!empty($employee_data)) { $item['emp_id'] = $employee_data['id'] ?? null; $item['emp_name'] = $employee_data['name'] ?? null; + $item['emp_code'] = $employee_data['emp_code'] ?? null; $item['emp_mail'] = $employee_data['email_corporate'] ?? null; $item['emp_mobile'] = $employee_data['mobile'] ?? null; $item['insured_emp_id'] = $employee_data['insured_emp_id'] ?? null; $item['insured_name'] = $employee_data['insured_name'] ?? null; } else { - $reason = sprintf( - 'The policy number "%s" does not exist in our system. ' . - 'Details - Client ID: %s, Client Policy ID: %s, Employee Number: %s, Relationship: %s', - $row['insurer_policy_number'], - $file_data['client_id'], - $file_data['client_policy_id'], - $row['employee_number'], - $item['relationship'] - ); - - $rejecetd_reason[$row['id']] = ["ticket_master_insert_reject_reason" => $reason]; + $reason = 'This employee not exist in our system.'; + $rejecetd_reason[] = ["id" => $row['id'], "master_reject_reason" => $reason]; continue; } diff --git a/app/Libraries/TPAClaimsImportServices/RcareClaimImportService.php b/app/Libraries/TPAClaimsImportServices/RcareClaimImportService.php index 4808d89e..a75289a2 100644 --- a/app/Libraries/TPAClaimsImportServices/RcareClaimImportService.php +++ b/app/Libraries/TPAClaimsImportServices/RcareClaimImportService.php @@ -60,10 +60,8 @@ class RcareClaimImportService extends BaseTpaClaimImportService // Employee / Member 'employee_member_id' => 'emp_code', - 'relation' => 'relationship', // Policy - 'policy_number' => 'policy_no', 'policy_start_date' => 'date_of_incep', // Claim Dates @@ -159,9 +157,7 @@ class RcareClaimImportService extends BaseTpaClaimImportService } $ticketMasterModel = new TicketMasterModel(); - $ticketMasterModel->insertBatch($data); - - return true; + return $ticketMasterModel->insertBatch($data); } @@ -172,9 +168,7 @@ class RcareClaimImportService extends BaseTpaClaimImportService } $builder = $this->db->table('claims_dump_reliance'); - $builder->insertBatch($data); - - return true; + return $builder->updateBatch($data, 'id'); } @@ -185,9 +179,7 @@ class RcareClaimImportService extends BaseTpaClaimImportService } $builder = $this->db->table('claims_dump_reliance'); - $builder->insertBatch($data); - - return true; + return $builder->updateBatch($data, 'id'); } @@ -291,7 +283,7 @@ class RcareClaimImportService extends BaseTpaClaimImportService if ($isduplicate) { $reason = "This claim already exists in our system."; - $rejecetd_reason[$row['id']] = ["ticket_master_insert_reject_reason" => $reason]; + $rejecetd_reason[] = ["id" => $row['id'], "master_reject_reason" => $reason]; continue; } @@ -310,23 +302,15 @@ class RcareClaimImportService extends BaseTpaClaimImportService if (!empty($employee_data)) { $item['emp_id'] = $employee_data['id'] ?? null; $item['emp_name'] = $employee_data['name'] ?? null; + $item['emp_code'] = $employee_data['emp_code'] ?? null; $item['emp_mail'] = $employee_data['email_corporate'] ?? null; $item['emp_mobile'] = $employee_data['mobile'] ?? null; $item['insured_emp_id'] = $employee_data['insured_emp_id'] ?? null; $item['insured_name'] = $employee_data['insured_name'] ?? null; } else { - $reason = sprintf( - 'The policy number "%s" does not exist in our system. ' . - 'Details - Client ID: %s, Client Policy ID: %s, Employee Number: %s, Relationship: %s', - $row['insurer_policy_number'], - $file_data['client_id'], - $file_data['client_policy_id'], - $row['employee_number'], - $item['relationship'] - ); - - $rejecetd_reason[$row['id']] = ["ticket_master_insert_reject_reason" => $reason]; + $reason = 'This employee not exist in our system.'; + $rejecetd_reason[] = ["id" => $row['id'], "master_reject_reason" => $reason]; continue; } diff --git a/app/Libraries/TPAClaimsImportServices/VidalClaimImportService.php b/app/Libraries/TPAClaimsImportServices/VidalClaimImportService.php index b8bc92b8..50ef9924 100644 --- a/app/Libraries/TPAClaimsImportServices/VidalClaimImportService.php +++ b/app/Libraries/TPAClaimsImportServices/VidalClaimImportService.php @@ -163,7 +163,6 @@ class VidalClaimImportService extends BaseTpaClaimImportService ["excel_column" => "Last Document Received date", "db_column" => "last_document_received_date"], ]; - protected $mapping = [ ["excel_column" => ["col_name" => "TPA Policy Number", "col_index" => 0], "db_column" => "tpa_policy_number"], @@ -312,11 +311,9 @@ class VidalClaimImportService extends BaseTpaClaimImportService ["excel_column" => ["col_name" => "Last Document Received date", "col_index" => 113], "db_column" => "last_document_received_date"], ]; - protected $ticketMasterMapping = [ // Policy / Claim identifiers - 'insurer_policy_number' => 'policy_no', 'insurer_claim_number' => 'claim_number', 'tpa_claim_number' => 'tpa_claim_id', @@ -346,9 +343,9 @@ class VidalClaimImportService extends BaseTpaClaimImportService // Meta 'file_id' => 'file_id', + 'type_of_claim' => 'tpa_claim_type', ]; - protected $statusMapping = [ 'CL Paid with Settlement Letter' => 11, 'CL Rejected' => 8, @@ -380,9 +377,7 @@ class VidalClaimImportService extends BaseTpaClaimImportService } $ticketMasterModel = new TicketMasterModel(); - $ticketMasterModel->insertBatch($data); - - return true; + return $ticketMasterModel->insertBatch($data); } @@ -393,9 +388,7 @@ class VidalClaimImportService extends BaseTpaClaimImportService } $builder = $this->db->table('claims_dump_vidal'); - $builder->insertBatch($data); - - return true; + return $builder->updateBatch($data, 'id'); } @@ -406,9 +399,7 @@ class VidalClaimImportService extends BaseTpaClaimImportService } $builder = $this->db->table('claims_dump_vidal'); - $builder->insertBatch($data); - - return true; + return $builder->updateBatch($data, 'id'); } @@ -514,7 +505,7 @@ class VidalClaimImportService extends BaseTpaClaimImportService if ($isduplicate) { $reason = "This claim already exists in our system."; - $rejecetd_reason[$row['id']] = ["ticket_master_insert_reject_reason" => $reason]; + $rejecetd_reason[] = ["id" => $row['id'], "master_reject_reason" => $reason]; continue; } @@ -534,22 +525,14 @@ class VidalClaimImportService extends BaseTpaClaimImportService $item['emp_id'] = $employee_data['id'] ?? null; $item['emp_name'] = $employee_data['name'] ?? null; $item['emp_mail'] = $employee_data['email_corporate'] ?? null; + $item['emp_code'] = $employee_data['emp_code'] ?? null; $item['emp_mobile'] = $employee_data['mobile'] ?? null; $item['insured_emp_id'] = $employee_data['insured_emp_id'] ?? null; $item['insured_name'] = $employee_data['insured_name'] ?? null; } else { - $reason = sprintf( - 'The policy number "%s" does not exist in our system. ' . - 'Details - Client ID: %s, Client Policy ID: %s, Employee Number: %s, Relationship: %s', - $row['insurer_policy_number'], - $file_data['client_id'], - $file_data['client_policy_id'], - $row['employee_number'], - $item['relationship'] - ); - - $rejecetd_reason[$row['id']] = ["ticket_master_insert_reject_reason" => $reason]; + $reason = 'This employee not exist in our system.'; + $rejecetd_reason[] = ["id" => $row['id'], "master_reject_reason" => $reason]; continue; } diff --git a/app/Libraries/ZipService.php b/app/Libraries/ZipService.php new file mode 100644 index 00000000..42030ffc --- /dev/null +++ b/app/Libraries/ZipService.php @@ -0,0 +1,179 @@ +s3Service = new S3Service(); + } + + /** + * Zips a local folder and uploads it to S3 + */ + public function zipAndUploadS3(string $localFolderPath, string $s3Folder = '', string $zipName = ''): array + { + // dd($localFolderPath, $s3Folder, $zipName); + if (!is_dir($localFolderPath)) { + return ['status' => false, 'message' => 'Local directory does not exist']; + } + + // 1. Prepare naming + $folderName = basename($localFolderPath); + $zipName = $zipName ?: $folderName . '_' . time() . '.zip'; + $tempZipPath = FCPATH . 'tmp/' . $zipName; + + // 2. Create the Local Zip + $zipResult = $this->createLocalZip($localFolderPath, $tempZipPath); + + if (!$zipResult['status']) { + return $zipResult; + } + + try { + + // 3. Upload to S3 + $uploadResult = $this->s3Service->upload($tempZipPath, $s3Folder, $zipName); + // dd($uploadResult); + + // 4. Cleanup + if (file_exists($tempZipPath)) { + unlink($tempZipPath); + } + + $get_presinged_url = $this->s3Service->getPresignedUrl($uploadResult['key'], 2,880); + + // To delete the original temprory folder after zipping and uploading + // $this->deleteDirectory($localFolderPath); + + return ['status' => true, 'data' => $uploadResult, 'presigned_url' => $get_presinged_url]; + + } catch (\Exception $e) { + log_message('error', 'Zip/Upload Error: ' . $e->getMessage()); + return ['status' => false, 'message' => $e->getMessage()]; + } + } + + /** + * Zips a local folder using native ZipArchive + */ + + public function createLocalZip(string $localFolderPath, string $destinationPath): array + { + // 1. Validate Source Directory + if (!is_dir($localFolderPath)) { + return ['status' => false, 'message' => 'Source directory does not exist']; + } + + // 2. Check if folder is empty (ignoring hidden files) + $filesInFolder = array_diff(scandir($localFolderPath), array('.', '..')); + if (empty($filesInFolder)) { + return ['status' => false, 'message' => 'No records found to compress']; + } + + // 3. Ensure the destination directory exists and is writable + $destDir = dirname($destinationPath); + if (!is_dir($destDir)) { + mkdir($destDir, 0777, true); + } + + $zip = new ZipArchive(); + + // 4. Open the zip file + $openZip = $zip->open($destinationPath, ZipArchive::CREATE | ZipArchive::OVERWRITE); + if ($openZip !== true) { + return ['status' => false, 'message' => "Could not open Zip. Error code: " . $openZip]; + } + + try { + $files = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($localFolderPath, \RecursiveDirectoryIterator::SKIP_DOTS), + \RecursiveIteratorIterator::LEAVES_ONLY + ); + + $fileCount = 0; + $sourcePath = realpath($localFolderPath); + + foreach ($files as $file) { + if (!$file->isDir()) { + $filePath = $file->getRealPath(); + + // Calculate relative path correctly + $relativePath = ltrim(substr($filePath, strlen($sourcePath)), DIRECTORY_SEPARATOR); + + // Add to zip + if ($zip->addFile($filePath, $relativePath)) { + $fileCount++; + } + } + } + + // 5. Finalize + if ($fileCount > 0) { + if (!$zip->close()) { + return ['status' => false, 'message' => 'Failed to write ZIP file to disk (Check permissions/space)']; + } + } else { + $zip->close(); + return ['status' => false, 'message' => 'No files were added to the archive']; + } + + return [ + 'status' => true, + 'path' => $destinationPath, + 'count' => $fileCount, + 'message' => 'Zip created successfully' + ]; + + } catch (\Exception $e) { + // Only attempt to close if the zip object was successfully opened + if (isset($zip->status) && $zip->status !== ZipArchive::ER_OK) { + @$zip->close(); + } + log_message('error', 'Local Zip Error: ' . $e->getMessage()); + return ['status' => false, 'message' => 'from catch Exception: ' . $e->getMessage()]; + } + } + + private function deleteDirectory($dir) + { + if (!file_exists($dir)) { + return true; + } + + if (!is_dir($dir)) { + // Use @ to suppress warnings if the file is already gone or locked + // return @unlink($dir); + return unlink($dir); + } + + // scandir can return false if the directory isn't readable + $items = scandir($dir); + if ($items === false) { + return false; + } + + foreach ($items as $item) { + if ($item == '.' || $item == '..') { + continue; + } + + // Recursively call the function + if (!$this->deleteDirectory($dir . DIRECTORY_SEPARATOR . $item)) { + // If a child cannot be deleted, attempt to change its permissions and try once more + @chmod($dir . DIRECTORY_SEPARATOR . $item, 0777); + if (!$this->deleteDirectory($dir . DIRECTORY_SEPARATOR . $item)) { + return false; + } + } + } + + // Finally, remove the empty directory + return @rmdir($dir); + } +} \ No newline at end of file diff --git a/app/Models/ClientDepositModel.php b/app/Models/ClientDepositModel.php index 8a61b204..7aa4ff7b 100755 --- a/app/Models/ClientDepositModel.php +++ b/app/Models/ClientDepositModel.php @@ -30,6 +30,7 @@ class ClientDepositModel extends Model "cd_ac_pk", "record_date", "policy_transaction_id", + "file_id", ]; diff --git a/app/Models/ClientPolicyModel.php b/app/Models/ClientPolicyModel.php index fa7672ec..b11c97f6 100755 --- a/app/Models/ClientPolicyModel.php +++ b/app/Models/ClientPolicyModel.php @@ -303,6 +303,8 @@ class ClientPolicyModel extends Model $caseSql = ""; } + $url = base_url('downloadCdSplitUpFile?id='); + // Fetch the deposit data based on client and insurer IDs $query = $this->db->table('cash_deposit') ->select('cash_deposit.*') @@ -312,6 +314,12 @@ class ClientPolicyModel extends Model // ->select('policies.name as policy_name') ->select('policy_type.policy_type') ->select('user_profiles.first_name as username') + ->select("CASE + WHEN cash_deposit.file_id IS NOT NULL AND cash_deposit.file_id != '' + THEN CONCAT(" . $this->db->escape($url) . ", cash_deposit.file_id) + ELSE NULL + END AS split_up_url", + false) ->select($caseSql) ->join('user_profiles', 'user_profiles.id = cash_deposit.created_by', 'left') ->join('insurers', 'insurers.id = cash_deposit.insurer_id', 'left') @@ -337,7 +345,9 @@ class ClientPolicyModel extends Model } $query->orderBy('cash_deposit.id', 'DESC'); - return $query->get()->getResult(); + $data = $query->get()->getResult(); + + return $data; } diff --git a/app/Models/EmployeePolicyModel.php b/app/Models/EmployeePolicyModel.php index 7df0e021..6b9b17f1 100755 --- a/app/Models/EmployeePolicyModel.php +++ b/app/Models/EmployeePolicyModel.php @@ -280,6 +280,14 @@ class EmployeePolicyModel extends Model 'cp.policy_no', 'cp.policy_type_id', 'cp.is_addon', + '( + select id from employees + where emp_code = emp.emp_code + and client_id = emp.client_id + and lower(relationship) = "self" + and is_active = 1 + limit 1 + ) as self_employee_id', $ecard_download_link ]) ->join('employees emp', 'employee_polices.employee_id = emp.id') @@ -391,8 +399,8 @@ class EmployeePolicyModel extends Model ->where('is_active',1) ->find(); } -//------------------------------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------------------------- public function getInceptionEmployeeDataForExportExcel($ref_data, $return_type = 0) { @@ -2218,5 +2226,70 @@ class EmployeePolicyModel extends Model // return $result; } + // for this function using bulk e-card download as a zip + public function getEmployeeDataWithPolicyUsingClientPolicyIdOrEmployeePolicyIds($params, $limit = 100, $last_id = 0) + { + $client_policy_id = $params['client_policy_id'] ?? null; + $emp_policy_ids = $params['emp_policy_ids'] ?? null; + + if (empty($client_policy_id) && empty($emp_policy_ids)) { + return []; + } + + $builder = $this->db->table('employee_polices'); + $builder->select(' + employee_polices.id as emp_policy_id, + employee_polices.client_policy_id, + employees.name, + employees.emp_code, + employees.id as emp_id, + tpa.short_name, + employee_polices.tpa_id, + client_policy.policy_no + ') + ->join('client_policy', 'client_policy.id = employee_polices.client_policy_id') + ->join('employees', 'employees.id = employee_polices.employee_id') + ->join('tpa', 'tpa.id = client_policy.tpa_id') + ->where([ + 'employees.emp_status' => 'active', + 'employees.is_active' => '1', + 'employee_polices.status' => 'active', + 'employee_polices.is_active' => '1', + ]) + ->where("employee_polices.tpa_id IS NOT NULL AND employee_polices.tpa_id <> ''"); + + // BATCHING LOGIC: Only get records greater than the last processed ID + if ($last_id > 0) { + $builder->where('employee_polices.id >', $last_id); + } + + if ($client_policy_id) $builder->where('employee_polices.client_policy_id', $client_policy_id); + if ($emp_policy_ids) $builder->whereIn('employee_polices.id', $emp_policy_ids); + + $builder->orderBy('employee_polices.id', 'ASC'); // Critical for keyset pagination + $builder->limit($limit); + + return $builder->get()->getResultArray(); + } + + public function getClientPolicyDetailsByClientPolicyIdOrEmployeePolicyId($params) + { + $client_policy_id = $params['client_policy_id'] ?? null; + $emp_policy_id = $params['emp_policy_id'] ?? null; + + if (empty($client_policy_id) && empty($emp_policy_id)) { + return []; + } + + $builder = $this->db->table('client_policy'); + $builder->select('client_policy.*') + ->join('employee_polices ep', 'ep.client_policy_id = client_policy.id', 'left'); + + if ($client_policy_id) $builder->where('employee_polices.client_policy_id', $client_policy_id); + if ($emp_policy_id) $builder->where('employee_polices.id', $emp_policy_id); + + return $builder->get()->getResultArray(); + } + } \ No newline at end of file diff --git a/app/Models/PolicyTransactionModel.php b/app/Models/PolicyTransactionModel.php index 98243549..74df001c 100644 --- a/app/Models/PolicyTransactionModel.php +++ b/app/Models/PolicyTransactionModel.php @@ -2540,6 +2540,9 @@ pt.ref, pt.data_received_date, + pt.endorse_eff_date, + pt.policy_start_date, + pt.policy_end_date, pt.renewal_date, pt.installment, nhance_branch.branch_name as nhance_branch, @@ -2699,6 +2702,9 @@ pt.ref, pt.data_received_date, + pt.endorse_eff_date, + pt.policy_start_date, + pt.policy_end_date, pt.renewal_date, pt.installment, nhance_branch.branch_name as nhance_branch, @@ -3143,6 +3149,9 @@ pt.ref, pt.data_received_date, + pt.endorse_eff_date, + pt.policy_start_date, + pt.policy_end_date, pt.renewal_date, pt.installment, nhance_branch.branch_name as nhance_branch, @@ -3303,6 +3312,9 @@ pt.ref, pt.data_received_date, + pt.endorse_eff_date, + pt.policy_start_date, + pt.policy_end_date, pt.renewal_date, pt.installment, nhance_branch.branch_name as nhance_branch, @@ -3490,6 +3502,9 @@ pt.ref, pt.data_received_date, + pt.endorse_eff_date, + pt.policy_start_date, + pt.policy_end_date, pt.renewal_date, pt.installment, nhance_branch.branch_name as nhance_branch, @@ -3676,7 +3691,7 @@ $result = $query->getResultArray(); // $countofalldata = count($result); // dd($result); - dd($this->db->getLastQuery()->getQuery()); + // dd($this->db->getLastQuery()->getQuery()); $keys = []; $filtered = []; diff --git a/app/Models/TicketMasterModel.php b/app/Models/TicketMasterModel.php index f2feb0d5..7b50d11e 100644 --- a/app/Models/TicketMasterModel.php +++ b/app/Models/TicketMasterModel.php @@ -93,6 +93,9 @@ class TicketMasterModel extends Model 'required_docs', 'policy_transaction_id', 'tpa_claim_type', + 'tpa_ailments', + 'claim_dump_ref_id', + ]; diff --git a/app/Views/UserList.php b/app/Views/UserList.php index 28cde270..ca47296c 100755 --- a/app/Views/UserList.php +++ b/app/Views/UserList.php @@ -581,7 +581,7 @@ table.dataTable tbody td {
- +
@@ -884,7 +884,20 @@ table.dataTable tbody td { +getFlashdata('error')) : ?> + getFlashdata('error') as $error) : ?> + + + + + + + + + + + + + + diff --git a/app/Views/notification.php b/app/Views/notification.php index 93e8213e..7948a3a4 100755 --- a/app/Views/notification.php +++ b/app/Views/notification.php @@ -131,6 +131,8 @@ $member_review_and_summary_mail = 0; $account_maneger_summary_mail = 0; $client_hr_summary_mail = 0; + $hr_cd_insufficient_balance_mail = 0; + if (isset($notification)) { foreach ($notification as $value) { @@ -161,6 +163,10 @@ if ($value['template_name'] == 'client_hr_summary_mail') { $client_hr_summary_mail = $value['enabled']; } + + if ($value['template_name'] == 'hr_cd_insufficient_balance_mail') { + $hr_cd_insufficient_balance_mail = $value['enabled']; + } } } ?>

@@ -265,6 +271,7 @@ +
@@ -283,6 +290,26 @@
+
+ + +
+
+
+ + HR CD Insufficient Balance Mail +
+
+ + + +
+
+ +
@@ -988,6 +1015,89 @@ + + +