From f9d6b761abbaf3b5859cc9088f08e48a707949df Mon Sep 17 00:00:00 2001 From: venba-Inspriron-3558 Date: Wed, 19 Nov 2025 11:00:44 +0530 Subject: [PATCH] CHANGE_invoicePolicyMapping --- app/Config/Routes.php | 5 +- app/Controllers/PayoutController.php | 268 ++++- .../PolicyTransactionController.php | 14 - app/Models/InvoiceItemModel.php | 25 + app/Models/InvoiceModel.php | 55 +- app/Views/invoice_policy_mapping.php | 970 ++++++++++++++++++ app/Views/invoice_policy_mapping_add.php | 543 ++++++++++ app/Views/payout_list.php | 17 +- 8 files changed, 1873 insertions(+), 24 deletions(-) create mode 100644 app/Views/invoice_policy_mapping.php create mode 100755 app/Views/invoice_policy_mapping_add.php diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 634252a7..4f0580df 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -480,7 +480,6 @@ $routes->group("rfq", ["filter" => "authMVC"], function ($routes) { $routes->get("driveListFiles", "GoogleDriveController::listFiles"); $routes->post('dmsSearch', 'PolicyTransactionController::dmsSearch', ['filter' => 'authMVC']); $routes->get('dmsSearch', 'PolicyTransactionController::dmsSearch', ['filter' => 'authMVC']); -$routes->get('payouts', 'PolicyTransactionController::payouts', ['filter' => 'authMVC']); $routes->get('downloadGdriveFile', 'GoogleDriveController::downloadGdriveFile', ['filter' => 'authMVC']); $routes->get('cli/sendZeptoMail', 'MasterController::testZeptoSMTP'); @@ -774,6 +773,10 @@ $routes->group('payout', function($routes) { $routes->post('fetchUtrDetails',"PayoutController::fetchUtrDetails"); $routes->post('saveUtrDetails',"PayoutController::saveUtrDetails"); $routes->post('removeUtrDetails',"PayoutController::removeUtrDetails"); + // invoice policy mapping + $routes->get('invoices', 'PayoutController::invoices'); + $routes->post('invoices/save', 'PayoutController::saveInvoice'); + $routes->get('invoices/history', 'PayoutController::auditHistory'); }); //PARTNER COMMISSION diff --git a/app/Controllers/PayoutController.php b/app/Controllers/PayoutController.php index 02bbe1b2..5c86ff39 100644 --- a/app/Controllers/PayoutController.php +++ b/app/Controllers/PayoutController.php @@ -9,6 +9,7 @@ use App\Models\InvoiceItemModel; use App\Models\InvoiceModel; use App\Models\InvoiceUtrModel; use App\Models\PolicyTransactionModel; +use App\Models\AuditHistoryModel; class PayoutController extends BaseController { @@ -20,21 +21,23 @@ class PayoutController extends BaseController protected $policyTransactionModel; protected $payout_status; + protected $auditHistory; + public function __construct() { set_session_context('PayoutController'); $this->myLogger = \Config\Services::mylogger(); $this->payout_status = [ - 1 => "Draft", - 2 => "Pending", - 3 => "Complete", + 1 => "Pending", + 2 => "Complete", ]; $this->invoiceItemModel = new InvoiceItemModel(); $this->invoiceModel = new InvoiceModel(); $this->invoiceUtrModel = new InvoiceUtrModel(); $this->policyTransactionModel = new PolicyTransactionModel(); + $this->auditHistory = new AuditHistoryModel(); } public function payoutList() @@ -189,4 +192,263 @@ class PayoutController extends BaseController } + /*************************************************************************************************************/ + //... Payout-invoice Mapping Commission's amount and Adjustment's Amount - Data Display + public function invoices() + { + + $type = $this->request->getGet('type'); + + $title = $type === 'add' ? 'Add Invoices' + : ($type === 'edit' ? 'Edit Invoices' + : ($type === 'adjustment' ? 'Adjustment Invoices' + : 'Invoices')); + + $data['tab_name'] = $title; + $data['page_name'] = $title; + + $id = $this->request->getGet('id'); + + + $data['agents'] = $this->invoiceModel->agentList(); // common both add and edit + // $data['checked_policy_numbers'] = []; + // $data['invoice'] = []; + // $data['extra_payouts'] = []; + + //... Now Seperated add => 'policy_transaction_payouts1' + //... Now Seperated edit and adjustment => 'policy_transaction_payouts' old file + //... Reason : Due Datatable issues Export button Searching like that so seperated + if ($type === 'add') { + $invoiceNo = $this->generateInvoiceNumber(); + $data['payouts'] = $this->invoiceModel->payoutList(1); + $data['invoice_number'] = $invoiceNo; + return $this->loadLayout('invoice_policy_mapping_add', $data); + } + + if (($type === 'edit' || $type === 'adjustment') && !empty($id)) { + + $invoice = $this->invoiceModel->where('id', $id)->first(); + $data['freeze_edit'] = $this->auditHistory->where('table_name', 'partner_invoice')->where('pk', $id)->countAllResults(); + + $agentId = $invoice['agent_id'] ?? null; + + $data['payouts'] = $this->invoiceModel->payoutList(2 ,$agentId,$id); + $data['extra_payouts'] = $agentId ? $this->invoiceModel->payoutList(3, $agentId) : []; + + $invoice_items = $this->invoiceItemModel->where('invoice_id', $id)->findAll(); + + if (!$invoice) { return redirect()->to('payout/invoices')->with('error', 'Invoice not found'); } + + $data['invoice'] = $invoice; + $data['invoice_items'] = $invoice_items; + // Initialize array for policy numbers + $data['checked_policy_numbers'] = array_column(array_filter($invoice_items, fn($ii) => isset($ii['is_active']) && $ii['is_active'] == 1),'policy_no'); + + $data['invoice_number']= $invoice['invoice_no']; + $data['type'] = $type; + + return $this->loadLayout('invoice_policy_mapping', $data); + + } + + + } + + //... Payout-invoice Mapping - Save/update/soft Delete/Hard Delete Data + public function saveInvoice() + { + $json = $this->request->getJSON(true); + + if (!$json) { + return $this->response->setJSON(['error' => 'Invalid JSON','message' => 'Invalid JSON received.'])->setStatusCode(400); + } + + $id = $json['invoice_id'] ?? null; + try { + + //... ADD Part + if (empty($id)) { + + $invoiceData = [ + 'invoice_no' => $json['invoice_no'], + 'agent_id' => $json['agent_id'], + 'invoice_date' => $json['invoice_date'], + 'invoice_amount' => $json['invoice_amount'], + 'payout_status' => 1 + ]; + + $invoiceId = $this->invoiceModel->insert($invoiceData); + + foreach ($json['policies'] as $p) { + $this->invoiceItemModel->insert([ + 'invoice_id' => $invoiceId, + 'policy_id' => $p['policy_id'], + 'policy_no' => $p['policy_no'], + 'commission_amount' => $p['commission_amount'], + 'is_active' => 1 + ]); + } + + $message = "Invoice created successfully.\nInvoice No: " . $json['invoice_no']; + + } + + // ... EDIT part + if (!empty($id)) { + + $invoiceId = $id; + + $invoiceData = [ + 'invoice_no' => $json['invoice_no'], + 'agent_id' => $json['agent_id'], + 'invoice_date' => $json['invoice_date'], + 'invoice_amount' => $json['invoice_amount'], + ]; + + $this->invoiceModel->update($invoiceId, $invoiceData); + + //... Fetch existing invoice item rows + $existingItems = $this->invoiceItemModel + ->where('invoice_id', $invoiceId) + ->findAll(); + + //... Create map by policy_no + $existingMap = []; + foreach ($existingItems as $item) { + $existingMap[$item['policy_no']] = $item; + } + + $newPolicyNos = []; + + //... Loop new JSON policies + foreach ($json['policies'] as $p) { + + $newPolicyNos[] = $p['policy_no']; + + if (isset($existingMap[$p['policy_no']])) { + + //... Update existing item + $this->invoiceItemModel + ->where('id', $existingMap[$p['policy_no']]['id']) + ->set([ + 'commission_amount' => $p['commission_amount'], + 'is_active' => 1 + ]) + ->update(); + + } else { + + //... Insert new item + $this->invoiceItemModel->insert([ + 'invoice_id' => $invoiceId, + 'policy_id' => $p['policy_id'], + 'policy_no' => $p['policy_no'], + 'commission_amount' => $p['commission_amount'], + 'is_active' => 1, + ]); + } + } + + //... Delete items removed in JSON (hard delete) + foreach ($existingItems as $old) { + if (!in_array($old['policy_no'], $newPolicyNos)) { + $this->invoiceItemModel + ->where('id', $old['id']) + ->delete(); + } + } + //... Delete items removed in JSON (soft delete REF : SVM ) + // foreach ($existingItems as $old) { + // if (!in_array($old['policy_no'], $newPolicyNos)) { + // $this->invoiceItemModel + // ->where('id', $old['id']) + // ->set(['is_active' => 0]) + // ->update(); + // } + // } + + $message = "Invoice updated successfully."; + + } + + return $this->response->setJSON([ + 'status' => 'success', + 'message' => $message, + 'invoice_id' => $invoiceId + ]); + + } catch (\Exception $e) { + + return $this->response->setJSON([ + 'status' => 'error', + 'message' => 'Unexpected error occurred: ' . $e->getMessage() + ]); + } + } + + + + + //... Payout-invoice Mapping - Invoice number is auto-generated only for the Add mode. + // Note: It will change each time the page is reloaded.. (REF:MGW) + private function generateInvoiceNumber() + { + $year = date('Y'); + $month = date('m'); + + do { + // random 3-digit number + $random = str_pad(rand(1, 999), 3, '0', STR_PAD_LEFT); + $invoiceNo = "INV{$year}{$month}{$random}"; + + // check main invoice table + $existsMain = $this->invoiceModel + ->where('invoice_no', $invoiceNo) + ->first(); + + // check partner invoice table + $existsPartner = $this->invoiceModel + ->where('invoice_no', $invoiceNo) + ->first(); + + } while ($existsMain || $existsPartner); // regenerate if duplicate found + + return $invoiceNo; + } + + //... Payout-invoice Mapping Audit History Based on "Adjustment" value (REF: KV,SVM) + public function auditHistory() + { + + + $iid = $this->request->getGet('id'); + + $details['invoice'] = $this->auditHistory + ->select('auditing_history.*,partner_invoice.invoice_no, user_profiles.first_name as created_name') + ->join('user_profiles', 'user_profiles.id = auditing_history.created_by', 'left') + ->join('partner_invoice', 'partner_invoice.id = auditing_history.pk', 'left') + ->where('auditing_history.table_name', 'partner_invoice') // ok + ->where('auditing_history.pk', $iid) + ->orderBy('auditing_history.created_at', 'desc') + ->get() + ->getResultArray(); + + $details['invoice_child'] = $this->auditHistory + ->select('auditing_history.*,partner_invoice.invoice_no, user_profiles.first_name as created_name') + ->join('user_profiles', 'user_profiles.id = auditing_history.created_by', 'left') + ->join('partner_invoice_items', 'partner_invoice_items.id = auditing_history.pk', 'left') + ->join('partner_invoice', 'partner_invoice.id = partner_invoice_items.invoice_id', 'left') + ->where('auditing_history.table_name', 'partner_invoice_items') // FIXED + ->where('partner_invoice.id', $iid) + ->orderBy('auditing_history.created_at', 'desc') + ->get() + ->getResultArray(); + + return $this->response->setJSON([ + 'status' => 'success', + 'data' => $details + ]); + + } + } diff --git a/app/Controllers/PolicyTransactionController.php b/app/Controllers/PolicyTransactionController.php index 8d24f27b..a2f88d5f 100644 --- a/app/Controllers/PolicyTransactionController.php +++ b/app/Controllers/PolicyTransactionController.php @@ -2811,20 +2811,6 @@ $this->loadLayout('dms_search', $data); } - public function payouts() - { - - $data['tab_name'] = 'Payouts'; - $data['page_name'] = 'Payouts'; - $data['payouts'] = []; - $data['agents'] = [ 1 => "Agent 1", 2 => "Agent 2", 3 => "Agent 3", 4 => "Agent 4", 5 => "Agent 5", 6 => "Agent 6", 7 => "Agent 7", 8 => "Agent 8"]; - $data['brokers'] = []; - - if ($this->request->is('post')) {} - if ($this->request->is('get')) {} - - $this->loadLayout('policy_transaction_payouts', $data); - } //--------------------------------------------------------------------------------------------------- public function getCoShareStatementDetails($pt_id) diff --git a/app/Models/InvoiceItemModel.php b/app/Models/InvoiceItemModel.php index 328be1d9..2533dd0f 100644 --- a/app/Models/InvoiceItemModel.php +++ b/app/Models/InvoiceItemModel.php @@ -38,4 +38,29 @@ class InvoiceItemModel extends Model protected $validationMessages = []; protected $skipValidation = false; + + protected $beforeInsert = ["checkAndAddCreatedByValue"]; + protected $beforeUpdate = ["checkAndUpdateUpdatedByValue"]; + + protected function checkAndAddCreatedByValue(array $data) + { + // Check if 'updated_by' value is null or empty + if (empty($data['data']['created_by'])) { + // Set 'updated_by' value to the current session user ID + $data['data']['created_by'] = get_session_userid(); + } + + return $data; + } + + protected function checkAndUpdateUpdatedByValue(array $data) + { + // Check if 'updated_by' value is null or empty + if (empty($data['data']['updated_by'])) { + // Set 'updated_by' value to the current session user ID + $data['data']['updated_by'] = get_session_userid(); + } + + return $data; + } } diff --git a/app/Models/InvoiceModel.php b/app/Models/InvoiceModel.php index 49d91ced..ea5fc4d3 100644 --- a/app/Models/InvoiceModel.php +++ b/app/Models/InvoiceModel.php @@ -29,7 +29,7 @@ class InvoiceModel extends Model protected $useTimestamps = false; protected $createdField = 'created_at'; protected $updatedField = 'updated_at'; - + // Validation (optional) protected $validationRules = [ 'invoice_no' => 'required|max_length[100]', @@ -187,4 +187,57 @@ class InvoiceModel extends Model return $data; } + + + public function payoutList($flag, $agentId = null, $invoiceId = null) + { + $builder = $this->db->table('policy_transaction pt') + ->select(' + pt.id, + pt.policy_no AS policyNo, + pt.agent_id AS agentId, + pp.insured_name AS customer, + pp.premium_amount AS premium, + pp.commission_amount AS commission, + pp.issued_date AS date_db, + DATE_FORMAT(pp.issued_date, "%d/%m/%Y") AS date, + pii.id AS invoiceItemId + ') + ->join('partner_policy pp','pt.policy_no = pp.policy_number AND pt.agent_id = pp.agent_id','left') + ->where('pt.is_active',1) + ->where('pt.agent_id IS NOT NULL', null, false); + + if ($flag == 1) { // Add mode + // EXCLUDE all policies that exist in partner_invoice_items + $builder->join('partner_invoice_items pii','pii.policy_no = pt.policy_no','left'); + $builder->where("pt.policy_no NOT IN (SELECT policy_no FROM partner_invoice_items)", null, false); + } + + if ($flag == 2) { // Edit mode + // Policies belonging to a specific invoice + $builder->select('pii.commission_amount as paid_amount'); + $builder->join('partner_invoice_items pii','pii.policy_no = pt.policy_no','inner'); // must exist + $builder->join('partner_invoice pi','pi.id = pii.invoice_id','inner'); // must exist + $builder->where('pii.is_active',1); + if ($invoiceId) { + $builder->where('pi.id', $invoiceId); // only policies of this invoice + } + if ($agentId) { + $builder->where('pt.agent_id', $agentId); + } + } + + if ($flag == 3) { // Extra policies + // Policies not assigned to any invoice + $builder->select('pii.commission_amount as paid_amount'); + $builder->join('partner_invoice_items pii','pii.policy_no = pt.policy_no','left'); + $builder->where('pii.id IS NULL', null, false); + if ($agentId) { + $builder->where('pt.agent_id', $agentId); + } + } + + return $builder->get()->getResultArray(); + } + } diff --git a/app/Views/invoice_policy_mapping.php b/app/Views/invoice_policy_mapping.php new file mode 100644 index 00000000..12d18e6b --- /dev/null +++ b/app/Views/invoice_policy_mapping.php @@ -0,0 +1,970 @@ + + +
+
+
+
+

+ + + + Invoice Details + + + +

+
+
+ +
+
+ + +
+
+ + +
+
+ + + +
+
+ + + +
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+ + +
+

+ Policy Selection + +

+
+ + +
+ + + + + + + + + + + + + + + + +
+ + +
+ + + +
+ +
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
Policy No
Customer
Premium
Policy Issues Date
Commission Amount
Paid Amount
+ + +
+
+
+ Selected Policies + 0 +
+ +
+ Total Commission + ₹0.00 +
+ + +
+ Total Paid Amount + ₹0.00 +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+
+
+
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/app/Views/invoice_policy_mapping_add.php b/app/Views/invoice_policy_mapping_add.php new file mode 100755 index 00000000..43238c83 --- /dev/null +++ b/app/Views/invoice_policy_mapping_add.php @@ -0,0 +1,543 @@ + + + +
+
+
+
+

+ + + + Invoice Details + + + +

+
+
+ +
+
+ + +
+
+ + +
+
+ + + +
+
+ + + +
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+

+ Policy Selection + +

+
+ +
+ + + + +
+ + + + + +
+ +
+ +
+
+
+ + + + + + + + + + + + + + +
Policy No
Customer
Premium
Policy Issues Date
Commission Amount
+
+ +
+
+
+ Selected Policies + 0 +
+ +
+ Total Commission + ₹0.00 +
+ +
+ +
+ + +
+
+
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/app/Views/payout_list.php b/app/Views/payout_list.php index df7d3c79..ff2a36f2 100644 --- a/app/Views/payout_list.php +++ b/app/Views/payout_list.php @@ -182,11 +182,18 @@
-
-
--> +
+
+ +
+
@@ -219,8 +226,8 @@