diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 8bd55f6..ee3c61e 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -138,7 +138,8 @@ $routes->group('api', ['filter' => 'appSignature'], function ($routes) { - $routes->get('checkPolicyDoc', 'PolicyController::checkPolicyDoc'); + $routes->get('checkPolicyDoc', 'PolicyController::readFile'); + $routes->get('calculateCommission', 'PolicyController::calculateCommission'); $routes->get('testPolicy', 'QuotationController::testPolicy'); diff --git a/app/Controllers/JobWorker.php b/app/Controllers/JobWorker.php new file mode 100755 index 0000000..3eb76d4 --- /dev/null +++ b/app/Controllers/JobWorker.php @@ -0,0 +1,235 @@ + [ + 'type' => 'CC', // Handler Category (Possible values: HC, CC, HF) + 'handler' => 'App\Controllers\PolicyController', + ], + ]; + + + + public function __construct() + { + + } + + public static function streamOutput($data) + { + ob_implicit_flush(true); + // try { ob_end_flush(); } catch(Exception $e) { echo $e->getMessage(); } + echo $data; + flush(); + } + + public static function processJobs(array $jobdata = []) + { + // echo 'listen';//die(); + $query = " + SELECT id, name, payload, uuid + FROM partner_jobs + WHERE status=? + ORDER BY created_dt ASC"; + $where_condition = [self::STATUS_QUEUED]; + $db = \Config\Database::connect(); + $jobs = $db->query($query, $where_condition)->getResult(); + + if(count($jobs)) + { + // echo count($jobs); + // print_r($jobs);die; + foreach($jobs as $key => $job) + { + // echo $job->id.' - '.$job->name; + //sleep(1); + + SELF::processjob(['id' => $job->id,'uuid' => $job->uuid]); + // usleep( 500000 ); + } + } + } + /** + * process jobs + */ + public static function processJob(array $jobdata = []) + { + + // print_r($jobdata); + // echo 'listen'; + // die(); + $query = " + SELECT id, name, payload, uuid + FROM partner_jobs + WHERE status=? + ORDER BY created_dt ASC + LIMIT 1 FOR UPDATE"; + $where_condition = [self::STATUS_QUEUED]; + + if(isset($jobdata) && count($jobdata)) + { + $query = " + SELECT id, name, payload, uuid + FROM partner_jobs + WHERE status=? AND id=? AND uuid=? + ORDER BY created_dt ASC + LIMIT 1 FOR UPDATE"; + $where_condition = [self::STATUS_QUEUED,$jobdata['id'],$jobdata['uuid']]; + } + + $db = \Config\Database::connect(); + $job = $db->query($query, $where_condition)->getResult(); + // print_r($job);die(); + if ($job !== []) + { + $job = $job[0]; + + + + // echo "\nProcessing job id - " . $job->id . "\n"; + SELF::streamOutput("\nProcessing job id - " . $job->id . "\n"); + // sleep(5); + // echo "Job name - " . $job->name . "\n"; + SELF::streamOutput("Job name - " . $job->name . "\n"); + // sleep(5); + + // print_r(SELF::$event_class_mapping); + // echo array_key_exists($job->name,SELF::$event_class_mapping) ? 'mapped' : 'notmapped'; + // die(); + try + { + $start = microtime(true); + $runtime = null; + $job_status = self::STATUS_RUNNING; + $db->query("UPDATE jobs SET status=? WHERE id=? AND uuid=?", [$job_status, $job->id,$job->uuid]); + + if (!array_key_exists($job->name,SELF::$event_class_mapping)) + { + throw new \RuntimeException('Job ' . $job->name . ' handler not registered'); + } + + $handler = SELF::$event_class_mapping[$job->name]; + $handleInstance = null; + + if($handler['type'] == 'CC' || $handler['type'] == 'HC') + { + // echo 'CLASS - ' . $handler['type'].' - ' . $handler['handler']; + $handlerClass = $handler['handler']; + if(class_exists($handlerClass)) + { + $handleInstance = new $handlerClass(); + } + else + { + throw new \RuntimeException('Job ' . $job->name . ' or handler class not found'); + // echo $e->getMessage(); + } + + if (method_exists($handleInstance, $job->name)) + { + $jobHandler = [$handleInstance, $job->name]; + //throw new \RuntimeException('Job ' . $job->name . ' not found'); + } + else if(method_exists($handleInstance, 'handle')) + { + $jobHandler = [$handleInstance, 'handle']; + } + else + { + throw new \RuntimeException('Job ' . $job->name . ' or handler not found'); + } + } + else if($handler['type'] == 'HF') + { + // echo 'HF - ' . $handler['type']; + $jobHandler = $handleInstance = $handler['handler']; + // echo $jobHandler; + + } + else{ + throw new \RuntimeException('Job ' . $job->name . ' Invalid job type'); + } + + $payload = json_decode($job->payload, true); + if (!is_array($payload)) + { + throw new \InvalidArgumentException('Invalid payload format here'); + } + + $payload = is_array($payload) ? $payload : []; + try + { + $response = $jobHandler($payload,$job->id); + $job_status = self::STATUS_DONE; + } + catch(\Exception $e) + { + $job_status = self::STATUS_FAILED; + $runtime = $runtime === null ? microtime(true) - $start : $runtime; + $response = ['file_name' => $e->getFile(),'error' => $e->getMessage(),'line_no' => $e->getLine(),'info' => $e->getTraceAsString(),'scope' => 'task failed']; + } + + $runtime = microtime(true) - $start; + + } + catch (\Exception $e) + { + //die(); + $job_status = self::STATUS_FAILED; + $runtime = $runtime === null ? microtime(true) - $start : $runtime; + $response = ['file_name' => $e->getFile(),'error' => $e->getMessage(),'line_no' => $e->getLine(),'info' => $e->getTraceAsString(),'scope' => 'worker failed']; + } + + $db->query("UPDATE jobs SET status=?, run_time=?, response=? WHERE id=? AND uuid=?", [ + $job_status, + $runtime, + json_encode($response), + $job->id,$job->uuid + ]); + + //update file status if this job is directly linked with a file id + + if($job_status == self::STATUS_FAILED) + { + //get file from job payload + // if(array_key_exists('file_id', $payload) && $payload['file_id'] != NULL && $payload['file_id'] != "" && is_numeric($payload['file_id']) && count($payload) == 1) + // { + // $fileModel = new FileModel(); + // $fileModel->where('id', $payload['file_id']) + // ->set(['status' => 'failed','reason' => json_encode(['error_type' => 0,'error_summary' => [0],'error_data' => 'System Error, please contact Admin/Support team']) ]) + // ->update(); + // } + + } + + // echo "Job $job->id $job_status. Response - $response \n"; + // echo "Job $job->id $job_status \n"; + SELF::streamOutput("Job $job->id $job_status \n"); + return true; + } + else + { + echo 'no job found in queue'; + } + } + + + + + + +} diff --git a/app/Controllers/Jobs.php b/app/Controllers/Jobs.php new file mode 100755 index 0000000..f44a6d1 --- /dev/null +++ b/app/Controllers/Jobs.php @@ -0,0 +1,65 @@ + 'check','payload' => ['a' => 10]]) + public function __construct() + { + // $this->job_payload = $payload; + // $this->myLogger = \Config\Services::mylogger(); + } + + /** + * add jobs to queue + */ + public static function addJob(array $payload) + { + $jobModel = new JobModel(); + $myLogger = \Config\Services::mylogger(); + + try + { + if(!is_array($payload)) + { + throw new \InvalidArgumentException('Invalid payload format while add job'); + } + + if(!isset($payload['job_name'])) + { + throw new \InvalidArgumentException('Job name not found while add job'); + } + + if(!isset($payload['payload'])) + { + throw new \InvalidArgumentException('Job payload not found while add job'); + } + + $uuid = generate_uuid(); + $jobid = $jobModel->insert(['name' => $payload['job_name'],'uuid' => $uuid,'payload' => json_encode($payload['payload']), 'status' => isset($payload['status']) ? $payload['status'] : 'queued']); + // echo $jobid; + $myLogger->logme('error','new job {jobid} added to queue',['jobid' => $jobid]); + return ['id' => $jobid,'uuid' => $uuid,'job_name' => $payload['job_name']]; + } + catch(\Exception $e) + { + $message = $e->getMessage(); + return $message; + $myLogger->logme('error','{messgae}',['messgae' => $message]); + } + } + +} diff --git a/app/Controllers/PolicyController.php b/app/Controllers/PolicyController.php index 8a8a6dd..45c41a1 100644 --- a/app/Controllers/PolicyController.php +++ b/app/Controllers/PolicyController.php @@ -249,7 +249,6 @@ class PolicyController extends ResourceController } } - public function uploadPolicyFile() { try { @@ -333,8 +332,6 @@ class PolicyController extends ResourceController } } - - // Download policy file public function downloadPolicyFile() { @@ -380,12 +377,93 @@ class PolicyController extends ResourceController } } + public function readFileAndCalculateCommission(array $data) + { + $policyId = $data['policy_id']; - public function checkPolicyDoc($policyId) + log_message('debug', 'checkPolicyDoc() started for policy_id: '.$policyId); + + $readDoc = $this->checkPolicyDoc(["policy_id" => $policyId]); + + if($readDoc['status'] == 'success') + { + + $data = $readDoc['data']; + + //update data in to policy table + $policyData['policy_number'] = $data['policy']['policy_number'] ?? null; + $policyData['issued_date'] = $data['policy']['issue_date'] ?? null; + $policyData['start_date'] = $data['policy']['period']['start'] ?? null; + $policyData['end_date'] = $data['policy']['period']['end'] ?? null; + $policyData['tp'] = $data['premium']['tp'] ?? null; + $policyData['od'] = $data['premium']['od'] ?? null; + $policyData['pa'] = $data['premium']['pa'] ?? null; + $policyData['cgst'] = $data['premium']['taxes']['cgst'] ?? 0; + $policyData['sgst'] = $data['premium']['taxes']['sgst'] ?? 0; + $policyData['igst'] = $data['premium']['taxes']['igst'] ?? 0; + $policyData['premium_amount'] = $data['premium']['total'] ?? null; + $policyData['rto_state_code'] = $data['vehicle']['rto_state_code'] ?? null; + $policyData['rto_city_code'] = $data['vehicle']['rto_city_code'] ?? null; + $policyData['weight'] = $data['vehicle']['weight'] ?? null; + $policyData['fuel_type'] = $data['vehicle']['fuel_type'] ?? null; + $policyData['date_of_registration'] = $data['vehicle']['date_of_registration'] ?? null; + $policyData['year_of_manufacture'] = $data['vehicle']['year_of_manufacture'] ?? null; + $policyData['engine_no'] = $data['vehicle']['engine_no'] ?? null; + $policyData['chassis_no'] = $data['vehicle']['chassis_no'] ?? null; + $policyData['make'] = $data['vehicle']['make'] ?? null; + $policyData['model'] = $data['vehicle']['model'] ?? null; + $policyData['cubic_capacity'] = $data['vehicle']['cubic_capacity'] ?? null; + $policyData['vehicle_type'] = $data['vehicle']['vehicle_type'] ?? null; + + log_message('debug', 'Policy Update Payload: ' . json_encode($policyData)); + + $updateStatus = $this->PolicyModel->update($policyId,$policyData); + + if ($updateStatus) + { + log_message('debug', 'Policy updated successfully for ID: '.$policyId); + + $calculateCommission = $this->calculateCommission($policyId); + + if($calculateCommission['status'] == 'success') + { + log_message('debug', 'BDS record creating started for ID: '.$policyId); + + // Call helper to create BDS record after creating client,clientPolicy,vehicle records + $policyData = $this->PolicyModel->select('partner_policy.*,Q.insurer_id,Q.insurer_branch_id,E.name as client_name,E.mobile as client_mobile,E.email as client_email,E.reg_no,E.vehicle_type_id,A.id as agent_id,A.agent_code') + ->join('partner_quotation Q', 'Q.id = partner_policy.quotation_id AND Q.status = "Accepted"', 'left') + ->join('partner_enquiry E', 'E.id = partner_policy.enquiry_id', 'left') + ->join('partner_agent A', 'A.id = partner_policy.agent_id', 'left') + ->where('partner_policy.id',$policyId) + ->first(); + $bdsLogs = createBDS($policyData, $policyId); + if (!empty($bdsLogs)) { + foreach ($bdsLogs as $msg) { + log_message('info', '[BDS Entry] ' . $msg); + } + } + } + + } else { + log_message('error', 'Failed to update policy for ID: '.$policyId); + } + } else { + log_message('error', 'checkPolicyDoc returned failure: ' . json_encode($readDoc)); + } + + + echo '
';
+        print_r($readDoc); 
+        die;
+        $this->respond($data);
+    }
+
+    public function checkPolicyDoc($policyId = null)
     {
 
          try
          {  
+            
 
             // Replace with your actual Gemini API key
             $apiKey = getenv('GEMINI_API_KEY');
@@ -398,7 +476,7 @@ class PolicyController extends ResourceController
             $record = $this->PolicyModel->find($policyId);
             $uploadedPath = WRITEPATH . 'uploads/policy/policy_pdf/';
             $filePath = $uploadedPath.$record['policy_pdf_file_name'];
-
+            // dd($filePath);
             // Check if the file exists
             if (!file_exists($filePath)) {
                 log_message('info',"Error: File not found at {$filePath}");
@@ -546,7 +624,7 @@ class PolicyController extends ResourceController
 
                     log_message('info', "Extracted and decoded final JSON data successfully.");
 
-                    return ['status'=>"sucess", 'message'=> "Doc read sucess" , 'data'=>$final_data];
+                    return ['status'=>"success", 'message'=> "Doc read sucess" , 'data'=>$final_data];
 
                 } else {
                     log_message('info',"Response structure invalid or no generated text candidate found.");
@@ -564,6 +642,110 @@ class PolicyController extends ResourceController
 
     }
 
+    public function calculateCommission($policyId = null)
+    {
+        log_message('debug', 'calculateCommission() started with policyId: ' . $policyId);
+
+        $record = $this->PolicyModel->select('partner_policy.* , pe.insurer_id , VT.vehicle_type , ipti.insurance_plan_type,')
+                                ->join('partner_enquiry pe', 'pe.id = partner_policy.enquiry_id', 'left')
+                                ->join('vehicle_type VT', 'VT.id = pe.vehicle_type_id', 'left')
+                                ->join('partner_quotation pq', 'pq.id = partner_policy.quotation_id', 'left')
+                                ->join('partner_insurance_plan_type_master ipti', 'ipti.id = pq.insurance_plan_type_id', 'left')
+                                ->where('partner_policy.id', $policyId)
+                                ->first();
+
+        $apiUrl = "https://venbait.in/nhance/dev/getCommission";
+
+        $token = "A7fP3xQ9mD2vT6sR1bW8kJ4yC0gN5zH3uL9pE2rF7cV1tX6hB0qM4dG8nS5aU3jK7";
+
+        $manufactureYear = (int) $record['year_of_manufacture'];
+        $currentYear     = (int) date("Y");
+        $vehicleAge = $currentYear - $manufactureYear;
+
+        $postData = [
+            "department" => "Motor",
+            "policy_business_type" => "retail",
+            "product" => "",
+            "renewal_type" => "fresh",
+            "renewal_sub_type" => "fresh",
+            "vehicle_type" => $record['vehicle_type'],
+            "policy_type" => $record['insurance_plan_type'], 
+            "premium" => $record['premium_amount'],
+            "od_premium" => $record['od'],
+            "tp_premium" => $record['tp'],
+            "cubic_capcity" => $record['cubic_capacity'],
+            "weight" => $record['weight'],
+            "make" => $record['make'],
+            "model" => $record['model'],
+            "manufacture_year" => $record['year_of_manufacture'],
+            "vehicle_age" => $vehicleAge,
+            "date_of_registration" => $record['date_of_registration'],
+            "fuel_type" => $record['fuel_type'],
+            "geo_rto_state" => $record['rto_state_code'],
+            "geo_rto_city" => $record['rto_city_code'],
+            "policy_issue_date" => $record['issued_date'],
+            "insurer_id" => $record['insurer_id']
+        ];
+
+        log_message('debug', 'API Request Payload: ' . json_encode($postData));
+
+        $ch = curl_init($apiUrl);
+
+        curl_setopt($ch, CURLOPT_POST, true);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+
+        // Headers
+        curl_setopt($ch, CURLOPT_HTTPHEADER, [
+            "Content-Type: application/json",
+            "Authorization: Bearer " . $token
+        ]);
+
+        // POST Data
+        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($postData));
+
+        $response = curl_exec($ch);
+        $error = curl_error($ch);
+
+        curl_close($ch);
+
+        if ($error)
+        {
+            log_message('error', 'cURL Error: ' . $error);
+            return ['status'=>"failed", 'message'=> 'cURL Error: ' . $error];
+        } else {
+
+            log_message('debug', 'API Response: ' . $response);
+
+            $result = json_decode($response, true);
+
+            // Optional: Debug API result
+            // print_r($result);
+
+            if (!empty($result) && isset($result['success']) && $result['success'] === true) {
+
+                // Safely extract values
+                $policyData = [
+                    'commission_amount'       => $result['data']['payout'] ?? null,
+                    'commission_applied_rule' => $result['data']['rule']['id'] ?? null,
+                ];
+
+                log_message('debug', 'Updating Policy (ID=75) With: ' . json_encode($policyData));
+
+                // Update record 
+                $this->PolicyModel->update($policyId, $policyData);
+
+                log_message('debug', 'Policy update successful!');
+
+                return ['status'=>"success", 'message'=> "Commission Updated!"];
+
+            } else {
+                log_message('debug', 'calculateCommission() - Invalid API Response');
+
+                return ['status'=>"failed", 'message'=> "Invalid API Response!"];
+            }
+        }
+    }
+
 
 
 
diff --git a/app/Controllers/QuotationController.php b/app/Controllers/QuotationController.php
index 21fb9af..b1dfb40 100644
--- a/app/Controllers/QuotationController.php
+++ b/app/Controllers/QuotationController.php
@@ -6,6 +6,9 @@ use App\Models\QuotationModel;
 use App\Models\EnquiryModel;
 use App\Models\PolicyModel;
 
+use App\Controllers\Jobs ;
+use App\Controllers\JobWorker ;
+
 class QuotationController extends ResourceController
 {
     protected $QuotationModel;
@@ -471,19 +474,22 @@ class QuotationController extends ResourceController
                 // Update enquiry status → Policy Created
                 $this->EnquiryModel->update($quot['enquiry_id'], ['status' => 'Policy Created']);
 
+                Jobs::addJob(['job_name' => 'readFileAndCalculateCommission','payload' => ['policy_id' => $newPolicyId]]);
+                log_message("info",'readFileAndCalculateCommission job pushed');
+
                 // Call helper to create BDS record after creating client,clientPolicy,vehicle records
-                $policyData = $this->PolicyModel->select('partner_policy.*,Q.insurer_id,Q.insurer_branch_id,E.name as client_name,E.mobile as client_mobile,E.email as client_email,E.reg_no,E.vehicle_type_id,A.id as agent_id,A.agent_code')
-                                                ->join('partner_quotation Q', 'Q.id = partner_policy.quotation_id AND Q.status = "Accepted"', 'left')
-                                                ->join('partner_enquiry E', 'E.id = partner_policy.enquiry_id', 'left')
-                                                ->join('partner_agent A', 'A.id = partner_policy.agent_id', 'left')
-                                                ->where('partner_policy.id',$newPolicyId)
-                                                ->first();
-                $bdsLogs = createBDS($policyData, $newPolicyId);
-                if (!empty($bdsLogs)) {
-                    foreach ($bdsLogs as $msg) {
-                        log_message('info', '[BDS Entry] ' . $msg);
-                    }
-                }
+                // $policyData = $this->PolicyModel->select('partner_policy.*,Q.insurer_id,Q.insurer_branch_id,E.name as client_name,E.mobile as client_mobile,E.email as client_email,E.reg_no,E.vehicle_type_id,A.id as agent_id,A.agent_code')
+                //                                 ->join('partner_quotation Q', 'Q.id = partner_policy.quotation_id AND Q.status = "Accepted"', 'left')
+                //                                 ->join('partner_enquiry E', 'E.id = partner_policy.enquiry_id', 'left')
+                //                                 ->join('partner_agent A', 'A.id = partner_policy.agent_id', 'left')
+                //                                 ->where('partner_policy.id',$newPolicyId)
+                //                                 ->first();
+                // $bdsLogs = createBDS($policyData, $newPolicyId);
+                // if (!empty($bdsLogs)) {
+                //     foreach ($bdsLogs as $msg) {
+                //         log_message('info', '[BDS Entry] ' . $msg);
+                //     }
+                // }
             }
 
 
diff --git a/app/Helpers/common_helper.php b/app/Helpers/common_helper.php
index 8514c03..a600be3 100644
--- a/app/Helpers/common_helper.php
+++ b/app/Helpers/common_helper.php
@@ -185,3 +185,18 @@ if (!function_exists('format_date_for_client')) {
         return null;
     }
 }
+
+
+if (!function_exists('generate_uuid')) {
+    function generate_uuid($version = 4, $format = 'hex')
+    {
+        $data = random_bytes(16);
+        // Set version to 0100
+        $data[6] = chr(ord($data[6]) & 0x0f | 0x40);
+        // Set bits 6-7 to 10
+        $data[8] = chr(ord($data[8]) & 0x3f | 0x80);
+        // Output the 36 character UUID.
+        $uuid = vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
+        return $uuid;
+    }
+}
diff --git a/app/Models/EnquiryModel.php b/app/Models/EnquiryModel.php
index 08113f6..f292c73 100644
--- a/app/Models/EnquiryModel.php
+++ b/app/Models/EnquiryModel.php
@@ -51,7 +51,9 @@ class EnquiryModel extends Model
                                 P.policy_number,
                                 P.id as policy_id,
                                 P.policy_pdf_file_name,
-                                PB.name as broker_name',
+                                PB.name as broker_name,
+                                pm.id as payment_mode_id , 
+                                pm.value as payment_mode_value'
                             )
                 ->join('vehicle_type VT', 'VT.id = partner_enquiry.vehicle_type_id', 'left')
                 ->join('partner_agent A', 'A.id = partner_enquiry.agent_id', 'left')
@@ -60,6 +62,7 @@ class EnquiryModel extends Model
                 ->join('insurers I', 'I.id = partner_enquiry.insurer_id', 'left')
                 ->join('partner_policy P', 'P.quotation_id = Q.id', 'left')
                 ->join('partner_brokers PB', 'PB.id = partner_enquiry.broker_id', 'left')
+                ->join('partner_payment_mode_master pm', 'pm.id = Q.payment_mode_id', 'left')
                 ->where('partner_enquiry.is_active', 1)
                 ->orderBy('partner_enquiry.created_on', 'ASC');
 
diff --git a/app/Models/JobModel.php b/app/Models/JobModel.php
new file mode 100755
index 0000000..8a98b64
--- /dev/null
+++ b/app/Models/JobModel.php
@@ -0,0 +1,20 @@
+