2007 lines
88 KiB
PHP
2007 lines
88 KiB
PHP
<?php
|
|
|
|
namespace App\Controllers;
|
|
use CodeIgniter\RESTful\ResourceController;
|
|
use App\Models\PolicyModel;
|
|
use App\Models\EnquiryModel;
|
|
use App\Models\QuotationModel;
|
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
|
use PhpOffice\PhpSpreadsheet\IOFactory;
|
|
|
|
class PolicyController extends ResourceController
|
|
{
|
|
protected $PolicyModel;
|
|
protected $QuotationModel;
|
|
protected $EnquiryModel;
|
|
|
|
protected $tier1VehicleTypeMap = [
|
|
|
|
/* ---------------- Two Wheeler ---------------- */
|
|
'two wheeler' => 'Two Wheeler',
|
|
'2 wheeler' => 'Two Wheeler',
|
|
'2w' => 'Two Wheeler',
|
|
'motorcycle' => 'Two Wheeler',
|
|
'bike' => 'Two Wheeler',
|
|
'scooter' => 'Two Wheeler',
|
|
'moped' => 'Two Wheeler',
|
|
|
|
/* ---------------- Four Wheeler ---------------- */
|
|
'four wheeler' => 'Four Wheeler',
|
|
'4 wheeler' => 'Four Wheeler',
|
|
'4w' => 'Four Wheeler',
|
|
'private car' => 'Four Wheeler',
|
|
'car' => 'Four Wheeler',
|
|
'jeep' => 'Four Wheeler',
|
|
|
|
/* ---------------- Goods Vehicle ---------------- */
|
|
'goods vehicle' => 'Goods Vehicle',
|
|
'good vehicle' => 'Goods Vehicle',
|
|
'goods carrier' => 'Goods Vehicle',
|
|
'goods carrying vehicle' => 'Goods Vehicle',
|
|
'cargo vehicle' => 'Goods Vehicle',
|
|
'lorry' => 'Goods Vehicle',
|
|
'truck' => 'Goods Vehicle',
|
|
'transport vehicle goods'=> 'Goods Vehicle',
|
|
|
|
/* ---------------- Commercial Vehicle ---------------- */
|
|
'commercial vehicle' => 'Commercial Vehicle',
|
|
'commercial car' => 'Commercial Vehicle',
|
|
'taxi' => 'Commercial Vehicle',
|
|
'cab' => 'Commercial Vehicle',
|
|
'hire vehicle' => 'Commercial Vehicle',
|
|
'passenger commercial' => 'Commercial Vehicle',
|
|
|
|
/* ---------------- Bus ---------------- */
|
|
'bus' => 'Bus',
|
|
'passenger bus' => 'Bus',
|
|
'school bus' => 'Bus',
|
|
'private bus' => 'Bus',
|
|
'stage carriage' => 'Bus',
|
|
|
|
/* ---------------- Tractor ---------------- */
|
|
'tractor' => 'Tractor',
|
|
'agricultural tractor' => 'Tractor',
|
|
'farm tractor' => 'Tractor',
|
|
];
|
|
|
|
protected $fuelType = [
|
|
'Petrol' => 'Petrol','Diesel' => 'Diesel','CNG' => 'CNG','LPG' => 'LPG',
|
|
];
|
|
|
|
public function __construct()
|
|
{
|
|
$this->PolicyModel = new PolicyModel();
|
|
$this->QuotationModel = new QuotationModel();
|
|
$this->EnquiryModel = new EnquiryModel();
|
|
}
|
|
|
|
// List policies
|
|
public function policyList()
|
|
{
|
|
try {
|
|
$manager_id = $this->request->getGet('manager_id');
|
|
|
|
$data = $this->PolicyModel ->where('manager_id',$manager_id)->findAll();
|
|
|
|
return $this->respond(['status' => 'success', 'code' => 200, 'data' => $data], 200);
|
|
} catch (\Exception $e) {
|
|
return $this->respond(['status' => 'failed', 'code' => 500, 'data' => $e->getMessage()], 500);
|
|
}
|
|
}
|
|
|
|
// Find single policy
|
|
public function findPolicy()
|
|
{
|
|
try {
|
|
$id = $this->request->getGet('id');
|
|
$record = $this->PolicyModel->select('partner_policy.* , ipti.insurance_plan_type,pq.insurance_plan_type_id,pq.insurer_id, i.name as insurer_name,i.short_name as insurer_short_name,Q.payment_mode_id,A.retention_rate as agent_retention_rate,S.retention_rate as manager_retention_rate, pe.vehicle_type_id as enquiry_vehicle_type_id_for_commission,pe.broker_id as enquiry_broker_id_for_commission, pe.reg_no as enquiry_reg_no_for_commission,pe.reg_no as enquiry_reg_no_for_commission')
|
|
->select('a.agent_code,a.name as agent_name')
|
|
->join('partner_quotation pq', 'pq.id = partner_policy.quotation_id', 'left')
|
|
->join('partner_enquiry pe', 'pe.id = partner_policy.enquiry_id', 'left')
|
|
->join('partner_quotation Q', 'Q.enquiry_id = pe.id AND Q.status = "Accepted" ', 'left')
|
|
->join('partner_insurance_plan_type_master ipti', 'ipti.id = pq.insurance_plan_type_id', 'left')
|
|
->join('partner_agent A', 'A.id = partner_policy.agent_id', 'left')
|
|
->join('partner_staff S', 'S.id = partner_policy.manager_id', 'left')
|
|
->join('insurers i', 'i.id = pq.insurer_id', 'left')
|
|
->join('partner_agent a', 'a.id = pe.agent_id', 'left')
|
|
->find((int)$id);
|
|
|
|
$record['issued_date'] = format_date_for_client($record['issued_date']);
|
|
$record['start_date'] = format_date_for_client($record['start_date']);
|
|
$record['end_date'] = format_date_for_client($record['end_date']);
|
|
|
|
if (!$record) {
|
|
return $this->respond(['status' => 'failed', 'code' => 404, 'data' => []], 200);
|
|
}
|
|
return $this->respond(['status' => 'success', 'code' => 200, 'data' => $record], 200);
|
|
|
|
} catch (\Exception $e) {
|
|
return $this->respond(['status' => 'failed', 'code' => 500, 'data' => $e->getMessage()], 500);
|
|
}
|
|
}
|
|
|
|
// Create policy
|
|
public function createPolicy()
|
|
{
|
|
try {
|
|
$data = $this->request->getPost();
|
|
$uploadPath = WRITEPATH . 'uploads/policy/';
|
|
|
|
$policyPdf = $this->request->getFile('policy_pdf_file_name');
|
|
$policyReceipt = $this->request->getFile('policy_payment_receipt_file_name');
|
|
|
|
$pdfFileName = null;
|
|
$receiptFileName = null;
|
|
|
|
// PDF Upload
|
|
if ($policyPdf && $policyPdf->isValid()) {
|
|
$pdfPath = $uploadPath . 'policy_pdf/';
|
|
if (!is_dir($pdfPath)) {
|
|
mkdir($pdfPath, 0777, true);
|
|
}
|
|
$pdfFileName = time() . '_' . $policyPdf->getRandomName();
|
|
$policyPdf->move($pdfPath, $pdfFileName);
|
|
}
|
|
|
|
// Receipt Upload
|
|
if ($policyReceipt && $policyReceipt->isValid()) {
|
|
$receiptPath = $uploadPath . 'policy_payment_receipt/';
|
|
if (!is_dir($receiptPath)) {
|
|
mkdir($receiptPath, 0777, true);
|
|
}
|
|
$receiptFileName = time() . '_' . $policyReceipt->getRandomName();
|
|
$policyReceipt->move($receiptPath, $receiptFileName);
|
|
}
|
|
|
|
//fetch enquiry_id & agent_id
|
|
$quotData = $this->QuotationModel->select('partner_quotation.*,E.agent_id')
|
|
->join('partner_enquiry E', 'E.id = partner_quotation.enquiry_id', 'left')
|
|
->where('partner_quotation.id',$data['quotation_id'])
|
|
->first();
|
|
|
|
$insertData = [
|
|
'enquiry_id' => $quotData['enquiry_id'],
|
|
'quotation_id' => $data['quotation_id'],
|
|
'insured_name' => $data['insured_name'],
|
|
'issued_date' => format_date_for_database($data['issued_date']),
|
|
'start_date' => format_date_for_database($data['start_date']),
|
|
'end_date' => format_date_for_database($data['end_date']),
|
|
'premium_amount' => $data['premium_amount'],
|
|
'policy_number' => $data['policy_number'],
|
|
'payment_mode' => $data['payment_mode'],
|
|
'manager_id' => $data['manager_id'],
|
|
'agent_id' => $quotData['agent_id'],
|
|
'policy_pdf_file_name' => $pdfFileName,
|
|
'policy_payment_receipt_file_name' => $receiptFileName,
|
|
|
|
// newly added fields
|
|
'tp' => $data['tp'] ?? null,
|
|
'od' => $data['od'] ?? null,
|
|
'pa' => $data['pa'] ?? null,
|
|
'cgst' => $data['cgst'] ?? null,
|
|
'sgst' => $data['sgst'] ?? null,
|
|
'igst' => $data['igst'] ?? null,
|
|
'rto_state_code' => $data['rto_state_code'] ?? null,
|
|
'rto_city_code' => $data['rto_city_code'] ?? null,
|
|
'weight' => $data['weight'] ?? null,
|
|
'fuel_type' => $data['fuel_type'] ?? null,
|
|
'date_of_registration' => !empty($data['date_of_registration']) ? format_date_for_database($data['date_of_registration']) : null,
|
|
'year_of_manufacture' => $data['year_of_manufacture'] ?? null,
|
|
'engine_no' => $data['engine_no'] ?? null,
|
|
'chassis_no' => $data['chassis_no'] ?? null,
|
|
'make' => $data['make'] ?? null,
|
|
'model' => $data['model'] ?? null,
|
|
'cubic_capacity' => $data['cubic_capacity'] ?? null,
|
|
'vehicle_type' => $data['vehicle_type'] ?? null,
|
|
'created_by' => $data['created_by']
|
|
];
|
|
|
|
|
|
$this->PolicyModel->insert($insertData);
|
|
$policyId = $this->PolicyModel->getInsertID();
|
|
|
|
//update enquiry status
|
|
$quotationData = $this->QuotationModel->where('id',$data['quotation_id'])->first();
|
|
if (!empty($quotationData)){
|
|
$enquiryArray = ['vehicle_type_id' => $data['vehicle_type_id'] ?? 0 , 'broker_id' => $data['broker_id'] ?? 0 , 'status'=> 'Policy Created' , 'enquiry_status' => 'Completed' ];
|
|
$this->EnquiryModel->update($quotationData['enquiry_id'], $enquiryArray );
|
|
}
|
|
|
|
// 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,partner_policy.insured_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);
|
|
// }
|
|
// }
|
|
|
|
// trigger_email('policy_created', ['policy_id' => $policyId]);
|
|
|
|
return $this->respond(['status' => 'success', 'code' => 200, 'data' => []], 200);
|
|
|
|
} catch (\Exception $e) {
|
|
return $this->respond(['status' => 'failed', 'code' => 500, 'data' => $e->getMessage()], 500);
|
|
}
|
|
}
|
|
|
|
// Update policy
|
|
public function updatePolicy()
|
|
{
|
|
try {
|
|
$data = $this->request->getJSON(true);
|
|
if (!isset($data['id'])) {
|
|
return $this->respond(['status' => 'failed', 'code' => 200, 'data' => 'ID Required'], 200);
|
|
}
|
|
|
|
$id = $data['id'];
|
|
$policy = $this->PolicyModel->find((int)$id);
|
|
if (!$policy) {
|
|
return $this->respond(['status' => 'failed', 'code' => 200, 'data' => 'Data Not Found'], 200);
|
|
}
|
|
// Check rc_no first, then fallback to enquiry_reg_no_for_commission
|
|
// Priority 1: New Form Input ($data)
|
|
// Priority 2: Existing Policy Record ($policy)
|
|
// Priority 3: Original Enquiry Record ($enquiry_reg_no)
|
|
|
|
$final_reg_no = !empty($data['rc_no'])
|
|
? $data['rc_no']
|
|
: (!empty($policy['rc_no'])
|
|
? $policy['rc_no']
|
|
: ($data['enquiry_reg_no_for_commission'] ?? null));
|
|
|
|
$final_payment_mode = !empty($data['payment_mode'])
|
|
? $data['payment_mode']
|
|
: (!empty($policy['payment_mode'])
|
|
? $policy['payment_mode']
|
|
: null);
|
|
|
|
|
|
$updateData = [
|
|
'rc_no' => $final_reg_no,
|
|
'insured_name' => $data['insured_name'] ?? $policy['insured_name'],
|
|
'issued_date' => format_date_for_database($data['issued_date']),
|
|
'start_date' => format_date_for_database($data['start_date']),
|
|
'end_date' => format_date_for_database($data['end_date']),
|
|
'premium_amount' => $data['premium_amount'] ?? $policy['premium_amount'],
|
|
'policy_number' => $data['policy_number'] ?? $policy['policy_number'],
|
|
'payment_mode' => $final_payment_mode,
|
|
'tp' => $data['tp'] ?? null,
|
|
'od' => $data['od'] ?? null,
|
|
'pa' => $data['pa'] ?? null,
|
|
'cgst' => $data['cgst'] ?? null,
|
|
'sgst' => $data['sgst'] ?? null,
|
|
'igst' => $data['igst'] ?? null,
|
|
'rto_state_code' => $data['rto_state_code'] ?? null,
|
|
'rto_city_code' => $data['rto_city_code'] ?? null,
|
|
'weight' => $data['weight'] ?? null,
|
|
'fuel_type' => $data['fuel_type'] ?? null,
|
|
'date_of_registration' => !empty($data['date_of_registration']) ? format_date_for_database($data['date_of_registration']) : null,
|
|
'year_of_manufacture' => $data['year_of_manufacture'] ?? null,
|
|
'engine_no' => $data['engine_no'] ?? null,
|
|
'chassis_no' => $data['chassis_no'] ?? null,
|
|
'make' => $data['make'] ?? null,
|
|
'model' => $data['model'] ?? null,
|
|
'cubic_capacity' => $data['cubic_capacity'] ?? null,
|
|
'vehicle_type' => $data['vehicle_type'] ?? null,
|
|
'broker_name' => $data['broker_name'] ?? null,
|
|
'commission_amount' => $data['commission_amount'] ?? null,
|
|
'updated_by' => $data['updated_by'] ?? null,
|
|
'is_data_accuracy_checked'=> 1
|
|
];
|
|
|
|
|
|
$EnquiryupdateData = [];
|
|
|
|
if (!empty($data['enquiry_broker_id_for_commission'])) {
|
|
$EnquiryupdateData['broker_id'] = $data['enquiry_broker_id_for_commission'];
|
|
}
|
|
|
|
if (!empty($data['enquiry_vehicle_type_id_for_commission'])) {
|
|
$EnquiryupdateData['vehicle_type_id'] = $data['enquiry_vehicle_type_id_for_commission'];
|
|
}
|
|
|
|
if ($final_reg_no) {
|
|
$EnquiryupdateData['reg_no'] = $final_reg_no;
|
|
}
|
|
|
|
if (!empty($data['insured_name'])) {
|
|
$EnquiryupdateData['name'] = $data['insured_name'];
|
|
}
|
|
|
|
|
|
if (!empty($EnquiryupdateData)) {
|
|
$policy = $this->PolicyModel
|
|
->select('enquiry_id')
|
|
->where('id', $id)
|
|
->first();
|
|
|
|
if (!empty($policy['enquiry_id'])) {
|
|
$EnquiryupdateData['updated_by'] = $data['updated_by'];
|
|
$db = \Config\Database::connect();
|
|
$db->table('partner_enquiry')
|
|
->where('id', $policy['enquiry_id'])
|
|
->update($EnquiryupdateData);
|
|
}
|
|
}
|
|
|
|
|
|
$partnerQuotationUpdateData = [];
|
|
if (!empty($data['insurance_plan_type_id'])) {
|
|
|
|
$partnerQuotation = $this->PolicyModel
|
|
->select('quotation_id')
|
|
->where('id', $id)
|
|
->first();
|
|
|
|
$partnerQuotationUpdateData['insurance_plan_type_id'] = $data['insurance_plan_type_id'];
|
|
if ($final_payment_mode) { $partnerQuotationUpdateData['payment_mode_id'] = $final_payment_mode; }
|
|
|
|
|
|
if (!empty($partnerQuotationUpdateData)) {
|
|
$partnerQuotationUpdateData['updated_by'] = $data['updated_by'];
|
|
$db = \Config\Database::connect();
|
|
$db->table('partner_quotation')
|
|
->where('id', $partnerQuotation['quotation_id'])
|
|
->update($partnerQuotationUpdateData);
|
|
}
|
|
|
|
// $updatedQuotation = $db->table('partner_quotation')
|
|
// ->where('id', $partnerQuotation['quotation_id'])
|
|
// ->get()
|
|
// ->getRowArray();
|
|
|
|
}
|
|
|
|
|
|
$uploadPath = WRITEPATH . 'uploads/policy/';
|
|
|
|
// PDF Update
|
|
$policyPdf = $this->request->getFile('policy_pdf_file_name');
|
|
if ($policyPdf && $policyPdf->isValid()) {
|
|
$pdfPath = $uploadPath . 'policy_pdf/';
|
|
if (!is_dir($pdfPath)) {
|
|
mkdir($pdfPath, 0777, true);
|
|
}
|
|
$pdfFileName = time() . '_' . $policyPdf->getRandomName();
|
|
$policyPdf->move($pdfPath, $pdfFileName);
|
|
$updateData['policy_pdf_file_name'] = $pdfFileName;
|
|
}
|
|
|
|
// Receipt Update
|
|
$policyReceipt = $this->request->getFile('policy_payment_receipt_file_name');
|
|
if ($policyReceipt && $policyReceipt->isValid()) {
|
|
$receiptPath = $uploadPath . 'policy_payment_receipt/';
|
|
if (!is_dir($receiptPath)) {
|
|
mkdir($receiptPath, 0777, true);
|
|
}
|
|
$receiptFileName = time() . '_' . $policyReceipt->getRandomName();
|
|
$policyReceipt->move($receiptPath, $receiptFileName);
|
|
$updateData['policy_payment_receipt_file_name'] = $receiptFileName;
|
|
}
|
|
|
|
$this->PolicyModel->update($id, $updateData);
|
|
|
|
|
|
// 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,partner_policy.insured_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,E.broker_id')
|
|
->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',$id)
|
|
->first();
|
|
if($policyData['broker_id'] == 1) //only for nhance
|
|
{
|
|
// $bdsLogs = createBDS($policyData, $id);
|
|
// if (!empty($bdsLogs)) {
|
|
// foreach ($bdsLogs as $msg) {
|
|
// log_message('info', '[BDS Entry] ' . $msg);
|
|
// }
|
|
// }
|
|
}
|
|
|
|
|
|
return $this->respond(['status' => 'success', 'code' => 200, 'data' => []], 200);
|
|
|
|
} catch (\Exception $e) {
|
|
return $this->respond(['status' => 'failed', 'code' => 500, 'data' => $e->getMessage()], 500);
|
|
}
|
|
}
|
|
|
|
public function updatePolicyCommission()
|
|
{
|
|
try {
|
|
$data = $this->request->getJSON(true);
|
|
|
|
if (empty($data['id'])) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 422,
|
|
'data' => 'Policy id is required',
|
|
], 422);
|
|
}
|
|
|
|
if (!isset($data['commission_amount']) || $data['commission_amount'] === '') {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 422,
|
|
'data' => 'commission_amount is required',
|
|
], 422);
|
|
}
|
|
|
|
$policyId = (int) $data['id'];
|
|
$policy = $this->PolicyModel->find($policyId);
|
|
if (!$policy) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 404,
|
|
'data' => 'Policy not found',
|
|
], 404);
|
|
}
|
|
|
|
$commission = (float) $data['commission_amount'];
|
|
if ($commission < 0) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 422,
|
|
'data' => 'commission_amount must be positive',
|
|
], 422);
|
|
}
|
|
|
|
/*
|
|
* Commission-only update endpoint.
|
|
* Keeps the existing policy workflow unchanged and updates only required fields.
|
|
*/
|
|
$updateData = [
|
|
'commission_amount' => number_format($commission, 2, '.', ''),
|
|
'updated_by' => $data['updated_by'] ?? null,
|
|
'updated_on' => date('Y-m-d H:i:s'),
|
|
];
|
|
|
|
if (!$this->PolicyModel->update($policyId, $updateData)) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 422,
|
|
'data' => $this->PolicyModel->errors(),
|
|
], 422);
|
|
}
|
|
|
|
return $this->respond([
|
|
'status' => 'success',
|
|
'code' => 200,
|
|
'data' => [
|
|
'policy_id' => (string) $policyId,
|
|
'commission_amount' => $updateData['commission_amount'],
|
|
'message' => 'Commission updated successfully',
|
|
],
|
|
], 200);
|
|
} catch (\Exception $e) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 500,
|
|
'data' => $e->getMessage(),
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
public function uploadPolicyFile()
|
|
{
|
|
try {
|
|
|
|
$data = $this->request->getPost();
|
|
$uploadPath = WRITEPATH . 'uploads/policy/';
|
|
|
|
$policyPdf = $this->request->getFile('policy_pdf_file_name');
|
|
|
|
$pdfFileName = null;
|
|
|
|
// PDF Upload
|
|
if ($policyPdf && $policyPdf->isValid()) {
|
|
$pdfPath = $uploadPath . 'policy_pdf/';
|
|
if (!is_dir($pdfPath)) {
|
|
mkdir($pdfPath, 0777, true);
|
|
}
|
|
$pdfFileName = time() . '_' . $policyPdf->getRandomName();
|
|
$policyPdf->move($pdfPath, $pdfFileName);
|
|
}
|
|
|
|
//fetch enquiry_id & agent_id
|
|
$quotData = $this->QuotationModel->select('partner_quotation.*,E.agent_id,E.name , VT.vehicle_type')
|
|
->join('partner_enquiry E', 'E.id = partner_quotation.enquiry_id', 'left')
|
|
->join('partner_agent A', 'A.id = E.agent_id', 'left')
|
|
->join('vehicle_type VT', 'VT.id = E.vehicle_type_id', 'left')
|
|
->where('partner_quotation.id',$data['quotation_id'])
|
|
->first();
|
|
|
|
if (!$quotData) {
|
|
return $this->respond(['status' => 'failed', 'code' => 404, 'message' => 'Quotation not found'], 404);
|
|
}
|
|
|
|
// ===== CHECK EXISTING POLICY =====
|
|
$policy = $this->PolicyModel
|
|
->where('enquiry_id', $quotData['enquiry_id'])
|
|
->first();
|
|
|
|
if ($policy)
|
|
{
|
|
|
|
$updateData = [
|
|
'policy_pdf_file_name' => $pdfFileName,
|
|
'updated_by' => $data['updated_by']
|
|
];
|
|
|
|
$this->PolicyModel->update($data['id'], $updateData);
|
|
$policyId = $data['id'];
|
|
|
|
Jobs::addJob(['job_name' => 'readFileAndCalculateCommission','payload' => ['policy_id' => $policyId]]);
|
|
log_message("info",'readFileAndCalculateCommission job pushed');
|
|
|
|
return $this->respond(['status' => 'success', 'code' => 200, 'data' => $policyId ], 200);
|
|
|
|
}
|
|
|
|
if (!isset($data['id'])) {
|
|
|
|
$insertData = [
|
|
'enquiry_id' => $quotData['enquiry_id'],
|
|
'quotation_id' => $data['quotation_id'],
|
|
'insured_name' => $quotData['name'],
|
|
'manager_id' => $data['manager_id'],
|
|
'agent_id' => $quotData['agent_id'],
|
|
'vehicle_type' => $quotData['vehicle_type'],
|
|
'policy_pdf_file_name' => $pdfFileName,
|
|
'created_by' => $data['created_by']
|
|
];
|
|
|
|
$policyId = $this->PolicyModel->insert($insertData);
|
|
|
|
//update enquiry status
|
|
$quotationData = $this->QuotationModel->where('id',$data['quotation_id'])->first();
|
|
if (!empty($quotationData)){
|
|
$enquiryArray = ['status'=> 'Policy Created' , 'enquiry_status' => 'Completed' ];
|
|
$this->EnquiryModel->update($quotationData['enquiry_id'], $enquiryArray );
|
|
}
|
|
|
|
Jobs::addJob(['job_name' => 'readFileAndCalculateCommission','payload' => ['policy_id' => $policyId]]);
|
|
log_message("info",'readFileAndCalculateCommission job pushed');
|
|
|
|
}else{
|
|
|
|
$updateData = [
|
|
'policy_pdf_file_name' => $pdfFileName,
|
|
'updated_by' => $data['updated_by']
|
|
];
|
|
|
|
$this->PolicyModel->update($data['id'], $updateData);
|
|
$policyId = $data['id'];
|
|
|
|
Jobs::addJob(['job_name' => 'readFileAndCalculateCommission','payload' => ['policy_id' => $policyId]]);
|
|
log_message("info",'readFileAndCalculateCommission job pushed');
|
|
|
|
}
|
|
|
|
|
|
return $this->respond(['status' => 'success', 'code' => 200, 'data' => $policyId ], 200);
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
return $this->respond(['status' => 'failed', 'code' => 500, 'data' => $e->getMessage()], 500);
|
|
}
|
|
}
|
|
|
|
// Download policy file
|
|
public function downloadPolicyFile()
|
|
{
|
|
try {
|
|
$policyId = $this->request->getGet('policy_id');
|
|
$fileType = $this->request->getGet('file_type'); // policy_pdf , policy_payment_receipt
|
|
|
|
if (!$policyId || !$fileType) {
|
|
return $this->respond(['status' => 'failed','code' => 400,'data' => 'policy_id and file_type are required'], 200);
|
|
}
|
|
|
|
// Map file_type to DB column and folder
|
|
$fileMap = [
|
|
'policy_pdf' => ['column' => 'policy_pdf_file_name', 'folder' => 'policy_pdf'],
|
|
'policy_payment_receipt'=> ['column' => 'policy_payment_receipt_file_name', 'folder' => 'policy_payment_receipt'],
|
|
];
|
|
|
|
if (!array_key_exists($fileType, $fileMap)) {
|
|
return $this->respond(['status' => 'failed','code' => 400,'data' => 'Invalid file_type'], 200);
|
|
}
|
|
|
|
$fileColumn = $fileMap[$fileType]['column'];
|
|
$folder = $fileMap[$fileType]['folder'];
|
|
|
|
// Fetch record from DB
|
|
$fileRecord = $this->PolicyModel->where('is_active', 1)->find((int)$policyId);
|
|
|
|
if (!$fileRecord || empty($fileRecord[$fileColumn])) {
|
|
return $this->respond([ 'status' => 'failed','code' => 404,'data' => 'File not found in database'], 200);
|
|
}
|
|
|
|
$filePath = WRITEPATH . "uploads/policy/{$folder}/" . $fileRecord[$fileColumn];
|
|
|
|
if (!file_exists($filePath)) {
|
|
return $this->respond(['status' => 'failed','code' => 404,'data' => 'File missing on server'], 200);
|
|
}
|
|
|
|
// Force file download
|
|
return $this->response->download($filePath, null);
|
|
|
|
} catch (\Exception $e) {
|
|
return $this->respond(['status' => 'failed','code' => 500,'message' => $e->getMessage() ], 500);
|
|
}
|
|
}
|
|
|
|
public function PolicyFilePath()
|
|
{
|
|
try {
|
|
$policyId = $this->request->getGet('policy_id');
|
|
$fileType = $this->request->getGet('file_type'); // policy_pdf , policy_payment_receipt
|
|
|
|
if (!$policyId || !$fileType) {
|
|
return $this->respond(['status' => 'failed','code' => 400,'data' => 'policy_id and file_type are required'], 200);
|
|
}
|
|
|
|
// Map file_type to DB column and folder
|
|
$fileMap = [
|
|
'policy_pdf' => ['column' => 'policy_pdf_file_name', 'folder' => 'policy_pdf'],
|
|
'policy_payment_receipt'=> ['column' => 'policy_payment_receipt_file_name', 'folder' => 'policy_payment_receipt'],
|
|
];
|
|
|
|
if (!array_key_exists($fileType, $fileMap)) {
|
|
return $this->respond(['status' => 'failed','code' => 400,'data' => 'Invalid file_type'], 200);
|
|
}
|
|
|
|
$fileColumn = $fileMap[$fileType]['column'];
|
|
$folder = $fileMap[$fileType]['folder'];
|
|
|
|
// Fetch record from DB
|
|
$fileRecord = $this->PolicyModel->where('is_active', 1)->find((int)$policyId);
|
|
|
|
if (!$fileRecord || empty($fileRecord[$fileColumn])) {
|
|
return $this->respond([ 'status' => 'failed','code' => 404,'data' => 'File not found in database'], 200);
|
|
}
|
|
|
|
$filePath = WRITEPATH . "uploads/policy/{$folder}/" . $fileRecord[$fileColumn];
|
|
$publicUrl = base_url("uploads/policy/{$folder}/" . $fileRecord[$fileColumn]);
|
|
|
|
if (!file_exists($filePath)) {
|
|
return $this->respond(['status' => 'failed','code' => 404,'data' => 'File missing on server'], 200);
|
|
}
|
|
|
|
|
|
// return $this->respond(['status' => 'success', 'code' => 200, 'data' => $publicUrl ], 200);
|
|
|
|
// Detect the file mime type
|
|
$mime = mime_content_type($filePath);
|
|
|
|
// Stream file to browser / Flutter
|
|
return $this->response
|
|
->setHeader('Content-Type', $mime)
|
|
->setHeader('Content-Disposition', 'inline; filename="' . $fileRecord[$fileColumn] . '"')
|
|
->setBody(file_get_contents($filePath));
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
return $this->respond(['status' => 'failed','code' => 500,'message' => $e->getMessage() ], 500);
|
|
}
|
|
}
|
|
|
|
public function readFileAndCalculateCommission(array $data)
|
|
{
|
|
$policyId = $data['policy_id'];
|
|
|
|
log_message('debug', 'checkPolicyDoc() started for policy_id: '.$policyId);
|
|
|
|
$readDoc = $this->checkPolicyDoc($policyId);
|
|
|
|
if($readDoc['status'] == 'success')
|
|
{
|
|
|
|
$data = $readDoc['data'];
|
|
|
|
$vehicleType = $data['vehicle']['vehicle_type'] ?? null;
|
|
$fuelType = $data['vehicle']['fuel_type'] ?? null;
|
|
if($vehicleType !== null)
|
|
{
|
|
$vehicleType = $this->postProcessGeminiData($vehicleType,$this->tier1VehicleTypeMap);
|
|
}
|
|
else
|
|
{
|
|
$vehicleType = 'UN_IDEN_DOC';
|
|
}
|
|
if($fuelType !== null)
|
|
{
|
|
$fuelType = $this->postProcessGeminiData($fuelType,$this->fuelType);
|
|
}
|
|
else
|
|
{
|
|
$fuelType = 'UN_IDEN_DOC';
|
|
}
|
|
|
|
//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['broker_name'] = $data['policy']['intermediary_name'] ?? 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'] = $fuelType;
|
|
$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['product'] = $vehicleType;
|
|
$policyData['rc_no'] = $data['vehicle']['reg_no'] ?? null;
|
|
$policyData['insured_name'] = $data['insured']['name'] ?? null;
|
|
$policyData['enquiry_vehicle_type_id_for_commission'] = $data['insured']['name'] ?? null;
|
|
$policyData['enquiry_broker_id_for_commission'] = $data['insured']['name'] ?? null;
|
|
|
|
|
|
|
|
// ->join('partner_enquiry pe', 'pe.id = partner_policy.enquiry_id', 'left')
|
|
|
|
|
|
|
|
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));
|
|
}
|
|
|
|
|
|
return ['checkPolicyDoc' => $readDoc['status'] , 'calculateCommission' => $calculateCommission['status'] ?? 'failed' ];
|
|
}
|
|
|
|
public function checkPolicyDoc($policyId = null , $return = null)
|
|
{
|
|
|
|
try
|
|
{
|
|
|
|
|
|
// Replace with your actual Gemini API key
|
|
$apiKey = getenv('GEMINI_API_KEY');
|
|
// The model to use and the API endpoint
|
|
$model = "gemini-pro";
|
|
$model = getenv('GEMINI_MODEL');
|
|
// $model = "gemini-1.5-pro";
|
|
$url = "https://generativelanguage.googleapis.com/v1beta/models/{$model}:generateContent?key={$apiKey}";
|
|
|
|
$record = $this->PolicyModel->find((int)$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}");
|
|
if($return == true)
|
|
{
|
|
return $this->respond(['status'=>"failed", 'message'=> "File not found at {$filePath}"], 200);
|
|
}else{
|
|
return ['status'=>"failed", 'message'=> "File not found at {$filePath}"];
|
|
}
|
|
}
|
|
|
|
// Get the file's MIME type using the finfo extension
|
|
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
|
$mimeType = finfo_file($finfo, $filePath);
|
|
finfo_close($finfo);
|
|
|
|
// Define supported inline MIME types
|
|
$supportedInlineMimeTypes = ['application/pdf','text/csv'];
|
|
|
|
// Read the file content and encode it to Base64
|
|
$fileContent = file_get_contents($filePath);
|
|
$base64Content = base64_encode($fileContent);
|
|
// The prompt you want to send to the model
|
|
// $prompt = "give me a json with emp data like name,age,dob,mobile and email. only json not any explanations";
|
|
$prompt = "Read the following motor policy pdf document and convert into JSON format as sample specified. Give me only JSON,not any explanations.while pick up premium break up give own damage, third party ,personal accident and taxes as mentioned in JSON format.Notes:vehicle_type should be like Two Wheeler,Four Feeler,Good Vehicle,Bus, Tractor,Commercial Vehicle.rto_state_code is first two char of reg_no and rto_city_code 3rd & 4th char of reg_no and it should be two digit numeric code. Any date should be in mysql date format";
|
|
$prompt .= '"{\"policy\":{\"intermediary_name\":\"\",\"policy_number\":\"\",\"issue_date\":\"\",\"period\":{\"start\":\"\",\"end\":\"\"},\"insurer\":\"\",\"previous_policy_number\":\"\"},\"insured\":{\"name\":\"\",\"father_name\":\"\",\"address\":[\"\"],\"mobile\":\"\",\"id_proofs\":{\"aadhaar\":\"\",\"pan\":\"\"}},\"vehicle\":{\"reg_no\":\"\",\"rto_state_code\":\"\",\"rto_city_code\":\"\",\"weight\":\"\",\"fuel_type\":\"\",\"date_of_registration\":\"\",\"year_of_manufacture\":\"\",\"engine_no\":\"\",\"chassis_no\":\"\",\"make\":\"\",\"model\":\"\",\"year\":\"\",\"cubic_capacity\":\"\",\"vehicle_type\":\"\"},\"rto\":\"\",\"premium\":{\"tp\":0,\"od\":0,\"pa\":0,\"taxes\":{\"cgst\":\"\",\"sgst\":\"\",\"igst\":\"\"},\"total\":0,\"in_words\":\"\"},\"endorsements\":[{\"code\":\"\",\"desc\":\"\"}]}"';
|
|
|
|
$payloadPart = null;
|
|
|
|
// The text part of the prompt
|
|
$text_part = [
|
|
"text" => $prompt
|
|
];
|
|
// Conditionally handle the file upload based on MIME type
|
|
if (in_array($mimeType, $supportedInlineMimeTypes)) {
|
|
// Handle PDF as inline data
|
|
$fileContent = file_get_contents($filePath);
|
|
$base64Content = base64_encode($fileContent);
|
|
$payloadPart = [
|
|
"inlineData" => [
|
|
"mimeType" => $mimeType,
|
|
"data" => $base64Content
|
|
]
|
|
];
|
|
|
|
$content_parts = [
|
|
"parts" => [
|
|
$text_part,
|
|
$payloadPart
|
|
]
|
|
];
|
|
}
|
|
// else {
|
|
// // Handle Excel/CSV using the Files API
|
|
// // echo "Detected unsupported inline MIME type ({$mimeType}). Uploading via Files API...\n";
|
|
// $fileInfo = $this->uploadFileToGemini($filePath, $apiKey); // Pass apiKey
|
|
|
|
// // print_r($fileInfo);
|
|
// // The file part, using the URI from the Files API upload
|
|
// $file_part = [
|
|
// "fileData" => [
|
|
// "fileUri" => $fileInfo['uri'],
|
|
// "mimeType" => $fileInfo['mimeType']
|
|
// ]
|
|
// ];
|
|
|
|
// // The full content array, containing both parts
|
|
// $content_parts = [
|
|
// "parts" => [
|
|
// $text_part,
|
|
// $file_part
|
|
// ]
|
|
// ];
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// The final JSON payload
|
|
$data = [
|
|
"contents" => [
|
|
$content_parts
|
|
]
|
|
];
|
|
|
|
// Encode the data to a JSON string
|
|
$json_data = json_encode($data);
|
|
|
|
// Initialize cURL
|
|
$ch = curl_init($url);
|
|
|
|
// Set cURL options
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); // Set the Content-Type header
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $json_data); // Set the JSON payload
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return the response as a string
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Optional: to bypass SSL verification if needed (not recommended for production)
|
|
|
|
// Execute the cURL request and get the response
|
|
$response = curl_exec($ch);
|
|
|
|
// Check for cURL errors
|
|
if (curl_errno($ch)) {
|
|
$curl_error = curl_error($ch);
|
|
log_message('info',"cURL Error: " . $curl_error);
|
|
if($return == true)
|
|
{
|
|
return $this->respond(['status'=>"failed", 'message'=> "cURL Error: " . $curl_error], 200);
|
|
}else{
|
|
return ['status'=>"failed", 'message'=> "cURL Error: " . $curl_error];
|
|
}
|
|
}
|
|
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
|
|
// Close the cURL handle
|
|
curl_close($ch);
|
|
$ch = null; // Mark handle as closed
|
|
// Check for non-successful HTTP status codes
|
|
if ($http_code < 200 || $http_code >= 300) {
|
|
log_message('info',"API returned non-successful HTTP status code: $http_code. Response: " . substr($response, 0, 200));
|
|
if($return == true)
|
|
{
|
|
return $this->respond(['status'=>"failed", 'message'=> "API returned non-successful HTTP status code: $http_code. Response: " . substr($response, 0, 200)], 200);
|
|
}else{
|
|
return ['status'=>"failed", 'message'=> "API returned non-successful HTTP status code: $http_code. Response: " . substr($response, 0, 200)];
|
|
}
|
|
}
|
|
|
|
// Decode the JSON response
|
|
$responseData = json_decode($response, true, 512, JSON_THROW_ON_ERROR);
|
|
$text_path = $responseData['candidates'][0]['content']['parts'][0]['text'] ?? null;
|
|
|
|
if ($text_path) {
|
|
$generatedText = $text_path;
|
|
log_message('info', "Successfully received generated text.");
|
|
|
|
// 9. Attempt to extract and decode the exact JSON from the generated text
|
|
$json_string = '';
|
|
|
|
// Preferred: Regex to find content inside a JSON markdown block: ```json\n(.*?)\n```
|
|
$extracted_json_match = [];
|
|
if (preg_match('/```json\s*(.*?)\s*```/s', $generatedText, $extracted_json_match)) {
|
|
$json_string = trim($extracted_json_match[1]);
|
|
} else {
|
|
// Fallback: Find the first '{' and the last '}'
|
|
$start = strpos($generatedText, '{');
|
|
$end = strrpos($generatedText, '}');
|
|
if ($start !== false && $end !== false && $end > $start) {
|
|
$json_string = substr($generatedText, $start, $end - $start + 1);
|
|
}
|
|
}
|
|
|
|
if (empty($json_string)) {
|
|
log_message('info',"Could not extract a valid JSON string from the generated text.");
|
|
if($return == true)
|
|
{
|
|
return $this->respond(['status'=>"failed", 'message'=> "Could not extract a valid JSON string from the generated text."], 200);
|
|
}else{
|
|
return ['status'=>"failed", 'message'=> "Could not extract a valid JSON string from the generated text."];
|
|
}
|
|
}
|
|
|
|
// Decode the extracted JSON string
|
|
$final_data = json_decode($json_string, true, 512, JSON_THROW_ON_ERROR);
|
|
|
|
log_message('info', "Extracted and decoded final JSON data successfully.");
|
|
|
|
if($return == true)
|
|
{
|
|
return $this->respond(['status'=>"success", 'message'=> "Doc read sucess" , 'data'=>$final_data], 200);
|
|
}else{
|
|
return ['status'=>"success", 'message'=> "Doc read sucess" , 'data'=>$final_data];
|
|
}
|
|
|
|
|
|
} else {
|
|
log_message('info',"Response structure invalid or no generated text candidate found.");
|
|
if($return == true)
|
|
{
|
|
return $this->respond(['status'=>"failed", 'message'=> "Response structure invalid or no generated text candidate found"], 200);
|
|
}else{
|
|
return ['status'=>"failed", 'message'=> "Response structure invalid or no generated text candidate found"];
|
|
}
|
|
}
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
// if ($ch !== null) {
|
|
// curl_close($ch);
|
|
// }
|
|
log_message('error', "Fatal Error: " . $e->getMessage());
|
|
if($return == true)
|
|
{
|
|
return $this->respond(['status'=>"failed", 'message'=> "Error: " . $e->getMessage()], 200);
|
|
}else{
|
|
return ['status'=>"failed", 'message'=> "Error: " . $e->getMessage()];
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public function calculateCommission($policyId = null , $return = null)
|
|
{
|
|
log_message('debug', 'calculateCommission() started with policyId: ' . $policyId);
|
|
|
|
$record = $this->PolicyModel->select('partner_policy.* , rto_state.rto_state_name as rto_state_code ,pe.insurer_id , VT.vehicle_type as vehicle_type_master , ipti.insurance_plan_type,A.retention_rate as agent_retention_rate,S.retention_rate as manager_retention_rate')
|
|
->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')
|
|
->join('rto_master rto_state', 'rto_state.rto_state = partner_policy.rto_state_code', 'left')
|
|
// ->join('rto_master rto_city', 'rto_city.rto_code = partner_policy.rto_city_code', 'left')
|
|
->join('partner_agent A', 'A.id = partner_policy.agent_id', 'left')
|
|
->join('partner_staff S', 'S.id = partner_policy.manager_id', 'left')
|
|
->where('partner_policy.id', $policyId)
|
|
->first();
|
|
|
|
$apiUrl = getenv('COMMISSION_CALCULATION_URL');
|
|
|
|
$token = getenv('COMMISSION_CALCULATION_TOKEN');
|
|
|
|
$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_capacity" => $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);
|
|
if($return == true)
|
|
{
|
|
return $this->respond( ['status'=>"failed", 'message'=> 'cURL Error: ' . $error], 200);
|
|
}else{
|
|
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($return == true)
|
|
{
|
|
return $this->respond(['status' => 'success', 'code' => 200, 'data' => $result , 'payload' => $postData ], 200);
|
|
}
|
|
|
|
if (!empty($result) && isset($result['success']) && $result['success'] === true) {
|
|
|
|
|
|
|
|
$actualCommission = $result['data']['payout'];
|
|
$agentRetention = $record['agent_retention_rate'];
|
|
$managerRetention = $record['manager_retention_rate'];
|
|
$commissionDeduction = $actualCommission * ($agentRetention+$managerRetention) / 100;
|
|
$commission = $actualCommission - $commissionDeduction;
|
|
|
|
|
|
// Safely extract values
|
|
$policyData = [
|
|
'commission_from_insurer' => $result['data']['payout'] ?? null,
|
|
'agent_retention_rate' => $agentRetention,
|
|
'manager_retention_rate' => $managerRetention,
|
|
'commission_amount' => $commission,
|
|
'commission_applied_rule' => $result['data']['rule']['id'] ?? null,
|
|
];
|
|
|
|
|
|
log_message('debug', 'Updating Policy (ID=75) With: ' . json_encode($policyData));
|
|
|
|
if($return == true)
|
|
{
|
|
return $this->respond(['status' => 'success', 'code' => 200, 'data' => $policyData ], 200);
|
|
}else{
|
|
// 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');
|
|
|
|
if($return == true)
|
|
{
|
|
return $this->respond( ['status'=>"failed", 'message'=> "Invalid API Response!"], 200);
|
|
}else{
|
|
return ['status'=>"failed", 'message'=> "Invalid API Response!"];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public function policyCommissionCalculationAndGeminiPolicyRead()
|
|
{
|
|
|
|
$type = $this->request->getGet('type');
|
|
$policyId = $this->request->getGet('policy_id');
|
|
|
|
if($type == 'read')
|
|
{
|
|
$readDoc = $this->checkPolicyDoc($policyId , false);
|
|
if($readDoc['status'] == 'success')
|
|
{
|
|
|
|
$data = $readDoc['data'];
|
|
|
|
$vehicleType = $data['vehicle']['vehicle_type'] ?? null;
|
|
$fuelType = $data['vehicle']['fuel_type'] ?? null;
|
|
if($vehicleType !== null)
|
|
{
|
|
$vehicleType = $this->postProcessGeminiData($vehicleType,$this->tier1VehicleTypeMap);
|
|
}
|
|
else
|
|
{
|
|
$vehicleType = 'UN_IDEN_DOC';
|
|
}
|
|
if($fuelType !== null)
|
|
{
|
|
$fuelType = $this->postProcessGeminiData($fuelType,$this->fuelType);
|
|
}
|
|
else
|
|
{
|
|
$fuelType = 'UN_IDEN_DOC';
|
|
}
|
|
|
|
//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['broker_name'] = $data['policy']['intermediary_name'] ?? 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'] = $fuelType;
|
|
$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['product'] = $vehicleType;
|
|
$policyData['rc_no'] = $data['vehicle']['reg_no'] ?? null;
|
|
$policyData['insured_name'] = $data['insured']['name'] ?? null;
|
|
|
|
log_message('debug', 'Policy Update Payload: ' . json_encode($policyData));
|
|
|
|
$updateStatus = $this->PolicyModel->update($policyId,$policyData);
|
|
|
|
} else {
|
|
log_message('error', 'checkPolicyDoc returned failure: ' . json_encode($readDoc));
|
|
}
|
|
|
|
return $this->respond(['status'=>$readDoc['status'], 'data'=> $readDoc ], 200);
|
|
|
|
|
|
}else if($type == 'commission')
|
|
{
|
|
return $this->calculateCommission($policyId , true);
|
|
}
|
|
|
|
}
|
|
|
|
public function searchThePolicies()
|
|
{
|
|
|
|
try{
|
|
|
|
$policy_number = $this->request->getGet('policy_number');
|
|
$vehicle_no = $this->request->getGet('vehicle_number');
|
|
if ($policy_number == '' && $vehicle_no == '') {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 200,
|
|
'data' => 'Value Required'
|
|
], 200);
|
|
}
|
|
|
|
$builder = $this->PolicyModel->select('partner_policy.*');
|
|
$builder->join('partner_enquiry pe', 'partner_policy.enquiry_id = pe.id', 'left');
|
|
|
|
if ($policy_number) {
|
|
$builder->like('partner_policy.policy_number', $policy_number);
|
|
} elseif ($vehicle_no) {
|
|
$builder->like('pe.reg_no', $vehicle_no);
|
|
} else {
|
|
$builder->groupStart()
|
|
->like('partner_policy.policy_number', $policy_number)
|
|
->orLike('pe.reg_no', $vehicle_no)
|
|
->groupEnd();
|
|
}
|
|
$result = $builder->get()->getResultArray();
|
|
if (!$result) {
|
|
return $this->respond(['status' => 'failed', 'code' => 200, 'data' => 'No Data Found'], 200);
|
|
}
|
|
|
|
return $this->respond(['status' => 'success', 'code' => 200, 'data' => $result], 200);
|
|
|
|
} catch (\Exception $e) {
|
|
return $this->respond(['status' => 'failed', 'code' => 500, 'data' => $e->getMessage()], 500);
|
|
}
|
|
}
|
|
|
|
public function postProcessGeminiData(string $incoming, array $masterArray): string
|
|
{
|
|
|
|
$value = strtolower(trim($incoming));
|
|
$value = preg_replace('/\s+/', ' ', $value); // normalize spaces
|
|
|
|
return $masterArray[$value] ?? 'UN_IDEN_TYPE';
|
|
}
|
|
|
|
public function calculateCommissionRequest()
|
|
{
|
|
$postRequest = $this->request->getJSON(true);
|
|
|
|
$apiUrl = getenv('COMMISSION_CALCULATION_URL');
|
|
|
|
$token = getenv('COMMISSION_CALCULATION_TOKEN');
|
|
|
|
$manufactureYear = (int) $postRequest['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" => $postRequest['vehicle_type'],
|
|
"policy_type" => $postRequest['insurance_plan_type'],
|
|
"premium" => $postRequest['premium_amount'],
|
|
"od_premium" => $postRequest['od'],
|
|
"tp_premium" => $postRequest['tp'],
|
|
"cubic_capacity" => $postRequest['cubic_capacity'],
|
|
"weight" => $postRequest['weight'],
|
|
"make" => $postRequest['make'],
|
|
"model" => $postRequest['model'],
|
|
"manufacture_year" => $postRequest['year_of_manufacture'],
|
|
"vehicle_age" => $vehicleAge,
|
|
"date_of_registration" => $postRequest['date_of_registration'],
|
|
"fuel_type" => $postRequest['fuel_type'],
|
|
"geo_rto_state" => $postRequest['rto_state_code'],
|
|
"geo_rto_city" => $postRequest['rto_city_code'],
|
|
"policy_issue_date" => $postRequest['issued_date'],
|
|
"insurer_id" => $postRequest['insurer_id'],
|
|
"payment_mode" => $postRequest['payment_mode']
|
|
];
|
|
|
|
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 $this->respond( ['status'=>"failed", 'message'=> 'cURL Error: ' . $error], 200);
|
|
|
|
} else {
|
|
|
|
log_message('debug', 'API Response: ' . $response);
|
|
|
|
$result = json_decode($response, true);
|
|
|
|
|
|
if (!empty($result) && isset($result['success']) && $result['success'] === true) {
|
|
|
|
$actualCommission = $result['data']['payout'];
|
|
$agentRetention = $postRequest['agent_retention_rate'];
|
|
$managerRetention = $postRequest['manager_retention_rate'];
|
|
$commissionDeduction = $actualCommission * ($agentRetention+$managerRetention) / 100;
|
|
$commission = $actualCommission - $commissionDeduction;
|
|
|
|
|
|
// Safely extract values
|
|
$policyData = [
|
|
'commission_from_insurer' => $result['data']['payout'] ?? null,
|
|
'agent_retention_rate' => $agentRetention,
|
|
'manager_retention_rate' => $managerRetention,
|
|
'commission_amount' => $commission,
|
|
'commission_applied_rule' => $result['data']['rule']['id'] ?? null,
|
|
];
|
|
|
|
|
|
log_message('debug', 'Updating Policy (ID=75) With: ' . json_encode($policyData));
|
|
|
|
return $this->respond(['status' => 'success', 'code' => 200, 'data' => $policyData ], 200);
|
|
|
|
} else {
|
|
log_message('debug', 'calculateCommission() - Invalid API Response');
|
|
|
|
return $this->respond( ['status'=>"failed", 'message'=> "Invalid API Response!"], 200);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
public function vehicleTypeMaster()
|
|
{
|
|
// Get only values & make unique
|
|
$vehicleTypes = array_values(array_unique($this->tier1VehicleTypeMap));
|
|
|
|
return $this->respond([
|
|
'status' => 'success',
|
|
'data' => $vehicleTypes
|
|
], 200);
|
|
}
|
|
|
|
public function fuelTypeMaster()
|
|
{
|
|
$fuelTypes = array_values(array_unique($this->fuelType));
|
|
|
|
return $this->respond([
|
|
'status' => 'success',
|
|
'data' => $fuelTypes
|
|
], 200);
|
|
}
|
|
|
|
|
|
public function softdelete()
|
|
{
|
|
try {
|
|
$policyId = (int) $this->request->getGet('policy_id');
|
|
|
|
if (!$policyId) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 400,
|
|
'data' => 'policy_id is required'
|
|
], 400);
|
|
}
|
|
|
|
$policy = $this->PolicyModel->find($policyId);
|
|
|
|
if (!$policy) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 404,
|
|
'data' => 'Data Not Found'
|
|
], 404);
|
|
}
|
|
|
|
// Start DB transaction
|
|
$db = \Config\Database::connect();
|
|
$db->transStart();
|
|
|
|
// Soft delete policy
|
|
$this->PolicyModel->update($policyId, ['is_active' => 0]);
|
|
|
|
// Soft delete quotation
|
|
if (!empty($policy['quotation_id'])) {
|
|
$this->QuotationModel->update(
|
|
(int) $policy['quotation_id'],
|
|
['is_active' => 0]
|
|
);
|
|
}
|
|
|
|
// Soft delete enquiry
|
|
if (!empty($policy['enquiry_id'])) {
|
|
$this->EnquiryModel->update(
|
|
(int) $policy['enquiry_id'],
|
|
['is_active' => 0]
|
|
);
|
|
}
|
|
|
|
$db->transComplete();
|
|
|
|
if ($db->transStatus() === false) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 500,
|
|
'data' => 'Failed to delete data'
|
|
], 500);
|
|
}
|
|
|
|
return $this->respond([
|
|
'status' => 'success',
|
|
'code' => 200,
|
|
'data' => 'Deleted Successfully!'
|
|
], 200);
|
|
|
|
} catch (\Throwable $e) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 500,
|
|
'message' => $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Stream a simple XLSX (title row, header row, data rows) without totals row.
|
|
*/
|
|
private function streamPendingCommissionExcel(array $header, array $data, string $title, string $fileName): void
|
|
{
|
|
while (ob_get_level() > 0) {
|
|
ob_end_clean();
|
|
}
|
|
|
|
$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
|
|
$columnCount = count($header);
|
|
$lastCol = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($columnCount);
|
|
|
|
$sheet->mergeCells("A1:{$lastCol}1");
|
|
$sheet->setCellValue('A1', $title);
|
|
$sheet->getStyle('A1')->getFont()->setBold(true)->setSize(14);
|
|
$sheet->getStyle('A1')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
|
|
|
$sheet->fromArray($header, null, 'A2');
|
|
$sheet->getStyle("A2:{$lastCol}2")->getFont()->setBold(true);
|
|
$sheet->getStyle("A2:{$lastCol}2")->getFill()
|
|
->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
|
|
->getStartColor()->setARGB('F2F2F2');
|
|
|
|
if ($data !== []) {
|
|
$sheet->fromArray($data, null, 'A3');
|
|
}
|
|
|
|
for ($i = 1; $i <= $columnCount; $i++) {
|
|
$col = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($i);
|
|
$sheet->getColumnDimension($col)->setAutoSize(true);
|
|
}
|
|
|
|
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
|
header("Content-Disposition: attachment; filename=\"{$fileName}\"");
|
|
header('Cache-Control: max-age=0');
|
|
|
|
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
|
|
$writer->save('php://output');
|
|
exit();
|
|
}
|
|
|
|
/**
|
|
* GET: from_date, to_date (optional), agent_code (optional) — at least one filter required.
|
|
* Exports policies where commission_amount is NULL or 0 (active policies only).
|
|
*/
|
|
public function downloadPendingCommissionExcel()
|
|
{
|
|
try {
|
|
$fromDate = $this->request->getGet('from_date');
|
|
$toDate = $this->request->getGet('to_date');
|
|
$agentCode = $this->request->getGet('agent_code');
|
|
$agentCode = $agentCode !== null && $agentCode !== '' ? trim((string) $agentCode) : null;
|
|
|
|
if ($fromDate === null || $fromDate === '') {
|
|
$fromDate = null;
|
|
}
|
|
if ($toDate === null || $toDate === '') {
|
|
$toDate = null;
|
|
}
|
|
|
|
if ($fromDate === null && $toDate === null && $agentCode === null) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 400,
|
|
'data' => 'Provide at least one of: from_date, to_date, or agent_code',
|
|
], 400);
|
|
}
|
|
|
|
$db = \Config\Database::connect();
|
|
$builder = $db->table('partner_policy pp');
|
|
$builder->select('pa.agent_code, pp.policy_number');
|
|
$builder->join('partner_agent pa', 'pa.id = pp.agent_id', 'left');
|
|
$builder->where('pp.is_active', 1);
|
|
$builder->groupStart()
|
|
->where('pp.commission_amount', null)
|
|
->orWhere('pp.commission_amount', 0)
|
|
->groupEnd();
|
|
|
|
if ($fromDate !== null) {
|
|
$builder->where('pp.issued_date >=', date('Y-m-d', strtotime((string) $fromDate)));
|
|
}
|
|
if ($toDate !== null) {
|
|
$builder->where('pp.issued_date <=', date('Y-m-d', strtotime((string) $toDate)));
|
|
}
|
|
if ($agentCode !== null) {
|
|
$builder->where('pa.agent_code', $agentCode);
|
|
}
|
|
|
|
$builder->orderBy('pa.agent_code', 'ASC');
|
|
$builder->orderBy('pp.policy_number', 'ASC');
|
|
|
|
$rows = $builder->get()->getResultArray();
|
|
|
|
$dataRows = [];
|
|
foreach ($rows as $row) {
|
|
$dataRows[] = [
|
|
$row['agent_code'] ?? '',
|
|
"`" . ($row['policy_number'] ?? ''), // 👈 force text
|
|
'',
|
|
];
|
|
}
|
|
|
|
$header = ['Agent Code', 'Policy Number', 'Payout Amount'];
|
|
|
|
$fromPart = $fromDate !== null ? date('Y-m-d', strtotime((string) $fromDate)) : 'na';
|
|
$toPart = $toDate !== null ? date('Y-m-d', strtotime((string) $toDate)) : 'na';
|
|
$agentPart = $agentCode !== null
|
|
? preg_replace('/[^A-Za-z0-9_-]+/', '_', $agentCode)
|
|
: 'all_agents';
|
|
$fileName = "commission_pending_{$fromPart}_{$toPart}_{$agentPart}.xlsx";
|
|
|
|
$title = 'Pending commission payout (fill Payout Amount and re-upload)';
|
|
|
|
$this->streamPendingCommissionExcel($header, $dataRows, $title, $fileName);
|
|
} catch (\Throwable $e) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 500,
|
|
'message' => $e->getMessage(),
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* GET: static sample .xlsx for clients (same columns as uploadCommissionExcel).
|
|
* No filters; use downloadPendingCommissionExcel for real pending rows from the database.
|
|
*/
|
|
public function downloadCommissionUploadSampleExcel()
|
|
{
|
|
try {
|
|
$header = ['Agent Code', 'Policy Number', 'Payout Amount'];
|
|
// Example rows — clients replace with real data or delete before upload.
|
|
$dataRows = [
|
|
["AG001", "`YOUR-POLICY-NUMBER-1", "1500.00"],
|
|
["AG002", "`YOUR-POLICY-NUMBER-2", ""],
|
|
];
|
|
$title = 'Sample: Fill Payout Amount, keep Agent Code matching the policy, upload via policy/uploadCommissionExcel';
|
|
$fileName = 'commission_payout_upload_sample.xlsx';
|
|
|
|
$this->streamPendingCommissionExcel($header, $dataRows, $title, $fileName);
|
|
} catch (\Throwable $e) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 500,
|
|
'message' => $e->getMessage(),
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* GET: commission / payout rows with filters. Invoice "raised" = active row in partner_invoice_items for policy_id.
|
|
*
|
|
* Query: from_date, to_date (issued_date), agent_id (partner_policy.agent_id), payout_raised=yes|no|all
|
|
* payout_raised=all: include both invoice-raised and not-raised policies (no EXISTS filter).
|
|
* At least one filter required among: from_date, to_date, agent_id, payout_raised.
|
|
*
|
|
* Response includes summary: total / raised / pending commission sums (commission_amount).
|
|
*
|
|
* List columns also include: reg_no, weight, fuel_type, vehicle_type, utr_no (from partner_invoice_utr via invoice).
|
|
*/
|
|
public function commissionPayoutReport()
|
|
{
|
|
try {
|
|
$fromDate = $this->request->getGet('from_date');
|
|
$toDate = $this->request->getGet('to_date');
|
|
$agentIdRaw = $this->request->getGet('agent_id');
|
|
$payoutRaised = $this->request->getGet('payout_raised');
|
|
|
|
$fromDate = ($fromDate !== null && $fromDate !== '') ? trim((string) $fromDate) : null;
|
|
$toDate = ($toDate !== null && $toDate !== '') ? trim((string) $toDate) : null;
|
|
|
|
$agentId = null;
|
|
if ($agentIdRaw !== null && $agentIdRaw !== '') {
|
|
$agentId = (int) $agentIdRaw;
|
|
}
|
|
|
|
if ($payoutRaised !== null && $payoutRaised !== '') {
|
|
$payoutRaised = strtolower(trim((string) $payoutRaised));
|
|
if (! in_array($payoutRaised, ['yes', 'no', 'all'], true)) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 400,
|
|
'data' => 'payout_raised must be yes, no, or all',
|
|
], 400);
|
|
}
|
|
} else {
|
|
$payoutRaised = null;
|
|
}
|
|
|
|
$hasDateFilter = $fromDate !== null || $toDate !== null;
|
|
$hasPayoutFilter = $payoutRaised !== null;
|
|
if (! $hasDateFilter && $agentId === null && ! $hasPayoutFilter) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 400,
|
|
'data' => 'Provide at least one filter: from_date, to_date, agent_id, or payout_raised',
|
|
], 400);
|
|
}
|
|
|
|
$db = \Config\Database::connect();
|
|
$builder = $db->table('partner_policy pp');
|
|
$builder->select('pa.agent_code, pp.policy_number AS policy_no, pp.premium_amount AS premium, pp.commission_amount, pe.reg_no, pp.weight, pp.fuel_type, pp.vehicle_type');
|
|
$builder->select('COALESCE((SELECT GROUP_CONCAT(piu.utr_no ORDER BY piu.id SEPARATOR ", ") FROM partner_invoice_items pii_utr INNER JOIN partner_invoice pi_u ON pi_u.id = pii_utr.invoice_id AND pi_u.is_active = 1 INNER JOIN partner_invoice_utr piu ON piu.invoice_id = pii_utr.invoice_id AND piu.is_active = 1 WHERE pii_utr.policy_id = pp.id AND pii_utr.is_active = 1), "") AS utr_no', false);
|
|
$builder->select("(CASE WHEN EXISTS (SELECT 1 FROM partner_invoice_items pii INNER JOIN partner_invoice pi ON pi.id = pii.invoice_id AND pi.is_active = 1 WHERE pii.policy_id = pp.id AND pii.is_active = 1) THEN 'yes' ELSE 'no' END) AS received_or_not", false);
|
|
$builder->join('partner_agent pa', 'pa.id = pp.agent_id', 'left');
|
|
$builder->join('partner_enquiry pe', 'pe.id = pp.enquiry_id', 'left');
|
|
$builder->where('pp.is_active', 1);
|
|
|
|
if ($fromDate !== null) {
|
|
$builder->where('pp.issued_date >=', date('Y-m-d', strtotime($fromDate)));
|
|
}
|
|
if ($toDate !== null) {
|
|
$builder->where('pp.issued_date <=', date('Y-m-d', strtotime($toDate)));
|
|
}
|
|
if ($agentId !== null) {
|
|
$builder->where('pp.agent_id', $agentId);
|
|
}
|
|
if ($payoutRaised === 'yes') {
|
|
$builder->where('EXISTS (SELECT 1 FROM partner_invoice_items pii2 INNER JOIN partner_invoice pi2 ON pi2.id = pii2.invoice_id AND pi2.is_active = 1 WHERE pii2.policy_id = pp.id AND pii2.is_active = 1)', null, false);
|
|
} elseif ($payoutRaised === 'no') {
|
|
$builder->where('NOT EXISTS (SELECT 1 FROM partner_invoice_items pii2 INNER JOIN partner_invoice pi2 ON pi2.id = pii2.invoice_id AND pi2.is_active = 1 WHERE pii2.policy_id = pp.id AND pii2.is_active = 1)', null, false);
|
|
}
|
|
// payout_raised=all: no EXISTS / NOT EXISTS filter (both cases).
|
|
|
|
$builder->orderBy('pa.agent_code', 'ASC');
|
|
$builder->orderBy('pp.policy_number', 'ASC');
|
|
|
|
$rows = $builder->get()->getResultArray();
|
|
|
|
$sumTotal = 0.0;
|
|
$sumRaised = 0.0;
|
|
$sumPending = 0.0;
|
|
foreach ($rows as $row) {
|
|
$amt = (float) ($row['commission_amount'] ?? 0);
|
|
$sumTotal += $amt;
|
|
if (($row['received_or_not'] ?? '') === 'yes') {
|
|
$sumRaised += $amt;
|
|
} else {
|
|
$sumPending += $amt;
|
|
}
|
|
}
|
|
|
|
return $this->respond([
|
|
'status' => 'success',
|
|
'code' => 200,
|
|
'data' => $rows,
|
|
'count' => count($rows),
|
|
'summary' => [
|
|
'total' => round($sumTotal, 2),
|
|
'raised' => round($sumRaised, 2),
|
|
'pending' => round($sumPending, 2),
|
|
],
|
|
], 200);
|
|
} catch (\Throwable $e) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 500,
|
|
'message' => $e->getMessage(),
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* POST multipart field: commission_excel (xlsx). Updates partner_policy.commission_amount by policy number.
|
|
*/
|
|
public function uploadCommissionExcel()
|
|
{
|
|
try {
|
|
$file = $this->request->getFile('commission_excel');
|
|
if ($file === null || ! $file->isValid()) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 400,
|
|
'data' => 'commission_excel file is required (xlsx)',
|
|
], 400);
|
|
}
|
|
|
|
$ext = strtolower((string) $file->getClientExtension());
|
|
if ($ext !== 'xlsx') {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 400,
|
|
'data' => 'Only .xlsx files are supported',
|
|
], 400);
|
|
}
|
|
|
|
$spreadsheet = IOFactory::load($file->getTempName());
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
$highestRow = (int) $sheet->getHighestDataRow();
|
|
|
|
$headerRowNum = null;
|
|
for ($r = 1; $r <= min(5, $highestRow); $r++) {
|
|
$a = strtolower(trim((string) $sheet->getCell(Coordinate::stringFromColumnIndex(1) . $r)->getValue()));
|
|
$b = strtolower(trim((string) $sheet->getCell(Coordinate::stringFromColumnIndex(2) . $r)->getValue()));
|
|
if ($a === 'agent code' && str_contains($b, 'policy')) {
|
|
$headerRowNum = $r;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ($headerRowNum === null) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 400,
|
|
'data' => 'Could not find header row (Agent Code, Policy Number)',
|
|
], 400);
|
|
}
|
|
|
|
$db = \Config\Database::connect();
|
|
$db->transStart();
|
|
|
|
$updated = 0;
|
|
$skipped = 0;
|
|
$errors = [];
|
|
|
|
for ($r = $headerRowNum + 1; $r <= $highestRow; $r++) {
|
|
$agentCodeExcel = trim((string) $sheet->getCell('A' . $r)->getFormattedValue());
|
|
$policyNumber = trim((string) $sheet->getCell('B' . $r)->getFormattedValue());
|
|
$payoutRaw = $sheet->getCell('C' . $r)->getCalculatedValue();
|
|
|
|
// 🔥 Best Practice (Final Version)
|
|
// safe removal: single quote from the beginning of the policy number
|
|
if (isset($policyNumber[0]) && $policyNumber[0] === "`") {
|
|
$policyNumber = substr($policyNumber, 1);
|
|
}
|
|
|
|
if ($policyNumber === '') {
|
|
continue;
|
|
}
|
|
|
|
if ($agentCodeExcel === '') {
|
|
$errors[] = [
|
|
'row' => $r,
|
|
'policy_number' => $policyNumber,
|
|
'agent_code' => '',
|
|
'message' => 'Agent code is empty for this policy',
|
|
];
|
|
continue;
|
|
}
|
|
|
|
if ($payoutRaw === null || $payoutRaw === '') {
|
|
$skipped++;
|
|
continue;
|
|
}
|
|
|
|
if (is_numeric($payoutRaw)) {
|
|
$amount = (float) $payoutRaw;
|
|
} else {
|
|
$amount = (float) str_replace([',', ' '], '', (string) $payoutRaw);
|
|
}
|
|
|
|
if ($amount < 0 || is_nan($amount)) {
|
|
$errors[] = [
|
|
'row' => $r,
|
|
'policy_number' => $policyNumber,
|
|
'agent_code' => $agentCodeExcel,
|
|
'message' => 'Invalid payout amount',
|
|
];
|
|
continue;
|
|
}
|
|
|
|
$policy = $db->table('partner_policy pp')
|
|
->select('pp.id, pa.agent_code as db_agent_code')
|
|
->join('partner_agent pa', 'pa.id = pp.agent_id', 'left')
|
|
->where('pp.policy_number', $policyNumber)
|
|
->where('pp.is_active', 1)
|
|
->get()
|
|
->getRowArray();
|
|
|
|
if (! $policy) {
|
|
$errors[] = [
|
|
'row' => $r,
|
|
'policy_number' => $policyNumber,
|
|
'agent_code' => $agentCodeExcel,
|
|
'message' => 'Policy not found or inactive',
|
|
];
|
|
continue;
|
|
}
|
|
|
|
$dbAgentCode = trim((string) ($policy['db_agent_code'] ?? ''));
|
|
if (strcasecmp($dbAgentCode, $agentCodeExcel) !== 0) {
|
|
$errors[] = [
|
|
'row' => $r,
|
|
'policy_number' => $policyNumber,
|
|
'agent_code' => $agentCodeExcel,
|
|
'expected_agent_code' => $dbAgentCode,
|
|
'message' => 'Agent code does not match this policy number',
|
|
];
|
|
continue;
|
|
}
|
|
|
|
$this->PolicyModel->update((int) $policy['id'], ['commission_amount' => $amount]);
|
|
$updated++;
|
|
}
|
|
|
|
$db->transComplete();
|
|
|
|
if ($db->transStatus() === false) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 500,
|
|
'data' => 'Transaction failed',
|
|
], 500);
|
|
}
|
|
|
|
return $this->respond([
|
|
'status' => 'success',
|
|
'code' => 200,
|
|
'data' => [
|
|
'updated_rows' => $updated,
|
|
'skipped_empty_payout' => $skipped,
|
|
'error_count' => count($errors),
|
|
'errors' => $errors,
|
|
],
|
|
], 200);
|
|
} catch (\Throwable $e) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 500,
|
|
'message' => $e->getMessage(),
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* POST JSON: id (partner_policy.id), commission_amount (number or null).
|
|
*/
|
|
public function payoutInilneEditUpdate()
|
|
{
|
|
try {
|
|
$data = $this->request->getJSON(true);
|
|
if (! is_array($data)) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 400,
|
|
'data' => 'Invalid JSON body',
|
|
], 400);
|
|
}
|
|
|
|
if (! isset($data['id']) || $data['id'] === '' || $data['id'] === null) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 400,
|
|
'data' => 'id is required',
|
|
], 400);
|
|
}
|
|
|
|
if (! array_key_exists('commission_amount', $data)) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 400,
|
|
'data' => 'commission_amount is required',
|
|
], 400);
|
|
}
|
|
|
|
$id = (int) $data['id'];
|
|
$policy = $this->PolicyModel->find($id);
|
|
if (! $policy) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 404,
|
|
'data' => 'Data Not Found',
|
|
], 404);
|
|
}
|
|
|
|
$raw = $data['commission_amount'];
|
|
if ($raw === null || $raw === '') {
|
|
$commission = null;
|
|
} elseif (is_numeric($raw)) {
|
|
$commission = (float) $raw;
|
|
} else {
|
|
$clean = str_replace([',', ' '], '', (string) $raw);
|
|
if ($clean === '' || ! is_numeric($clean)) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 400,
|
|
'data' => 'commission_amount must be numeric or null',
|
|
], 400);
|
|
}
|
|
$commission = (float) $clean;
|
|
}
|
|
|
|
if ($commission !== null && ($commission < 0 || is_nan($commission))) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 400,
|
|
'data' => 'commission_amount cannot be negative',
|
|
], 400);
|
|
}
|
|
|
|
$this->PolicyModel->update($id, ['commission_amount' => $commission]);
|
|
|
|
return $this->respond([
|
|
'status' => 'success',
|
|
'code' => 200,
|
|
'data' => [
|
|
'id' => $id,
|
|
'commission_amount' => $commission,
|
|
],
|
|
], 200);
|
|
} catch (\Throwable $e) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'code' => 500,
|
|
'message' => $e->getMessage(),
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|