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
}