From 396d9a2949dd1433ddf688af4ca108b5edf6617d Mon Sep 17 00:00:00 2001 From: Venkatesh Date: Sat, 4 Jul 2026 18:34:28 +0530 Subject: [PATCH] FIX_Add from Opportunities fetching only one policy for GMC/GPA/GTLI --- app/Config/Routes.php | 3 +- app/Controllers/LeadsController.php | 244 ++++++++++++++++++++++++++-- app/Views/view_rfq.php | 43 +++-- 3 files changed, 260 insertions(+), 30 deletions(-) diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 7158f0ca..234b82a9 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -554,7 +554,8 @@ $routes->group("leads", ["filter" => "authMVC"], function ($routes) { $routes->post("sendMail", "LeadsController::sendMailWithAttachement"); $routes->get("exportQCRandRFQ/(:any)", "LeadsController::exportQCRandRFQ/$1"); $routes->get("featchLeadDataAndInsertClient/(:any)", "LeadsController::featchLeadDataAndInsertClient/$1"); - $routes->get("featchClientPolicyFromLead/(:any)", "LeadsController::featchClientPolicyFromLead/$1"); + $routes->get("featchClientPolicyFromLead/(:any)", "LeadsController::featchClientPolicyFromLead/$1"); + $routes->get("getLeadPolicyTerms/(:num)", "LeadsController::getLeadPolicyTerms/$1"); }); $routes->group("rfq", ["filter" => "authMVC"], function ($routes) { diff --git a/app/Controllers/LeadsController.php b/app/Controllers/LeadsController.php index 41f4252e..ecc9ed74 100644 --- a/app/Controllers/LeadsController.php +++ b/app/Controllers/LeadsController.php @@ -4129,16 +4129,17 @@ class LeadsController extends BaseController return $this->respond(['status' => false, 'message' => 'Failed to create Client', 'data' => null], 200); } - $result = $this->createClientWithLeadData($data); + $result = $this->createClientWithMatchingLeadsPolicies($data); if ($result) { - $policy_data = $this->clientPolicyModel->where('client_id', $result)->where('is_active', 1)->first(); return $this->respond([ - 'status' => true, - 'message' => 'New Client created successfully', - 'client_id' => $result, - 'data' => $data, - 'client_policy_id' => $policy_data['id'] ?? null, + 'status' => true, + 'message' => 'New Client created successfully', + 'client_id' => $result['client_id'], + 'data' => $data, + 'client_policy_id' => $result['primary_policy_id'], + 'client_policy_ids' => $result['policy_ids'], + 'lead_ids' => $result['lead_ids'], ], 200); } @@ -4150,6 +4151,110 @@ class LeadsController extends BaseController } } + /** + * Create one client + branch + contact from the given lead, then create a policy + * for every active lead that shares the same client_name, client_short_name, + * branch_name and branch_code and does not yet have a policy. + * + * @return array{client_id: int, branch_id: int, primary_policy_id: int|null, policy_ids: int[], lead_ids: int[]}|false + */ + public function createClientWithMatchingLeadsPolicies(array $data) + { + try { + $matchingLeads = $this->getMatchingLeadsForClientInsert($data); + + if (empty($matchingLeads)) { + return false; + } + + $client_id = $this->clientModel->insert($this->prepareClientData($data)); + if (! $client_id) { + return false; + } + + $branch_id = $this->clientBranchModel->insert($this->prepareClientBranchData($data, $client_id)); + if (! $branch_id) { + return false; + } + + $this->levelContactModel->insert($this->prepareContactData($data, $branch_id)); + + $policy_ids = []; + $lead_ids = []; + $primary_policy_id = null; + $primary_lead_id = (int) $data['id']; + + foreach ($matchingLeads as $lead) { + $lead_ids[] = (int) $lead['id']; + $policy_id = $this->createClientPolicyWithLeadData($lead, $client_id, $branch_id); + + // Ensure client link is set even if policy insert fails for a lead. + $this->leadsModel->where('id', $lead['id'])->set('is_client_created', $client_id)->update(); + + if ($policy_id) { + $policy_ids[] = (int) $policy_id; + if ((int) $lead['id'] === $primary_lead_id) { + $primary_policy_id = (int) $policy_id; + } + } + } + + if (empty($policy_ids)) { + return false; + } + + if ($primary_policy_id === null) { + $primary_policy_id = $policy_ids[0]; + } + + return [ + 'client_id' => $client_id, + 'branch_id' => $branch_id, + 'primary_policy_id' => $primary_policy_id, + 'policy_ids' => $policy_ids, + 'lead_ids' => $lead_ids, + ]; + } catch (\Throwable $e) { + $this->myLogger->logme('error', 'createClientWithMatchingLeadsPolicies failed'); + return false; + } + } + + /** + * Active leads with the same client/branch identity that still need a policy. + */ + private function getMatchingLeadsForClientInsert(array $data): array + { + $leads = $this->leadsModel + ->where('is_active', 1) + ->where('client_name', $data['client_name'] ?? null) + ->where('client_short_name', $data['client_short_name'] ?? null) + ->where('branch_name', $data['branch_name'] ?? null) + ->where('branch_code', $data['branch_code'] ?? null) + ->groupStart() + ->where('is_policy_created', null) + ->orWhere('is_policy_created', '') + ->groupEnd() + ->orderBy('id', 'asc') + ->findAll(); + + // Always include the primary lead if it was filtered out somehow. + $primaryId = (int) ($data['id'] ?? 0); + $found = false; + foreach ($leads as $lead) { + if ((int) $lead['id'] === $primaryId) { + $found = true; + break; + } + } + + if (! $found && $primaryId > 0) { + array_unshift($leads, $data); + } + + return $leads; + } + public function createClientWithLeadData($data) { try { @@ -4283,21 +4388,128 @@ class LeadsController extends BaseController // } } - if ($data['lead_form_type'] == 1) { - $client_policy_data['policy_terms'] = $this->preparePolicyTermsFromRFQ($data); - } else { - - $placementJson = $this->getPlacementJson($data); - if ($placementJson) { - $client_policy_data['placement_json'] = $placementJson; - $client_policy_data['policy_terms'] = $this->convertNonEbQCRJsonToPolicyTerms(json_decode($placementJson, true)); - } + $termsData = $this->buildPolicyTermsFromLead($data); + if ($termsData['policy_terms'] !== null) { + $client_policy_data['policy_terms'] = $termsData['policy_terms']; + } + if ($termsData['placement_json'] !== null) { + $client_policy_data['placement_json'] = $termsData['placement_json']; } // print_r($client_policy_data); die; return $client_policy_data; } + /** + * Build policy_terms (and placement_json for non-EB) from lead RFQ/QCR data. + * + * @return array{policy_terms: ?string, placement_json: ?string} + */ + private function buildPolicyTermsFromLead(array $data): array + { + $policy_terms = null; + $placement_json = null; + + if ((int) ($data['lead_form_type'] ?? 0) === 1) { + $policy_terms = $this->preparePolicyTermsFromRFQ($data); + } else { + $placement_json = $this->getPlacementJson($data); + if ($placement_json) { + $policy_terms = $this->convertNonEbQCRJsonToPolicyTerms(json_decode($placement_json, true)); + } + } + + return [ + 'policy_terms' => $policy_terms, + 'placement_json' => $placement_json, + ]; + } + + public function getLeadPolicyTerms($lead_id) + { + try { + $data = $this->leadsModel + ->where('leads.id', $lead_id) + ->where('leads.is_active', 1) + ->first(); + + if (! $data) { + return $this->respond([ + 'status' => false, + 'message' => 'Lead not found or inactive', + 'data' => null, + ], 200); + } + + $termsData = $this->buildPolicyTermsFromLead($data); + $policy_terms = $termsData['policy_terms']; + + if ($policy_terms === null) { + return $this->respond([ + 'status' => false, + 'message' => 'Policy terms could not be generated. Check RFQ/QCR and proposal data.', + 'data' => null, + ], 200); + } + + $client_policy_id = (int) ($this->request->getGet('client_policy_id') ?? 0); + $updated = false; + + if ($client_policy_id > 0) { + $client_policy = $this->clientPolicyModel + ->where('id', $client_policy_id) + ->where('is_active', 1) + ->first(); + + if (! $client_policy) { + return $this->respond([ + 'status' => false, + 'message' => 'Client policy not found or inactive', + 'data' => null, + ], 200); + } + + $updateData = [ + 'policy_terms' => $policy_terms, + ]; + + if ($termsData['placement_json'] !== null) { + $updateData['placement_json'] = $termsData['placement_json']; + } + + $updated = (bool) $this->clientPolicyModel->update($client_policy_id, $updateData); + + if (! $updated) { + return $this->respond([ + 'status' => false, + 'message' => 'Failed to update policy terms', + 'data' => null, + ], 200); + } + } + + return $this->respond([ + 'status' => true, + 'message' => $updated + ? 'Policy terms updated successfully' + : 'Policy terms fetched successfully', + 'lead_id' => (int) $lead_id, + 'client_policy_id' => $client_policy_id > 0 ? $client_policy_id : null, + 'updated' => $updated, + 'lead_form_type' => (int) ($data['lead_form_type'] ?? 0), + 'policy_type_id' => (int) ($data['policy_type_id'] ?? 0), + 'policy_terms' => json_decode($policy_terms, true), + ], 200); + } catch (\Throwable $e) { + $this->myLogger->logme('error', 'getLeadPolicyTerms failed'); + return $this->respond([ + 'status' => false, + 'message' => 'Internal server error', + 'error' => $e->getMessage(), + ], 500); + } + } + private function preparePolicyTermsFromRFQ($data) { try { diff --git a/app/Views/view_rfq.php b/app/Views/view_rfq.php index c1d4c104..32fe85e3 100644 --- a/app/Views/view_rfq.php +++ b/app/Views/view_rfq.php @@ -2023,24 +2023,38 @@ function processTotalSumInsured(data) { } -// Function to move add row button to last row +// Function to move add row button to last visible row +// On QCR page, rows with QCR unchecked are hidden — place + on the last available (visible) row function moveAddRowButton() { - // console.log('table', rfqTable) - const lastRow = rfqTable.rows[rfqTable.rows.length - 1]; - const actionCell = lastRow.querySelector('.action'); + // Remove any existing add buttons so we can place on the last visible row + rfqTable.querySelectorAll('.action #addRow, .action button.btn-primary.btn-sm').forEach(function(btn) { + if (btn.id === 'addRow' || btn.textContent.trim() === '+') { + btn.remove(); + } + }); - if (actionCell && !actionCell.querySelector('#addRow')) { + // Prefer last non-hidden body row (hidden when QCR is unchecked on QCR page) + const bodyRows = rfqTable.tBodies[0] ? rfqTable.tBodies[0].rows : []; + let lastVisibleRow = null; + for (let i = bodyRows.length - 1; i >= 0; i--) { + if (!bodyRows[i].classList.contains('hidden')) { + lastVisibleRow = bodyRows[i]; + break; + } + } + + if (!lastVisibleRow) { + return; + } + + const actionCell = lastVisibleRow.querySelector('.action'); + if (actionCell) { actionCell.innerHTML += ' '; document.getElementById('addRow').addEventListener('click', addRow); } - // const actionCell = lastRow.cells[lastRow.cells.length - 1]; - // actionCell.innerHTML = - // ' QCR Client '; - // document.getElementById('addRow').addEventListener('click', addRow); - - // const lastRow = rows[rows.length - 1]; + hideQCR(); // keep QCR checkbox hidden on QCR page after row changes } @@ -2406,11 +2420,14 @@ function addRow(e) { const actionCell = newRow.insertCell(); actionCell.classList.add('action'); actionCell.innerHTML = - ' QCR Client '; + ' QCR Client '; - e.target.remove(); + if (e && e.target) { + e.target.remove(); + } updateRowNumbers(); realignSpecialConditions(); + moveAddRowButton(); // place + on last visible row isFormDataModified = true; // if any value changeing in the table to set true }