8921 lines
381 KiB
PHP
8921 lines
381 KiB
PHP
<?php
|
|
namespace App\Controllers;
|
|
|
|
use App\Controllers\Jobs;
|
|
use CodeIgniter\API\ResponseTrait;
|
|
use Exception;
|
|
|
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
|
use PhpOffice\PhpSpreadsheet\Style\Border;
|
|
use PhpOffice\PhpSpreadsheet\Style\Fill;
|
|
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
|
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
|
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
|
|
|
use App\Models\UserModel;
|
|
use App\Models\ClientModel;
|
|
use App\Models\ClientBranchModel;
|
|
use App\Models\ClientPolicyModel;
|
|
use App\Models\LevelContactModel;
|
|
use App\Models\LeadsModel;
|
|
use App\Models\PolicyTypeModel;
|
|
use App\Models\KYCEntityTypeModel;
|
|
use App\Models\PolicyTransactionStatusModel;
|
|
use App\Models\InsurerBranchModel;
|
|
use App\Models\TPABranchModel;
|
|
use App\Models\RFQModel;
|
|
use App\Models\InsurerModel;
|
|
use App\Models\OccupancyMasterModel;
|
|
use App\Models\LeadFilesModel;
|
|
use App\Models\LeadInstallmentPaymentDetails;
|
|
use App\Models\GmailSentHistoryModel;
|
|
use App\Models\SalesActualLeadModel;
|
|
use App\Models\SalesContactPersonModel;
|
|
|
|
use App\Helpers\MailHelper;
|
|
use App\Helpers\ExcelMergeHelper;
|
|
use App\Helpers\ExcelSanitizeHelper;
|
|
use App\Libraries\GoogleSheetLib;
|
|
|
|
class LeadsController extends BaseController
|
|
{
|
|
use ResponseTrait;
|
|
|
|
//log message
|
|
protected $myLogger;
|
|
|
|
//models
|
|
protected $clientModel;
|
|
protected $userModel;
|
|
protected $clientBranchModel;
|
|
protected $clientPolicyModel;
|
|
protected $levelContactModel;
|
|
protected $leadsModel;
|
|
protected $policyTypeModel;
|
|
protected $kycEntityTypeModel;
|
|
protected $policyTransactionStatusModel;
|
|
protected $insurerBranchModel;
|
|
protected $tpaBranchModel;
|
|
protected $RFQModel;
|
|
protected $insurerModel;
|
|
protected $occupancyModel;
|
|
protected $leadFilesModel;
|
|
protected $leadInstallmentPaymentDetails;
|
|
protected $gmailSentHistoryModel;
|
|
|
|
//variables for storing array
|
|
protected $issuer;
|
|
protected $clientType;
|
|
protected $leadType;
|
|
public $leadsStatus;
|
|
protected $claim_type_for_gpa;
|
|
protected $cause_of_death;
|
|
protected $buisnessType;
|
|
protected $member_data_excel_columns;
|
|
protected $general_relationships;
|
|
protected $leadModel;
|
|
protected $contactModel;
|
|
|
|
public function __construct()
|
|
{
|
|
set_session_context('LEAD CONTROLLER');
|
|
$this->myLogger = \Config\Services::mylogger();
|
|
|
|
$this->clientModel = new ClientModel();
|
|
$this->userModel = new UserModel();
|
|
$this->clientBranchModel = new ClientBranchModel();
|
|
$this->clientPolicyModel = new ClientPolicyModel();
|
|
$this->levelContactModel = new LevelContactModel();
|
|
$this->leadsModel = new LeadsModel();
|
|
$this->policyTypeModel = new PolicyTypeModel();
|
|
$this->kycEntityTypeModel = new KYCEntityTypeModel();
|
|
$this->policyTransactionStatusModel = new PolicyTransactionStatusModel();
|
|
$this->insurerBranchModel = new InsurerBranchModel();
|
|
$this->tpaBranchModel = new TPABranchModel();
|
|
$this->RFQModel = new RFQModel();
|
|
$this->insurerModel = new InsurerModel();
|
|
$this->occupancyModel = new OccupancyMasterModel();
|
|
$this->leadFilesModel = new LeadFilesModel();
|
|
$this->leadInstallmentPaymentDetails = new LeadInstallmentPaymentDetails();
|
|
$this->gmailSentHistoryModel = new GmailSentHistoryModel();
|
|
$this->leadModel = new SalesActualLeadModel();
|
|
$this->contactModel = new SalesContactPersonModel();
|
|
|
|
|
|
$this->issuer = [1 => 'JIBS', 2 => 'Nhance'];
|
|
$this->clientType = [1 => 'Group', 2 => 'Individual'];
|
|
$this->leadType = [1 => 'Fresh', 2 => 'Renewal', 3 => 'Roll Over'];
|
|
$data = $this->kycEntityTypeModel->where('is_active', 1)->findAll();
|
|
$this->buisnessType = array_column($data, 'name', 'id');
|
|
// $this->buisnessType = [1 => 'Public Sector', 2 => 'Private Sector',3=> 'Trust',4 => 'Proprietorship',5 => 'Partnership',6 => 'Private',7 => 'Individual'];
|
|
$this->leadsStatus = [
|
|
'queued' => 'In-Queued',
|
|
'rfq_created' => 'RFQ Created',
|
|
'rfq_sent' => 'RFQ Sent',
|
|
'qcr_created' => 'QCR Created',
|
|
'qcr_sent' => 'QCR Sent',
|
|
'lost' => 'Lost',
|
|
'co_insurer_pending' => 'Co-Insurer Pending',
|
|
'won' => 'Won',
|
|
'completed_with_corrections' => 'Completed with Corrections',
|
|
'completed_without_corrections' => 'Completed without Corrections',
|
|
];
|
|
|
|
$this->claim_type_for_gpa = [
|
|
'nil' => 'Nil',
|
|
'accident_death' => 'Accident Death',
|
|
'permanent_total_disablement' => 'Permanent Total Disablement',
|
|
'permanent_partial_disablement' => 'Permanent Partial Disablement',
|
|
'temporary_total_disablement_benefit' => 'Temporary Total Disablement benefit',
|
|
];
|
|
|
|
$this->cause_of_death = [
|
|
'natural_death' => 'Natural Death',
|
|
'suicide' => 'Suicide',
|
|
'accident' => 'Accident',
|
|
'cardiac_arrest' => 'Cardiac Arrest',
|
|
'septic_shock' => 'Septic shock',
|
|
'heart_attack' => 'Heart Attack',
|
|
];
|
|
|
|
$this->member_data_excel_columns = [
|
|
'sno' => [
|
|
'col_idx' => 0,
|
|
'col_cell_name' => 'A',
|
|
'col_name' => 'Sl no',
|
|
'is_mandatory' => false,
|
|
'data_type' => 'str',
|
|
'format' => null,
|
|
'allowed_values' => null,
|
|
],
|
|
'emp_code' => [
|
|
'col_idx' => 1,
|
|
'col_cell_name' => 'B',
|
|
'col_name' => 'Emp Code',
|
|
'is_mandatory' => true,
|
|
'data_type' => 'str',
|
|
'format' => null,
|
|
'allowed_values' => null,
|
|
],
|
|
'name' => [
|
|
'col_idx' => 2,
|
|
'col_cell_name' => 'C',
|
|
'col_name' => 'Name',
|
|
'is_mandatory' => true,
|
|
'data_type' => 'str',
|
|
'format' => null,
|
|
'allowed_values' => null,
|
|
],
|
|
'relationship' => [
|
|
'col_idx' => 3,
|
|
'col_cell_name' => 'D',
|
|
'col_name' => 'Relationship',
|
|
'is_mandatory' => true,
|
|
'data_type' => 'str',
|
|
'format' => null,
|
|
'allowed_values' => [
|
|
'Self', 'Spouse', 'Son', 'Daughter', 'Father', 'Mother',
|
|
'Father-in-law', 'Mother-in-law',
|
|
'self', 'spouse', 'son', 'daughter', 'father', 'mother',
|
|
'father-in-law', 'mother-in-law',
|
|
],
|
|
'custom' => 'check_relationship_for_member_data',
|
|
'params' => ['row', 'relationship', 'columns_to_check'],
|
|
],
|
|
'gender' => [
|
|
'col_idx' => 4,
|
|
'col_cell_name' => 'E',
|
|
'col_name' => 'Gender',
|
|
'is_mandatory' => true,
|
|
'data_type' => 'str',
|
|
'format' => null,
|
|
'allowed_values' => ['M', 'F'],
|
|
],
|
|
'dob' => [
|
|
'col_idx' => 5,
|
|
'col_cell_name' => 'F',
|
|
'col_name' => 'DOB',
|
|
'is_mandatory' => true,
|
|
'data_type' => 'str',
|
|
'format' => 'd-M-Y',
|
|
'allowed_values' => null,
|
|
'age_validation' => true,
|
|
// 'custom' => 'check_dob_diff',
|
|
// 'params' => ['row', 'relationship', 'default_age_ratio', 'policy_details']
|
|
],
|
|
'age' => [
|
|
'col_idx' => 6,
|
|
'col_cell_name' => 'G',
|
|
'col_name' => 'Age',
|
|
'is_mandatory' => true,
|
|
'data_type' => 'int',
|
|
'format' => null,
|
|
'allowed_values' => null,
|
|
],
|
|
'email' => [
|
|
'col_idx' => 7,
|
|
'col_cell_name' => 'H',
|
|
'col_name' => 'Email',
|
|
'is_mandatory' => false,
|
|
'data_type' => 'str',
|
|
'format' => null,
|
|
'allowed_values' => null,
|
|
],
|
|
'mobile' => [
|
|
'col_idx' => 8,
|
|
'col_cell_name' => 'I',
|
|
'col_name' => 'Mobile',
|
|
'is_mandatory' => false,
|
|
'data_type' => 'str',
|
|
'format' => null,
|
|
'allowed_values' => null,
|
|
],
|
|
'si' => [
|
|
'col_idx' => 9,
|
|
'col_cell_name' => 'J',
|
|
'col_name' => 'SI',
|
|
'is_mandatory' => false,
|
|
'data_type' => 'int',
|
|
'format' => null,
|
|
'allowed_values' => null,
|
|
],
|
|
];
|
|
|
|
$this->general_relationships = [
|
|
'self' => [
|
|
'name' => 'Self',
|
|
'gender' => 'M',
|
|
'age_min' => 18,
|
|
'age_max' => null,
|
|
],
|
|
'spouse' => [
|
|
'name' => 'Spouse',
|
|
'gender' => 'F',
|
|
'age_min' => 18,
|
|
'age_max' => null,
|
|
],
|
|
'son' => [
|
|
'name' => 'Son',
|
|
'gender' => 'M',
|
|
'age_min' => null,
|
|
'age_max' => 25,
|
|
],
|
|
'daughter' => [
|
|
'name' => 'Daughter',
|
|
'gender' => 'F',
|
|
'age_min' => null,
|
|
'age_max' => 25,
|
|
],
|
|
'father' => [
|
|
'name' => 'Father',
|
|
'gender' => 'M',
|
|
'age_min' => 18,
|
|
'age_max' => null,
|
|
],
|
|
'mother' => [
|
|
'name' => 'Mother',
|
|
'gender' => 'F',
|
|
'age_min' => 18,
|
|
'age_max' => null,
|
|
],
|
|
'father-in-law' => [
|
|
'name' => 'Father in Law',
|
|
'gender' => 'M',
|
|
'age_min' => 18,
|
|
'age_max' => null,
|
|
],
|
|
'mother-in-law' => [
|
|
'name' => 'Mother in Law',
|
|
'gender' => 'F',
|
|
'age_min' => 18,
|
|
'age_max' => null,
|
|
],
|
|
];
|
|
|
|
}
|
|
|
|
public function viewLeadsList()
|
|
{
|
|
$data['tab_name'] = 'Opportunities';
|
|
$data['page_name'] = 'Opportunities';
|
|
|
|
// Set basic data
|
|
$data['issuer'] = $this->issuer;
|
|
$data['client_type'] = $this->clientType;
|
|
$data['lead_type'] = $this->leadType;
|
|
$data['lead_status'] = $this->leadsStatus;
|
|
|
|
// Fetch policy types and entity data
|
|
$data['policy_type'] = $this->policyTypeModel->where('is_active', 1)->findAll();
|
|
$data['entity'] = $this->kycEntityTypeModel->where('is_active', 1)->findAll();
|
|
|
|
// Data needed for mail modals on Opportunities list (reuse RFQ behaviour)
|
|
$data['userList'] = $this->userModel->getUserListForRFQ();
|
|
$data['exclusiveUserList'] = $this->userModel->getexclusiveUserListForRFQ();
|
|
// Attachments for mails are lead-specific and will be handled at RFQ level;
|
|
// keep placeholder here so modal templates render without notices.
|
|
$data['attachment_html'] = '';
|
|
|
|
// dd($lastFiveYears);
|
|
if ($this->request->is('get')) {
|
|
// Fetch leads data
|
|
$data['lead_data_list'] = $this->leadsModel->getLeadDataForLising();
|
|
// Load layout and pass data
|
|
$this->loadLayout('lead_filter', $data);
|
|
} else {
|
|
|
|
$isFromDashboard = $this->request->getPost("is_dashboard");
|
|
|
|
if (isset($isFromDashboard) && ! empty($isFromDashboard) && $isFromDashboard == 1) {
|
|
$ids = $this->request->getPost('ids');
|
|
$ids = array_filter(explode(',', $ids));
|
|
|
|
if (! empty($ids)) {
|
|
$idsStr = implode(',', array_map('intval', $ids)); // sanitize IDs to be integers
|
|
$where = "leads.id IN ($idsStr)";
|
|
} else {
|
|
$where = '1 = 0'; // No valid IDs, return empty result
|
|
}
|
|
// dd($where );
|
|
$data['lead_data_list'] = $this->leadsModel->getLeadDataForLising($where);
|
|
$this->loadLayout('lead_filter', $data);
|
|
} else {
|
|
$search_data = $this->request->getPost();
|
|
|
|
$where = [];
|
|
foreach ($search_data as $search_objects => $key) {
|
|
if ($key != null && $key != '' && $key != 0 && $search_objects != 'is_dashboard') {
|
|
if ($search_objects == 'status') {
|
|
$where[('leads.' . $search_objects)] = $key;
|
|
} else {
|
|
$where[$search_objects] = $key;
|
|
}
|
|
}
|
|
}
|
|
// !dd($where);
|
|
$data['lead_data_list'] = $this->leadsModel->getLeadDataForLising($where);
|
|
|
|
$html = view('leads_list', $data);
|
|
return $this->respond(['status' => true, 'html' => $html], 200);
|
|
}
|
|
}
|
|
}
|
|
|
|
public function createLead()
|
|
{
|
|
$id = $this->request->getPost('id');
|
|
$actual_lead_id = $this->request->getPost('actual_lead_id');
|
|
$actual_lead_id = ! empty($actual_lead_id) ? $actual_lead_id : null;
|
|
|
|
$this->normalizeClaimHistoryPostData();
|
|
$postData = $this->request->getPost();
|
|
$data = $this->prepareLeadData();
|
|
|
|
|
|
$rules = [
|
|
|
|
'lead_type' => [
|
|
'rules' => 'integer',
|
|
'errors' => ['required' => 'Opportunity Type is required'],
|
|
],
|
|
'issuer' => [
|
|
'rules' => 'required',
|
|
'errors' => ['required' => 'Issuer is required'],
|
|
],
|
|
'gst' => [
|
|
'rules' => 'required|regex_match[/^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}Z[0-9A-Z]{1}$/]',
|
|
'errors' => [
|
|
'required' => 'GST Number is required.',
|
|
'regex_match' => 'Invalid GST format. Example: 22AAAAA0000A1Z5',
|
|
],
|
|
],
|
|
'branch_name' => [
|
|
'rules' => 'required|regex_match[/^[a-zA-Z0-9\s_-]+$/]|min_length[3]',
|
|
'errors' => [
|
|
'required' => 'Branch Name is required.',
|
|
'regex_match' => 'Branch Name can only contain letters, numbers, spaces, hyphens and underscores..',
|
|
'min_length' => 'Branch Name must be at least 3 characters long.',
|
|
],
|
|
],
|
|
'branch_code' => [
|
|
'rules' => 'required|regex_match[/^[a-zA-Z0-9_-]+$/]',
|
|
'errors' => [
|
|
'required' => 'Branch Code is required.',
|
|
'regex_match' => 'Branch Code can only contain letters, numbers, hyphens and underscores..',
|
|
],
|
|
],
|
|
'contact_person_name' => [
|
|
'rules' => 'required|regex_match[/^[a-zA-Z0-9_ -]+$/]',
|
|
'errors' => [
|
|
'required' => 'Contact Person Name is required',
|
|
'regex_match' => 'Contact person name only letters, numbers and spaces, hyphens and underscores..',
|
|
],
|
|
],
|
|
'contact_person_mobile' => [
|
|
'rules' => 'required',
|
|
'rules' => 'required|exact_length[10]|regex_match[/^[0-9]+$/]',
|
|
'errors' => [
|
|
'required' => 'Contact Person Mobile is required',
|
|
'regex_match' => 'Contact Person Mobile Only numbers',
|
|
'exact_length' => 'Contact Person Mobile must be exactly 10 digits long.',
|
|
],
|
|
],
|
|
'contact_person_email' => [
|
|
'rules' => 'required|regex_match[/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/]',
|
|
'errors' => [
|
|
'required' => 'Contact Person Email address is required.',
|
|
'regex_match' => 'Please enter a valid email format (e.g., name@domain.com).',
|
|
],
|
|
// 'rules' => 'required|valid_email|regex_match[/^[a-zA-Z0-9_-]+$/]',
|
|
// 'regex_match' => 'Contact Person Email Only letters, numbers and characters _ - @ . are allowed'
|
|
|
|
],
|
|
'salse_person_id' => [
|
|
'rules' => 'required',
|
|
'errors' => ['required' => 'Sales Person is required'],
|
|
],
|
|
'status' => [
|
|
'rules' => 'required',
|
|
'errors' => ['required' => 'Status is required'],
|
|
],
|
|
'next_reminder_date' => [
|
|
'label' => 'Next Reminder Date',
|
|
'rules' => 'permit_empty|valid_date[d/m/Y]',
|
|
'errors' => [
|
|
'valid_date' => 'The {field} must be in the format DD/MM/YYYY.',
|
|
],
|
|
],
|
|
];
|
|
|
|
if (isset($postData['lead_type']) && in_array((int) $postData['lead_type'], [1, 3], true)) {
|
|
|
|
$rules['entity_type_id'] = [
|
|
'rules' => 'required',
|
|
'errors' => ['required' => 'Entity Type is required'],
|
|
];
|
|
|
|
$clientNameRules = 'required|regex_match[/^[a-zA-Z0-9_ -]+$/]';
|
|
$clientShortNameRules = 'required|regex_match[/^[a-zA-Z0-9_-]+$/]';
|
|
|
|
// Only validate for uniqueness if it's a new client being specified.
|
|
// If an existing client is selected from the dropdown, `client_id` will be present.
|
|
if (empty($postData['client_id'])) {
|
|
$ignoreClientId = null;
|
|
$lead = null;
|
|
if ($id) { // This is an update of a lead
|
|
$lead = $this->leadsModel->find($id);
|
|
if ($lead && ! empty($lead['is_client_created'])) {
|
|
$ignoreClientId = (int) $lead['is_client_created'];
|
|
}
|
|
}
|
|
|
|
$submittedName = trim((string) ($postData['client_name'] ?? ''));
|
|
$submittedShort = trim((string) ($postData['client_short_name'] ?? ''));
|
|
$nameUnchanged = $lead && strcasecmp(trim((string) ($lead['client_name'] ?? '')), $submittedName) === 0;
|
|
$shortUnchanged = $lead && strcasecmp(trim((string) ($lead['client_short_name'] ?? '')), $submittedShort) === 0;
|
|
|
|
if ($ignoreClientId) {
|
|
$clientNameRules .= '|is_unique[clients.client_name,id,' . $ignoreClientId . ']';
|
|
$clientShortNameRules .= '|is_unique[clients.short_name,id,' . $ignoreClientId . ']';
|
|
} else {
|
|
// On edit, unchanged names belong to this opportunity — do not treat as duplicates.
|
|
// (Client row may already exist even when is_client_created is unset.)
|
|
if (! $nameUnchanged) {
|
|
$clientNameRules .= '|is_unique[clients.client_name]';
|
|
}
|
|
if (! $shortUnchanged) {
|
|
$clientShortNameRules .= '|is_unique[clients.short_name]';
|
|
}
|
|
}
|
|
}
|
|
|
|
$rules['client_name'] = [
|
|
'rules' => $clientNameRules,
|
|
'errors' => [
|
|
'required' => 'Client Name is required',
|
|
'regex_match' => 'Client Name only letters, numbers, space, hyphens and underscores are allowed',
|
|
'is_unique' => 'This Client Name already exists.',
|
|
],
|
|
];
|
|
|
|
$rules['client_short_name'] = [
|
|
'rules' => $clientShortNameRules,
|
|
'errors' => [
|
|
'required' => 'Client Short Name is required',
|
|
'regex_match' => 'Client Short Name only letters, numbers, hyphens and underscores are allowed',
|
|
'is_unique' => 'This Client Short Name already exists.',
|
|
],
|
|
];
|
|
}
|
|
|
|
foreach ($postData as $key => $value) {
|
|
// Check if the key starts with 'docs_name_'
|
|
if (strpos($key, 'docs_name_') === 0) {
|
|
$rules[$key . '.*'] = [
|
|
'label' => 'Document Name',
|
|
'rules' => 'permit_empty|regex_match[/^[a-zA-Z0-9_\- ]+$/]',
|
|
'errors' => [
|
|
'regex_match' => 'Document Name in {field} can only contain letters, numbers, hyphens, and underscores.',
|
|
],
|
|
];
|
|
}
|
|
}
|
|
|
|
// print_r($rules); die;
|
|
|
|
if ((int) $this->request->getPost('lead_form_type') === 2) {
|
|
$rules['policy_type_id'] = [
|
|
'rules' => 'required',
|
|
'errors' => ['required' => 'Policy Type is required'],
|
|
];
|
|
$rules['policy_start_date'] = [
|
|
'rules' => 'required',
|
|
'errors' => ['required' => 'Date of Commencement is required'],
|
|
];
|
|
$rules['policy_end_date'] = [
|
|
'rules' => 'required',
|
|
'errors' => ['required' => 'Date of Expiry is required'],
|
|
];
|
|
|
|
if ((int) $this->request->getPost('claim_history') === 1) {
|
|
$nilClaimsRows = $this->resolveNilClaimRowFlags($postData);
|
|
$claimRowCount = $this->getClaimHistoryRowCount($postData, $nilClaimsRows);
|
|
|
|
for ($claimIndex = 0; $claimIndex < $claimRowCount; $claimIndex++) {
|
|
$rules["first_year.$claimIndex"] = [
|
|
'rules' => 'required|regex_match[/^\d{4}-\d{4}$/]',
|
|
'errors' => [
|
|
'required' => 'Claim Year is required for all entries.',
|
|
'regex_match' => 'Year must be in format YYYY-YYYY.',
|
|
],
|
|
];
|
|
|
|
if (! empty($nilClaimsRows[$claimIndex])) {
|
|
continue;
|
|
}
|
|
|
|
$rules["first_policy_type_.$claimIndex"] = [
|
|
'rules' => 'required|regex_match[/^[a-zA-Z0-9 _-]+$/]',
|
|
'errors' => [
|
|
'required' => 'Policy Type is required in Claim History.',
|
|
'regex_match' => 'Policy Type only letters, numbers, space, hyphens and underscores are allowed',
|
|
],
|
|
];
|
|
$rules["first_date_of_loss_.$claimIndex"] = [
|
|
'rules' => 'required|regex_match[/^[0-9]{2}-[0-9]{2}-[0-9]{4}$/]',
|
|
'errors' => [
|
|
'required' => 'Date of Loss is required.',
|
|
'regex_match' => 'Date of Loss must be inValid format.',
|
|
],
|
|
];
|
|
$rules["first_cause_of_loss.$claimIndex"] = [
|
|
'rules' => 'required|regex_match[/^[a-zA-Z0-9 _-]+$/]',
|
|
'errors' => [
|
|
'required' => 'Cause of Loss is required.',
|
|
'regex_match' => 'Cause of Loss only letters, numbers, space, hyphens and underscores are allowed',
|
|
],
|
|
];
|
|
$rules["first_claim_amount.$claimIndex"] = [
|
|
'rules' => 'required|numeric',
|
|
'errors' => [
|
|
'required' => 'Claim Amount is required.',
|
|
'numeric' => 'Claim Amount must be a number.',
|
|
],
|
|
];
|
|
$rules["first_settled_amount.$claimIndex"] = [
|
|
'rules' => 'required|numeric',
|
|
'errors' => [
|
|
'required' => 'Settled Amount is required.',
|
|
'numeric' => 'Settled Amount must be a number.',
|
|
],
|
|
];
|
|
$rules["first_claim_status.$claimIndex"] = [
|
|
'rules' => 'required|alpha_space',
|
|
'errors' => [
|
|
'required' => 'Claim Status is required.',
|
|
'alpha_space' => 'Claim Status should only contain letters and spaces.',
|
|
],
|
|
];
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
$leadFormType = (int) ($postData['lead_form_type'] ?? 1);
|
|
$postedPolicyTypeIds = array_map('intval', (array) ($postData['policy_type_id'] ?? []));
|
|
$claimHistoryPolicyTypes = [1, 6, 7];
|
|
$hasClaimHistoryPolicy = count(array_intersect($postedPolicyTypeIds, $claimHistoryPolicyTypes)) > 0;
|
|
$isEbClaimHistory = $leadFormType === 1
|
|
&& in_array((int) ($postData['lead_type'] ?? 0), [1, 2, 3], true)
|
|
&& $hasClaimHistoryPolicy
|
|
&& (int) ($postData['claim_history'] ?? 0) === 1;
|
|
|
|
if ($isEbClaimHistory) {
|
|
$nilClaimsRows = $this->resolveNilClaimRowFlags($postData);
|
|
$claimRowCount = $this->getClaimHistoryRowCount($postData, $nilClaimsRows);
|
|
|
|
for ($claimIndex = 0; $claimIndex < $claimRowCount; $claimIndex++) {
|
|
$rules["first_year.$claimIndex"] = [
|
|
'rules' => 'required|regex_match[/^\d{4}-\d{4}$/]',
|
|
'errors' => [
|
|
'required' => 'Claim Year is required for all entries.',
|
|
'regex_match' => 'Year must be in format YYYY-YYYY.',
|
|
],
|
|
];
|
|
|
|
if (! empty($nilClaimsRows[$claimIndex])) {
|
|
continue;
|
|
}
|
|
|
|
$rules["emp_id.$claimIndex"] = [
|
|
'rules' => 'required',
|
|
'errors' => ['required' => 'Employee ID is required in Claim History.'],
|
|
];
|
|
$rules["emp_name.$claimIndex"] = [
|
|
'rules' => 'required',
|
|
'errors' => ['required' => 'Employee Name is required in Claim History.'],
|
|
];
|
|
$rules["gender.$claimIndex"] = [
|
|
'rules' => 'required|in_list[Female,Male]',
|
|
'errors' => [
|
|
'required' => 'Gender is required in Claim History.',
|
|
'in_list' => 'Gender must be Female or Male.',
|
|
],
|
|
];
|
|
$rules["designation.$claimIndex"] = [
|
|
'rules' => 'required',
|
|
'errors' => ['required' => 'Designation is required in Claim History.'],
|
|
];
|
|
$rules["sum_insured.$claimIndex"] = [
|
|
'rules' => 'required|numeric',
|
|
'errors' => [
|
|
'required' => 'Sum Insured is required in Claim History.',
|
|
'numeric' => 'Sum Insured must be a number.',
|
|
],
|
|
];
|
|
$rules["first_death_date.$claimIndex"] = [
|
|
'rules' => 'required|regex_match[/^[0-9]{2}-([0-9]{2}|[A-Za-z]{3})-[0-9]{4}$/]',
|
|
'errors' => [
|
|
'required' => 'Date of Death is required.',
|
|
'regex_match' => 'Date of Death must be in DD-MM-YYYY or DD-MMM-YYYY format.',
|
|
],
|
|
];
|
|
$rules["first_cause_of_death.$claimIndex"] = [
|
|
'rules' => 'required|in_list[natural_death,suicide,accident,cardiac_arrest,septic_shock,heart_attack]',
|
|
'errors' => [
|
|
'required' => 'Nature/Cause Of Death is required.',
|
|
'in_list' => 'Nature/Cause Of Death is invalid.',
|
|
],
|
|
];
|
|
$rules["first_claim_amount.$claimIndex"] = [
|
|
'rules' => 'required|numeric',
|
|
'errors' => [
|
|
'required' => 'Claim/Settled Amount is required.',
|
|
'numeric' => 'Claim/Settled Amount must be a number.',
|
|
],
|
|
];
|
|
}
|
|
}
|
|
|
|
// 1. MANUALLY VALIDATE FILES BEFORE PROCESSING
|
|
// $allFiles = $this->request->getFiles();
|
|
// foreach ($allFiles as $inputName => $files) {
|
|
// // If it's a single file, wrap it in an array to use the same logic
|
|
// $fileArray = is_array($files) ? $files : [$files];
|
|
|
|
// foreach ($fileArray as $index => $file) {
|
|
// if ($file->isValid() && !$file->hasMoved()) {
|
|
// $extension = strtolower($file->getExtension());
|
|
|
|
// // Logic: index 0 is Excel only, others are mixed
|
|
// if ($index === 0) {
|
|
// $allowed = ['xls', 'xlsx'];
|
|
// } else {
|
|
// $allowed = ['xls', 'xlsx', 'pdf', 'jpg', 'jpeg', 'png'];
|
|
// }
|
|
|
|
// if (!in_array($extension, $allowed)) {
|
|
// // Return 400 Error immediately
|
|
// return $this->response->setStatusCode(400)->setJSON([
|
|
// 'status' => false,
|
|
// 'message' => 'Input validation failed',
|
|
// 'code' => 400,
|
|
// 'errors' => [
|
|
// $inputName => "File " . ($index + 1) . " has an invalid extension ($extension). Allowed: " . implode(',', $allowed)
|
|
// ]
|
|
// ]);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
$isValid = $this->validate($rules);
|
|
|
|
$start_dates = $this->request->getPost('policy_start_date');
|
|
$end_dates = $this->request->getPost('policy_end_date');
|
|
|
|
if ($start_dates && $end_dates) {
|
|
|
|
$starts = is_array($start_dates) ? $start_dates : [$start_dates];
|
|
$ends = is_array($end_dates) ? $end_dates : [$end_dates];
|
|
|
|
foreach ($starts as $index => $s_date) {
|
|
$e_date = $ends[$index] ?? null;
|
|
|
|
if ($s_date && $e_date) {
|
|
|
|
$f_start = change_date_format($s_date, 'd/m/Y', 'Y-m-d');
|
|
$f_end = change_date_format($e_date, 'd/m/Y', 'Y-m-d');
|
|
|
|
if ($f_start && $f_end && ($f_end < $f_start)) {
|
|
$isValid = false;
|
|
|
|
// Determine the error key name
|
|
// If it's an array, we use index (e.g., policy_end_date.0)
|
|
$errorKey = is_array($start_dates) ? "policy_end_date.$index" : "policy_end_date";
|
|
|
|
$this->validator->setError($errorKey, 'Date of Expiry cannot be before Date of Commencement.');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (! $isValid) {
|
|
|
|
return $this->response->setStatusCode(400)->setJSON([
|
|
'status' => false,
|
|
'message' => 'Input validation failed',
|
|
'code' => 400,
|
|
'errors' => $this->validator->getErrors(),
|
|
]);
|
|
}
|
|
|
|
// print_r($data); die;
|
|
|
|
if (! $id) {
|
|
return $this->insertNewLead($data);
|
|
} else {
|
|
return $this->updateOldLead($id, $data);
|
|
}
|
|
}
|
|
|
|
private function prepareLeadData()
|
|
{
|
|
|
|
$request_data = $this->request->getPost();
|
|
$data = sanitizeInputArrayAdvanced($request_data);
|
|
$data['client_type'] = 1;
|
|
if (! in_array((int) $data['lead_type'], [1, 3], true)) {
|
|
$client_data = $this->clientModel->where('id', $data['client_id'])->where('is_active', 1)->first();
|
|
$data['client_name'] = $client_data['client_name'];
|
|
$data['client_short_name'] = $client_data['short_name'];
|
|
$data['entity_type_id'] = $client_data['entity_type_id'];
|
|
$data['client_type'] = $client_data['client_type'];
|
|
} else {
|
|
if (! empty($data['client_id'])) {
|
|
$data['is_client_created'] = $data['client_id'];
|
|
} else {
|
|
$data['client_id'] = 0;
|
|
$data['client_branch_id'] = 0;
|
|
$data['source_policy_id'] = 0;
|
|
|
|
// Keep existing client link on update when "Existing Client" is off.
|
|
// Otherwise is_client_created is wiped to null and later edits fail uniqueness checks.
|
|
if (! empty($data['id'])) {
|
|
$existingLead = $this->leadsModel->find($data['id']);
|
|
if ($existingLead && ! empty($existingLead['is_client_created'])) {
|
|
$data['is_client_created'] = $existingLead['is_client_created'];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$data['client_code'] = generate_client_code();
|
|
if ($data['client_code'] == 2) {
|
|
$data['client_code'] = generate_client_code('IC');
|
|
}
|
|
|
|
if ((int) ($data['lead_form_type'] ?? 1) === 2) {
|
|
$data = $this->prepareSingleLeadData($data);
|
|
} else {
|
|
$data = $this->prepareMultipleLeadData($data);
|
|
}
|
|
|
|
// print_r($data); die;
|
|
return $data;
|
|
}
|
|
|
|
private function prepareSingleLeadData($data)
|
|
{
|
|
// print_r($data); die;
|
|
$index_plus_one = 1;
|
|
$form_file_name = "file_name_" . $index_plus_one;
|
|
$form_docs_name = "docs_name_" . $index_plus_one;
|
|
$leads_file_primary_key = $data['leads_file_id'] ?? [];
|
|
|
|
$multi_file_data = [];
|
|
if (isset($data[$form_docs_name])) {
|
|
$files = $this->request->getFileMultiple($form_file_name);
|
|
$multi_file_data = $this->uploadMultiFiles($files, $data[$form_docs_name], $leads_file_primary_key);
|
|
}
|
|
|
|
// Separate the insurer and insurer branch, handle missing or invalid data
|
|
if (isset($data['insurer']) && strpos($data['insurer'], '-') !== false) {
|
|
list($insurer_branch_id, $insurer_id) = explode('-', $data['insurer']);
|
|
} else {
|
|
$insurer_branch_id = 0;
|
|
$insurer_id = 0;
|
|
}
|
|
|
|
$data['insurer_id'] = $insurer_id;
|
|
$data['insurer_branch_id'] = $insurer_branch_id;
|
|
|
|
// Separate the insurer and insurer branch, handle missing or invalid data
|
|
if (isset($data['tpa']) && strpos($data['tpa'], '-') !== false) {
|
|
list($tpa_branch_id, $tpa_id) = explode('-', $data['tpa']);
|
|
} else {
|
|
$tpa_branch_id = 0;
|
|
$tpa_id = 0;
|
|
}
|
|
|
|
$data['tpa_id'] = $tpa_id;
|
|
$data['tpa_branch_id'] = $tpa_branch_id;
|
|
|
|
if (! empty($data['policy_start_date'])) {
|
|
$data['policy_start_date'] = change_date_format($data['policy_start_date']);
|
|
} else {
|
|
$data['policy_start_date'] = null;
|
|
}
|
|
|
|
if (! empty($data['policy_end_date'])) {
|
|
$data['policy_end_date'] = change_date_format($data['policy_end_date']);
|
|
} else {
|
|
$data['policy_end_date'] = null;
|
|
}
|
|
|
|
// $data['file_name'] = file_Upload($files, $uploadFilePath);
|
|
$data['multi_file_data'] = $multi_file_data ?? null;
|
|
|
|
$processcedData[] = $data;
|
|
|
|
// print_r($data);die();
|
|
return $processcedData;
|
|
}
|
|
|
|
private function prepareMultipleLeadData($data)
|
|
{
|
|
// print_r($data); die;
|
|
$processedData = [];
|
|
|
|
foreach ($data['policy_type_id'] as $index => $value) {
|
|
|
|
$index_plus_one = $index + 1;
|
|
$form_file_name = "file_name_" . $index_plus_one;
|
|
$form_docs_name = "docs_name_" . $index_plus_one;
|
|
$leads_file_primary_key = $data['leads_file_id'] ?? [];
|
|
$files = $this->request->getFileMultiple($form_file_name);
|
|
$docs_names_from_post = $data[$form_docs_name] ?? [];
|
|
$multi_file_data = $this->uploadMultiFiles($files, $docs_names_from_post, $leads_file_primary_key);
|
|
|
|
// Separate the insurer and insurer branch, handle missing or invalid data
|
|
if (isset($data['insurer'][$index]) && strpos($data['insurer'][$index], '-') !== false) {
|
|
list($insurer_branch_id, $insurer_id) = explode('-', $data['insurer'][$index]);
|
|
} else {
|
|
$insurer_branch_id = 0;
|
|
$insurer_id = 0;
|
|
}
|
|
// Separate the insurer and insurer branch, handle missing or invalid data
|
|
if (isset($data['tpa'][$index]) && strpos($data['tpa'][$index], '-') !== false) {
|
|
list($tpa_branch_id, $tpa_id) = explode('-', $data['tpa'][$index]);
|
|
} else {
|
|
$tpa_branch_id = 0;
|
|
$tpa_id = 0;
|
|
}
|
|
|
|
// Separate the insurer and insurer branch, handle missing or invalid data
|
|
if (isset($data['proposed_insurer'][$index]) && strpos($data['proposed_insurer'][$index], '-') !== false) {
|
|
list($proposed_insurer_branch_id, $proposed_insurer_id) = explode('-', $data['proposed_insurer'][$index]);
|
|
} else {
|
|
$proposed_insurer_branch_id = 0;
|
|
$proposed_insurer_id = 0;
|
|
}
|
|
|
|
// Separate the TPA and TPA branch, handle missing or invalid data
|
|
if (isset($data['proposed_tpa'][$index]) && strpos($data['proposed_tpa'][$index], '-') !== false) {
|
|
list($proposed_tpa_branch_id, $proposed_tpa_id) = explode('-', $data['proposed_tpa'][$index]);
|
|
} else {
|
|
$proposed_tpa_branch_id = 0;
|
|
$proposed_tpa_id = 0;
|
|
}
|
|
|
|
if (! empty($data['policy_start_date'][$index])) {
|
|
$policy_start_date = change_date_format($data['policy_start_date'][$index], 'd/m/Y', 'Y-m-d');
|
|
} else {
|
|
$policy_start_date = null;
|
|
}
|
|
|
|
if (! empty($data['policy_end_date'][$index])) {
|
|
$policy_end_date = change_date_format($data['policy_end_date'][$index], 'd/m/Y', 'Y-m-d');
|
|
} else {
|
|
$policy_end_date = null;
|
|
}
|
|
|
|
if (! empty($data['incurred_claim_date'][$index])) {
|
|
$incurred_claims_date = change_date_format($data['incurred_claim_date'][$index], 'd/m/Y', 'Y-m-d');
|
|
} else {
|
|
$incurred_claims_date = null;
|
|
}
|
|
|
|
// if (!empty($data['premium_date'][$index])) {
|
|
// $premium_date = change_date_format($data['premium_date'][$index], 'd/m/Y', 'Y-m-d');
|
|
// } else {
|
|
// $premium_date = null;
|
|
// }
|
|
|
|
if (! empty($data['source_policy_start_date']) && $data['lead_type'] == 2) {
|
|
$data['source_policy_start_date'] = change_date_format($data['source_policy_start_date'], 'd/m/Y', 'Y-m-d');
|
|
} else {
|
|
$data['source_policy_start_date'] = null;
|
|
}
|
|
|
|
if (! empty($data['source_policy_end_date']) && $data['lead_type'] == 2) {
|
|
$data['source_policy_end_date'] = change_date_format($data['source_policy_end_date'], 'd/m/Y', 'Y-m-d');
|
|
} else {
|
|
$data['source_policy_end_date'] = null;
|
|
}
|
|
|
|
// convert the date
|
|
// Clean the input and handle empty strings
|
|
$reminderDate = trim($data['next_reminder_date'] ?? '');
|
|
|
|
if ($reminderDate !== '' && $reminderDate != null && $reminderDate != 0) {
|
|
$convertedDate = change_date_format($reminderDate);
|
|
$data['next_reminder_date'] = $convertedDate ?: null;
|
|
} else {
|
|
$data['next_reminder_date'] = null;
|
|
}
|
|
|
|
//convert 0 and 1
|
|
if (isset($data['is_insurer_auto_mail'])) {
|
|
$data['is_insurer_auto_mail'] = 1;
|
|
} else {
|
|
$data['is_insurer_auto_mail'] = 0;
|
|
}
|
|
|
|
// $file_name = file_Upload($files[$index], $uploadFilePath);
|
|
|
|
$last_3_years_claims = $data['finyear'];
|
|
|
|
$processedData[] = [
|
|
'lost_reason' => $data['lost_reason'] ?? null,
|
|
'actual_lead_id' => $data['actual_lead_id'] ?? null,
|
|
'lead_type' => $data['lead_type'],
|
|
'issuer' => $data['issuer'],
|
|
'client_type' => $data['client_type'],
|
|
'client_name' => $data['client_name'],
|
|
'client_short_name' => $data['client_short_name'],
|
|
'entity_type_id' => $data['entity_type_id'],
|
|
'client_code' => $data['client_code'],
|
|
'pan' => $data['pan'] ?? null,
|
|
'gst' => $data['gst'] ?? null,
|
|
'branch_name' => $data['branch_name'],
|
|
'branch_code' => $data['branch_code'],
|
|
'contact_person_name' => $data['contact_person_name'],
|
|
'contact_person_mobile' => $data['contact_person_mobile'],
|
|
'contact_person_email' => $data['contact_person_email'],
|
|
'client_id' => $data['client_id'] ?? 0,
|
|
'client_branch_id' => $data['client_branch_id'] ?? 0,
|
|
'is_client_created' => $data['is_client_created'] ?? null,
|
|
'source_policy_id' => $data['source_policy_id'] ?? 0,
|
|
'policy_type_id' => $value,
|
|
'salse_person_id' => $data['salse_person_id'] ?? 0,
|
|
'rfq_qcr_viewers' => $data['rfq_qcr_viewers'] ?? null,
|
|
'insurer_id' => $insurer_id ?? 0,
|
|
'insurer_branch_id' => $insurer_branch_id ?? 0,
|
|
'tpa_id' => $tpa_id ?? 0,
|
|
'tpa_branch_id' => $tpa_branch_id ?? 0,
|
|
'policy_start_date' => $policy_start_date,
|
|
'policy_end_date' => $policy_end_date,
|
|
'no_of_lives' => $data['no_of_lives'][$index] ?? null,
|
|
'incurred_claims' => $data['incurred_claims'][$index] ?? 0,
|
|
'location' => $data['location'][$index] ?? null,
|
|
'proposed_insurer_id' => $proposed_insurer_id ?? 0,
|
|
'proposed_insurer_branch_id' => $proposed_insurer_branch_id ?? 0,
|
|
'proposed_tpa_id' => $proposed_tpa_id ?? 0,
|
|
'proposed_tpa_branch_id' => $proposed_tpa_branch_id ?? 0,
|
|
|
|
'renewal_emp_count' => $data['renewal_emp_count'][$index] ?? 0,
|
|
'renewal_dept_count' => $data['renewal_dept_count'][$index] ?? 0,
|
|
'renewal_no_of_lives' => $data['renewal_no_of_lives'][$index] ?? 0,
|
|
'incept_emp_count' => $data['incept_emp_count'][$index] ?? 0,
|
|
'incept_dept_count' => $data['incept_dept_count'][$index] ?? 0,
|
|
'incept_no_of_lives' => $data['incept_no_of_lives'][$index] ?? 0,
|
|
'exp_emp_count' => $data['exp_emp_count'][$index] ?? 0,
|
|
'exp_dept_count' => $data['exp_dept_count'][$index] ?? 0,
|
|
'exp_no_of_lives' => $data['exp_no_of_lives'][$index] ?? 0,
|
|
|
|
'incurred_claims_date' => $incurred_claims_date,
|
|
'paid_claims' => $data['paid_claims'][$index] ?? 0,
|
|
'outstanding_claims' => $data['outstanding_claims'][$index] ?? 0,
|
|
'policy_run_days' => $data['policy_run_days'][$index] ?? 0,
|
|
'premium_at_inception' => $data['premium_at_inception'][$index] ?? 0,
|
|
'premium_date' => $data['premium_date'][$index] ?? 0,
|
|
'earned_premium' => $data['earned_premium'][$index] ?? 0,
|
|
'annualised_claims' => $data['annualised_claims'][$index] ?? 0,
|
|
'incurred_claims_ratio' => $data['incurred_claims_ratio'][$index] ?? 0,
|
|
'earned_claims_ratio' => $data['earned_claims_ratio'][$index] ?? 0,
|
|
'total_si_at_incept' => $data['total_si_at_incept'][$index] ?? 0,
|
|
'total_si_at_renewal' => $data['total_si_at_renewal'][$index] ?? 0,
|
|
|
|
'total_lives_at_incept' => $data['total_lives_at_incept'][$index] ?? 0,
|
|
'premium_at_incept' => $data['premium_at_incept'][$index] ?? 0,
|
|
'fin_years_claims' => $last_3_years_claims,
|
|
|
|
// 'file_name' => $file_name,
|
|
'multi_file_data' => $multi_file_data ?? null,
|
|
|
|
'status' => $data['status'] ?? null,
|
|
'notes' => $data['notes'] ?? null,
|
|
|
|
'lead_form_type' => $data['lead_form_type'] ?? 1,
|
|
'custom_fields' => $data['custom_fields'] ?? null,
|
|
|
|
'source_policy_start_date' => $data['source_policy_start_date'] ?? null,
|
|
'source_policy_end_date' => $data['source_policy_end_date'] ?? null,
|
|
'claim_history' => $data['claim_history'] ?? 0,
|
|
|
|
'next_reminder_date' => $data['next_reminder_date'] ?? null,
|
|
'is_insurer_auto_mail' => $data['is_insurer_auto_mail'] ?? 0,
|
|
];
|
|
}
|
|
// print_r($processedData);die();
|
|
return $processedData;
|
|
}
|
|
|
|
private function insertNewLead($data)
|
|
{
|
|
$insertCount = [];
|
|
foreach ($data as $value) {
|
|
$insert = $this->leadsModel->insert($value);
|
|
|
|
if ($insert) {
|
|
$this->insertMultiFilesData($value['multi_file_data'], $insert);
|
|
}
|
|
|
|
$insertCount[] = $insert;
|
|
$this->insertLeadStatus($insert, $value['status'], 3);
|
|
|
|
// if (in_array((int) $value['lead_type'], [1, 3], true) && $value['status'] == 'won') {
|
|
// $leadDataForClient = $this->leadsModel->find($insert);
|
|
// $this->createClientWithLeadData($leadDataForClient);
|
|
// }
|
|
|
|
if ($value['lead_form_type'] == 1) {
|
|
//for this push the job to the calculateMembersDemography() function
|
|
$job_details = new Jobs();
|
|
// $r = Jobs::addJob(['job_name' => 'memberDataListExcelFileFormatValidation', 'payload' => [
|
|
// 'lead_id' => $insert,
|
|
// ]]);
|
|
$r = Jobs::addJob(['job_name' => 'calculateMembersDemography', 'payload' => [
|
|
'lead_id' => $insert,
|
|
]]);
|
|
}
|
|
}
|
|
|
|
if (count($insertCount) > 0) {
|
|
return $this->respond(['status' => true, 'lead_id' => $insert, 'message' => 'New Opportunity created successfully', 'data' => $data], 200);
|
|
}
|
|
|
|
return $this->respond(['status' => false, 'lead_id' => $insert, 'message' => "Failed to create Opportunity", 'data' => $data], 200);
|
|
}
|
|
|
|
private function updateOldLead($id, $data)
|
|
{
|
|
if ($this->leadsModel->where('id', $id)->set($data[0])->update()) {
|
|
|
|
$this->insertMultiFilesData($data[0]['multi_file_data'], $id, $data[0]['lead_form_type']);
|
|
$this->insertLeadStatus($id, $data[0]['status'], 3);
|
|
|
|
// if (in_array((int) $data[0]['lead_type'], [1, 3], true) && $data[0]['status'] == 'won') {
|
|
// $leadDataForClient = $this->leadsModel->find($id);
|
|
// if (empty($leadDataForClient['is_client_created'])) {
|
|
// $this->createClientWithLeadData($leadDataForClient);
|
|
// }
|
|
// }
|
|
|
|
return $this->respond(['status' => true, 'lead_id' => $id, 'message' => "Opportunity updated successfully", 'data' => $data], 200);
|
|
}
|
|
return $this->respond(['status' => false, 'lead_id' => $id, 'message' => "Failed to update Opportunity", 'data' => $data], 200);
|
|
}
|
|
|
|
// Get the Single Lead data for edit uisng ajax (do not delete)
|
|
public function getLeadDataForEdit($id)
|
|
{
|
|
|
|
$data = $this->leadsModel
|
|
->where('leads.id', $id)
|
|
->where('leads.is_active', 1)
|
|
->first();
|
|
|
|
$data['lead_edit_data'] = $this->leadsModel
|
|
->where('leads.id', $id)
|
|
->where('leads.is_active', 1)
|
|
->first();
|
|
|
|
if (! empty($data['policy_start_date'])) {
|
|
$data['policy_start_date'] = change_date_format($data['policy_start_date'], 'Y-m-d', 'd/m/Y');
|
|
} else {
|
|
$data['policy_start_date'] = null;
|
|
}
|
|
|
|
if (! empty($data['policy_end_date'])) {
|
|
$data['policy_end_date'] = change_date_format($data['policy_end_date'], 'Y-m-d', 'd/m/Y');
|
|
} else {
|
|
$data['policy_end_date'] = null;
|
|
}
|
|
|
|
if (! empty($data['incurred_claims_date'])) {
|
|
$data['incurred_claims_date'] = change_date_format($data['incurred_claims_date'], 'Y-m-d', 'd/m/Y');
|
|
} else {
|
|
$data['incurred_claims_date'] = null;
|
|
}
|
|
|
|
// if (!empty($data['premium_date'])) {
|
|
// $data['premium_date'] = change_date_format($data['premium_date'], 'Y-m-d', 'd/m/Y');
|
|
// } else {
|
|
// $data['premium_date'] = null;
|
|
// }
|
|
|
|
$data['multi_file_data'] = $this->leadFilesModel
|
|
->where('lead_id', $id)
|
|
->where('type !=', 2)
|
|
->where('is_active', 1)
|
|
->first() ?? null;
|
|
|
|
$data['lastFiveYears'] = $this->getLastFiveFinancialYears();
|
|
$data['gpaClaimType'] = $this->claim_type_for_gpa;
|
|
$data['causeOfDeath'] = $this->cause_of_death;
|
|
|
|
if (! empty($data['fin_years_claims'])) {
|
|
$decoded = json_decode($data['fin_years_claims'], true);
|
|
$data['lead_edit_data']['fin_years_claims_array'] = isset($decoded['finyear']) ? $decoded['finyear'] : [];
|
|
} else {
|
|
$data['lead_edit_data']['fin_years_claims_array'] = [];
|
|
}
|
|
|
|
$data['html'] = $this->generateViewPageHtml($data['policy_type_id'], $data) ?? "";
|
|
|
|
// print_r($data); die;
|
|
|
|
if ($data) {
|
|
return $this->respond(['status' => true, 'data' => $data], 200);
|
|
} else {
|
|
return $this->respond(['status' => false], 200);
|
|
}
|
|
}
|
|
|
|
private function insertLeadStatus($primaryKey, $status, $statusType)
|
|
{
|
|
$statusData = [
|
|
'policy_tran_id' => $primaryKey,
|
|
'status' => $status,
|
|
'status_type' => $statusType,
|
|
'created_by' => get_session_userid(),
|
|
];
|
|
$this->policyTransactionStatusModel->insert($statusData);
|
|
}
|
|
|
|
public function uploadMultiFiles($files, $docs_names, $primaryKey)
|
|
{
|
|
$uploadFilePath = WRITEPATH . 'uploads/lead_files/';
|
|
|
|
$multi_file_data = [];
|
|
foreach ($files as $index => $value) {
|
|
$file_name = storage_file_Upload($value, $uploadFilePath, UPLOAD_EXT_LEAD_FILES);
|
|
$multi_file_data[] = [
|
|
'file_name' => $file_name,
|
|
'docs_name' => $docs_names[$index] ?? '',
|
|
'id' => $primaryKey[$index] ?? "",
|
|
];
|
|
}
|
|
|
|
return $multi_file_data;
|
|
}
|
|
|
|
public function insertMultiFilesData($data, $lead_id, $lead_form_type = null)
|
|
{
|
|
log_message('info', 'insertMultiFilesData() called with lead_id: ' . $lead_id);
|
|
|
|
if (! empty($data)) {
|
|
log_message('info', 'Data is not empty. Total items: ' . count($data));
|
|
|
|
foreach ($data as $key => $value) {
|
|
log_message('info', "Processing item at index {$key}: " . json_encode($value));
|
|
|
|
if (! empty($value['id'])) {
|
|
log_message('info', "Record with ID {$value['id']} exists. Preparing to update.");
|
|
|
|
$lead_file_data = [
|
|
'lead_id' => $lead_id,
|
|
'docs_name' => $value['docs_name'],
|
|
];
|
|
|
|
if (! empty($value['file_name'])) {
|
|
$lead_file_data['file_name'] = $value['file_name'];
|
|
log_message('info', "file_name found: {$value['file_name']}");
|
|
|
|
if (! empty($lead_form_type) && $lead_form_type == 1 && $key == 0) {
|
|
//for this push the job to the calculateMembersDemography() function
|
|
$job_details = new Jobs();
|
|
// $r = Jobs::addJob(['job_name' => 'memberDataListExcelFileFormatValidation', 'payload' => [
|
|
// 'lead_id' => $lead_id,
|
|
// ]]);
|
|
$r = Jobs::addJob(['job_name' => 'calculateMembersDemography', 'payload' => [
|
|
'lead_id' => $lead_id,
|
|
]]);
|
|
log_message('info', "calculateMembersDemography JOB PUSHED");
|
|
}
|
|
}
|
|
|
|
log_message('info', "Updating leadFilesModel where id = {$value['id']} with data: " . json_encode($lead_file_data));
|
|
$this->leadFilesModel->where('id', $value['id'])->set($lead_file_data)->update();
|
|
} else {
|
|
log_message('info', "No ID found. Preparing to insert new record.");
|
|
|
|
if (! empty($value['file_name'])) {
|
|
$lead_file_data = [
|
|
'lead_id' => $lead_id,
|
|
'docs_name' => $value['docs_name'],
|
|
'file_name' => $value['file_name'],
|
|
];
|
|
|
|
log_message('info', "Inserting into leadFilesModel: " . json_encode($lead_file_data));
|
|
$this->leadFilesModel->insert($lead_file_data);
|
|
} else {
|
|
log_message('warning', "Skipped insert: file_name missing in data at index {$key}");
|
|
}
|
|
}
|
|
|
|
if ($key == 0 && ! empty($value['file_name'])) {
|
|
log_message('info', "Setting first file_name '{$value['file_name']}' to leadsModel for lead_id: {$lead_id}");
|
|
$this->leadsModel->where('id', $lead_id)->set('file_name', $value['file_name'])->update();
|
|
}
|
|
}
|
|
} else {
|
|
log_message('warning', 'insertMultiFilesData() received empty data array.');
|
|
}
|
|
|
|
log_message('info', 'insertMultiFilesData() completed successfully.');
|
|
return true;
|
|
}
|
|
|
|
public function removeMultiFile()
|
|
{
|
|
$id = $this->request->getGet('lead_file_id');
|
|
if (! empty($id)) {
|
|
$this->leadFilesModel->where('id', $id)->set(['is_active' => 0])->update();
|
|
return $this->respond(['status' => true, 'message' => 'File removed successfully'], 200);
|
|
} else {
|
|
return $this->respond(['status' => false, 'message' => 'File could not be removed.'], 200);
|
|
}
|
|
}
|
|
|
|
public function uploadLeadAttachment()
|
|
{
|
|
try {
|
|
$leadId = (int) $this->request->getPost('lead_id');
|
|
$docsName = trim($this->request->getPost('docs_name') ?? '');
|
|
|
|
if ($leadId <= 0) {
|
|
return $this->respond(['status' => 'error', 'code' => 400, 'message' => 'Invalid lead id'], 400);
|
|
}
|
|
if (empty($docsName)) {
|
|
return $this->respond(['status' => 'error', 'code' => 400, 'message' => 'Document label is required'], 400);
|
|
}
|
|
|
|
$file = $this->request->getFile('attachment_file');
|
|
if (! $file || ! $file->isValid() || $file->hasMoved()) {
|
|
return $this->respond(['status' => 'error', 'code' => 400, 'message' => 'Invalid or missing file'], 400);
|
|
}
|
|
|
|
$uploadFilePath = WRITEPATH . 'uploads/lead_files/';
|
|
$fileName = storage_file_Upload($file, $uploadFilePath, UPLOAD_EXT_LEAD_FILES);
|
|
|
|
if (empty($fileName)) {
|
|
return $this->respond(['status' => 'error', 'code' => 400, 'message' => 'File upload failed. Check file type or size.'], 400);
|
|
}
|
|
|
|
$this->leadFilesModel->insert([
|
|
'lead_id' => $leadId,
|
|
'docs_name' => $docsName,
|
|
'file_name' => $fileName,
|
|
]);
|
|
|
|
// Return refreshed attachment HTML
|
|
$attachments = $this->leadFilesModel
|
|
->where('lead_id', $leadId)
|
|
->where('type !=', 2)
|
|
->where('is_active', 1)
|
|
->findAll();
|
|
|
|
$attachmentHtml = view('rfq/attachment_files', ['multi_file_data' => $attachments]);
|
|
|
|
return $this->respond([
|
|
'status' => 'success',
|
|
'code' => 200,
|
|
'message' => 'File uploaded successfully',
|
|
'attachment_html' => $attachmentHtml,
|
|
], 200);
|
|
|
|
} catch (\Throwable $e) {
|
|
$this->myLogger->logme('error', 'uploadLeadAttachment: ' . $e->getMessage());
|
|
return $this->respond(['status' => 'error', 'code' => 500, 'message' => 'Upload failed'], 500);
|
|
}
|
|
}
|
|
|
|
//--------RFQ-----------------------------------------------------------------------------------------------
|
|
|
|
// public function viewRFQ($id, $type = 1)
|
|
// {
|
|
|
|
// $data['rfq_data'] = $this->RFQModel
|
|
// ->where('lead_id', $id)
|
|
// // ->where('type', $type)
|
|
// ->where('is_active', 1)
|
|
// ->orderBy('id', 'desc')
|
|
// ->first();
|
|
// // dd($data);
|
|
|
|
// $data['rfq_count'] = $this->RFQModel
|
|
// ->where('lead_id', $id)
|
|
// // ->where('type', 1)
|
|
// ->where('is_active', 1)
|
|
// ->countAllResults();
|
|
|
|
// $data['qcr_count'] = $this->RFQModel
|
|
// ->where('lead_id', $id)
|
|
// ->where('type', 2)
|
|
// ->where('is_active', 1)
|
|
// ->countAllResults();
|
|
|
|
// // dd(count($data['rfq_data']));
|
|
|
|
// $data['lead_id'] = $id;
|
|
// $lead_data = $this->leadsModel
|
|
// ->select('
|
|
// leads.*,
|
|
// policy_type.question_json,
|
|
// policy_type.policy_type,
|
|
// policy_type.long_name,
|
|
// user_profiles.email as created_person_email
|
|
// ')
|
|
// ->join('policy_type', 'leads.policy_type_id = policy_type.id')
|
|
// ->join('user_profiles', 'leads.created_by = user_profiles.id', 'left')
|
|
// ->where('leads.id', $id)
|
|
// ->where('leads.is_active', 1)
|
|
// ->first();
|
|
|
|
// // dd($lead_data);
|
|
|
|
// if ($lead_data['lead_type'] != 1) {
|
|
// $client_policy_data = $this->clientPolicyModel->where('is_active', 1)->where('id', $lead_data['source_policy_id'])->first();
|
|
// if (isset($client_policy_data)) {
|
|
// $data['policy_terms'] = $client_policy_data['policy_terms'];
|
|
// }
|
|
// }
|
|
|
|
// $data['question_json'] = $lead_data['question_json'];
|
|
// $data['page_name'] = $type == 2 ? 'QCR' : 'RFQ';
|
|
// $data['insurer'] = $this->insurerBranchModel->getInsurerBranchesWithInsurerNames();
|
|
// $data['userList'] = $this->userModel->getUserListForRFQ();
|
|
// $data['exclusiveUserList'] = $this->userModel->getexclusiveUserListForRFQ();
|
|
// $data['lead_data'] = $lead_data;
|
|
// $data['tpa_list'] = $this->tpaBranchModel->getTpaBranchesWithTpaNames();
|
|
// $data['account_manager'] = $this->userModel->where('is_active', 1)->where('role', 3)->findAll();
|
|
|
|
// $mail_content = '
|
|
// <p>Dear Sir,</p>
|
|
// <p>Greetings From Nhance India!</p>
|
|
// <p>Please find attached the {{RFQ_OR_QCR}} for <strong>{{POLICY_TYPE}}</strong> policy pertaining to <strong>{{CLIENT_NAME}}</strong>.</p>
|
|
// <p>Kindly request you to share the competitive quotes at the earliest.</p>
|
|
// <p>In case of any query, please feel free to contact us.</p>
|
|
// <p>Thank You!</p><br>
|
|
// <p>Best regards,</p>
|
|
|
|
// <div style=\"margin: 0; padding: 0; line-height: 1.2;\">
|
|
// <div>{{LOGGED_USER_NAME}}</div>
|
|
// <div>Mobile: {{LOGGED_USER_MOBILE}}</div>
|
|
// </div>
|
|
|
|
// <img src="{{LOGO_PATH}}" alt="Nhance Logo" width="100" style="margin-top:10px;">
|
|
// ';
|
|
|
|
// if ($data['lead_data']['policy_end_date'] != null) {
|
|
// $subject = "{{CLIENT_NAME}} _ {{POLICY_TYPE}} _ {{RFQ_OR_QCR}} _ {{POLICY_YEAR}} {{POLICY_END_DATE}}";
|
|
// } else {
|
|
// $subject = "{{CLIENT_NAME}} _ {{POLICY_TYPE}} _ {{RFQ_OR_QCR}} _ {{POLICY_YEAR}}";
|
|
// }
|
|
|
|
// if ($lead_data['policy_type_id'] == 1) {
|
|
// $data['totalSumAssured'] = $this->handleMemberDataGPATotalSumInsurerFromExcel(['lead_id' => $id]);
|
|
// } else {
|
|
// $data['totalSumAssured'] = [];
|
|
// }
|
|
|
|
// $data['mail_content'] = $this->transformMailContent($lead_data, $mail_content, $data['page_name']);
|
|
// $data['subject'] = $this->transformMailContent($lead_data, $subject, $data['page_name']);
|
|
|
|
// $data['placement_mail_content'] = $this->transformMailContent($lead_data, $mail_content, 'Placement');
|
|
// $data['placement_subject'] = $this->transformMailContent($lead_data, $subject, 'Placement');
|
|
|
|
// $data['multi_file_data'] = $this->leadFilesModel->where('lead_id', $id)->where('is_active', 1)->findAll() ?? null;
|
|
// $installment_data['installments'] = $this->leadInstallmentPaymentDetails->where('lead_id', $id)->where('is_active', 1)->findAll() ?? null;
|
|
// $data['lead_data']['installment_data'] = view('rfq/installment_fields', $installment_data) ?? null;
|
|
// $data['attachment_html'] = view('rfq/attachment_files', $data) ?? "";
|
|
// $data['user_team'] = $this->userModel->select("ut.team_id")->join("user_teams ut", "ut.user_id = user_profiles.id and ut.is_active = 1")->where("user_profiles.is_active", 1)->first()['team_id'];
|
|
// $data['multi_file_data_html'] = $this->renderFileFields($data['multi_file_data']);
|
|
// // dd($data);
|
|
|
|
// if ($data['lead_data']['lead_form_type'] == 1) {
|
|
// $data['demogrphy_html_data'] = $this->generateDemographyDataTable(['lead_id' => $id]);
|
|
// $this->loadLayout('view_rfq.php', $data);
|
|
// } else if ($data['lead_data']['lead_form_type'] == 2) {
|
|
|
|
// $data['occupancy'] = $this->occupancyModel->findAll();
|
|
// // dd($data['occupancy']);
|
|
|
|
// if ($lead_data['lead_type'] != 1 && $data['rfq_count'] == 0) {
|
|
// $client_policy_data = $this->clientPolicyModel->where('is_active', 1)->where('id', $lead_data['source_policy_id'])->first();
|
|
// if (isset($client_policy_data)) {
|
|
|
|
// $data['rfq_data']['json'] = $client_policy_data['placement_json'];
|
|
// }
|
|
// }
|
|
|
|
// if (!empty($data['question_json'])) {
|
|
// $data['policies'] = json_decode($data['question_json'], true)['policies'];
|
|
// $data["child_table_data"] = json_decode($data['question_json'], true)['child_table_data'];
|
|
// }
|
|
|
|
// $data['product'] = $this->leadsModel->select("policy_type.policy_type")->join('policy_type', 'leads.policy_type_id = policy_type.id')->where('leads.id', $id)->first()['policy_type'];
|
|
// // $data['lead_register_data'] = json_decode($data['lead_data']['custom_fields']);
|
|
// // dd($data['lead_register_data']);
|
|
// // $data['entity_type'] = $this->kycEntityTypeModel->where('is_active', 1)->findAll();
|
|
// $data['buisness_type'] = $this->buisnessType;
|
|
|
|
// // dd($data);
|
|
// $data['client_type'] = $this->clientType;
|
|
// $this->loadLayout('view_rfq_non_eb', $data);
|
|
// }
|
|
// }
|
|
|
|
public function viewRFQ($id, $type = 1)
|
|
{
|
|
// 1. Combine RFQ queries into a single query
|
|
$rfqStats = $this->RFQModel
|
|
->select('
|
|
COUNT(*) as total_count,
|
|
SUM(CASE WHEN type != 2 THEN 1 ELSE 0 END) as rfq_count,
|
|
SUM(CASE WHEN type = 2 THEN 1 ELSE 0 END) as qcr_count
|
|
')
|
|
->where('lead_id', $id)
|
|
->where('is_active', 1)
|
|
->first();
|
|
|
|
$data['rfq_count'] = $rfqStats['rfq_count'] ?? 0;
|
|
$data['qcr_count'] = $rfqStats['qcr_count'] ?? 0;
|
|
|
|
// 2. Get RFQ data separately (only if needed)
|
|
$data['rfq_data'] = $this->RFQModel
|
|
->where('lead_id', $id)
|
|
->where('is_active', 1)
|
|
->orderBy('id', 'desc')
|
|
->first();
|
|
|
|
$data['lead_id'] = $id;
|
|
|
|
// 3. Optimize lead data query with specific field selection
|
|
$lead_data = $this->leadsModel
|
|
->select('
|
|
leads.*,
|
|
lead_files.status as demography_file_status,
|
|
policy_type.question_json,
|
|
policy_type.policy_type,
|
|
policy_type.long_name,
|
|
user_profiles.email as created_person_email
|
|
')
|
|
->join('policy_type', 'leads.policy_type_id = policy_type.id')
|
|
->join('user_profiles', 'leads.created_by = user_profiles.id', 'left')
|
|
->join('lead_files', 'leads.id = lead_files.lead_id AND lead_files.type = 2 AND lead_files.is_active = 1', 'left')
|
|
->where('leads.id', $id)
|
|
->where('leads.is_active', 1)
|
|
->first();
|
|
|
|
if (! $lead_data) {
|
|
// Handle case where lead doesn't exist
|
|
throw new \Exception('Opportunity not found');
|
|
}
|
|
|
|
// 4. Conditional query - only fetch if needed
|
|
if (! in_array((int) $lead_data['lead_type'], [1, 3], true)) {
|
|
$client_policy_data = $this->clientPolicyModel
|
|
->select('policy_terms, placement_json')
|
|
->where('is_active', 1)
|
|
->where('id', $lead_data['source_policy_id'])
|
|
->first();
|
|
|
|
if ($client_policy_data) {
|
|
$data['policy_terms'] = $client_policy_data['policy_terms'];
|
|
|
|
// Store for later use in lead_form_type == 2 condition
|
|
if ($lead_data['lead_form_type'] == 2 && $data['rfq_count'] == 0) {
|
|
$data['rfq_data']['json'] = $client_policy_data['placement_json'];
|
|
}
|
|
}
|
|
}
|
|
|
|
// 5. Cache decoded JSON to avoid multiple decodes
|
|
$question_json_decoded = ! empty($lead_data['question_json'])
|
|
? json_decode($lead_data['question_json'], true)
|
|
: null;
|
|
|
|
$data['question_json'] = $lead_data['question_json'];
|
|
$data['tab_name'] = $type == 2 ? 'QCR' : 'RFQ';
|
|
$data['page_name'] = $type == 2 ? 'QCR' : 'RFQ';
|
|
$data['lead_data'] = $lead_data;
|
|
|
|
// 6. Parallel/batch data fetching for independent queries
|
|
$data['insurer'] = $this->insurerBranchModel->getInsurerBranchesWithInsurerNames();
|
|
$data['userList'] = $this->userModel->getUserListForRFQ();
|
|
$data['exclusiveUserList'] = $this->userModel->getexclusiveUserListForRFQ();
|
|
$data['tpa_list'] = $this->tpaBranchModel->getTpaBranchesWithTpaNames();
|
|
$data['account_manager'] = $this->userModel
|
|
->where('is_active', 1)
|
|
->where('role', 3)
|
|
->findAll();
|
|
|
|
// 7. Define mail templates as constants or config
|
|
$mail_content = $this->getMailTemplate();
|
|
$placement_mail_content = $this->getMailTemplate('placement');
|
|
$subject = $this->getSubjectTemplate($lead_data);
|
|
|
|
// 8. Pre-calculate sum assured only for GPA
|
|
$data['totalSumAssured'] = ($lead_data['policy_type_id'] == 1) ? $this->handleMemberDataGPATotalSumInsurerFromExcel(['lead_id' => $id]) : [];
|
|
|
|
// 9. Transform mail content once
|
|
$data['mail_content'] = $this->transformMailContent($lead_data, $mail_content, $data['page_name']);
|
|
$data['subject'] = $this->transformMailContent($lead_data, $subject, $data['page_name']);
|
|
$data['placement_mail_content'] = $this->transformMailContent($lead_data, $placement_mail_content, 'Placement');
|
|
$data['placement_subject'] = $this->transformMailContent($lead_data, $subject, 'Placement');
|
|
|
|
// 10. Combine related queries
|
|
$data['multi_file_data'] = $this->leadFilesModel
|
|
->where('lead_id', $id)
|
|
->where('type !=', 2)
|
|
->where('is_active', 1)
|
|
->findAll();
|
|
|
|
$installment_data['installments'] = $this->leadInstallmentPaymentDetails
|
|
->where('lead_id', $id)
|
|
->where('is_active', 1)
|
|
->findAll();
|
|
|
|
// 11. Generate views efficiently
|
|
$data['lead_data']['installment_data'] = ! empty($installment_data['installments'])
|
|
? view('rfq/installment_fields', $installment_data)
|
|
: null;
|
|
|
|
$data['attachment_html'] = view('rfq/attachment_files', $data);
|
|
|
|
$user_team = $this->userModel
|
|
->select("ut.team_id")
|
|
->join("user_teams ut", "ut.user_id = user_profiles.id and ut.is_active = 1")
|
|
->where("user_profiles.is_active", 1)
|
|
->first();
|
|
$data['user_team'] = $user_team['team_id'] ?? null;
|
|
|
|
$data['multi_file_data_html'] = $this->renderFileFields($data['multi_file_data']);
|
|
|
|
// 12. Conditional rendering based on lead_form_type
|
|
if ($lead_data['lead_form_type'] == 1) {
|
|
// $data['demogrphy_html_data'] = $this->generateDemographyDataTable(['lead_id' => $id]);
|
|
$this->loadLayout('view_rfq.php', $data);
|
|
} else if ($lead_data['lead_form_type'] == 2) {
|
|
$data['occupancy'] = $this->occupancyModel->findAll();
|
|
|
|
// Use cached decoded JSON
|
|
if ($question_json_decoded) {
|
|
$data['policies'] = $question_json_decoded['policies'] ?? [];
|
|
$data["child_table_data"] = $question_json_decoded['child_table_data'] ?? [];
|
|
}
|
|
|
|
$data['product'] = $lead_data['policy_type'];
|
|
$data['buisness_type'] = $this->buisnessType;
|
|
$data['client_type'] = $this->clientType;
|
|
|
|
$this->loadLayout('view_rfq_non_eb', $data);
|
|
}
|
|
}
|
|
|
|
// 13. Extract mail template to separate method for reusability
|
|
private function getMailTemplate($template_type = "")
|
|
{
|
|
if ($template_type == 'placement') {
|
|
return '
|
|
<p>Dear Sir,</p>
|
|
<p>Greetings From Nhance India!</p>
|
|
<p>Please find attached the {{RFQ_OR_QCR}} for <strong>{{POLICY_TYPE}}</strong> policy pertaining to <strong>{{CLIENT_NAME}}</strong>.</p>
|
|
<p>Kindly request you to issue the policy at the earliest.</p>
|
|
<p>In case of any query, please feel free to contact us.</p>
|
|
<p>Thank You!</p><br>
|
|
<p>Best regards,</p>
|
|
|
|
<div style="margin: 0; padding: 0; line-height: 1.2;">
|
|
<div>{{LOGGED_USER_NAME}}</div>
|
|
<div>Mobile: {{LOGGED_USER_MOBILE}}</div>
|
|
</div>
|
|
|
|
<img src="{{LOGO_PATH}}" alt="Nhance Logo" width="100" style="margin-top:10px;">
|
|
';
|
|
} else {
|
|
return '
|
|
<p>Dear Sir,</p>
|
|
<p>Greetings From Nhance India!</p>
|
|
<p>Please find attached the {{RFQ_OR_QCR}} for <strong>{{POLICY_TYPE}}</strong> policy pertaining to <strong>{{CLIENT_NAME}}</strong>.</p>
|
|
<p>Kindly request you to share the competitive quotes at the earliest.</p>
|
|
<p>In case of any query, please feel free to contact us.</p>
|
|
<p>Thank You!</p><br>
|
|
<p>Best regards,</p>
|
|
|
|
<div style="margin: 0; padding: 0; line-height: 1.2;">
|
|
<div>{{LOGGED_USER_NAME}}</div>
|
|
<div>Mobile: {{LOGGED_USER_MOBILE}}</div>
|
|
</div>
|
|
|
|
<img src="{{LOGO_PATH}}" alt="Nhance Logo" width="100" style="margin-top:10px;">
|
|
';
|
|
}
|
|
}
|
|
|
|
// 14. Extract subject template to separate method
|
|
private function getSubjectTemplate($lead_data)
|
|
{
|
|
return $lead_data['policy_end_date'] != null
|
|
? "{{CLIENT_NAME}} _ {{POLICY_TYPE}} _ {{RFQ_OR_QCR}} _ {{POLICY_YEAR}} {{POLICY_END_DATE}}"
|
|
: "{{CLIENT_NAME}} _ {{POLICY_TYPE}} _ {{RFQ_OR_QCR}} _ {{POLICY_YEAR}}";
|
|
}
|
|
|
|
public function savePolicyInfo()
|
|
{
|
|
|
|
$data = $this->request->getPost();
|
|
|
|
$lead_id = $data['lead_id'];
|
|
$json_data = $data['registration_json'];
|
|
|
|
$existingJson = $this->RFQModel->where('is_active', 1)->where("lead_id", $lead_id)->first()['registration_json'] ?? null;
|
|
|
|
if (empty($existingJson)) {
|
|
$this->RFQModel
|
|
->where('lead_id', $lead_id)
|
|
->where('type', 1)
|
|
->where('is_active', 1)
|
|
->set('is_active', 0)
|
|
->update();
|
|
|
|
$insertData['lead_id'] = $lead_id;
|
|
$insertData['registration_json'] = json_encode($json_data);
|
|
|
|
$this->RFQModel->insert($insertData);
|
|
|
|
return $this->respond(['status' => true, "message" => "Policy Inforamtion saved"]);
|
|
} else {
|
|
|
|
return $this->respond(['status' => true, "message" => "Policy Inforamtion Already saved"]);
|
|
}
|
|
}
|
|
|
|
public function createRFQ()
|
|
{
|
|
$data = $this->request->getPost();
|
|
$lead_id = $data['lead_id'] ?? null;
|
|
|
|
if (! $lead_id) {
|
|
return $this->respond(['status' => false, 'message' => 'Opportunity ID is required'], 400);
|
|
}
|
|
|
|
$rfq_created = $this->RFQModel->where('lead_id', $lead_id)->where('is_active', 1)->countAllResults();
|
|
$qcr_created = false;
|
|
$inputJson = json_decode($data['json'], true);
|
|
if (isset($inputJson['premium_data']) && ! empty($inputJson['premium_data'])) {
|
|
$sortedJson = $this->reorderProposalsByInsurerTotal($inputJson);
|
|
$data['json'] = json_encode($sortedJson);
|
|
$qcr_created = true;
|
|
}
|
|
|
|
$quote_received_insurer = [];
|
|
if (($data['submit_type'] ?? "") === 'QCR') {
|
|
|
|
$inputJson = json_decode($data['json'], true);
|
|
$proposal_data = $inputJson['proposal_data'] ?? array_pop($inputJson);
|
|
|
|
if (isset($proposal_data['over_all_column_data'])) {
|
|
$proposel_count = $proposal_data['over_all_column_data'];
|
|
|
|
$this->myLogger->logme("error", "insurer id : " . json_encode($proposel_count));
|
|
|
|
foreach ($proposel_count as $key => $value) {
|
|
if (! empty($value['insurers'])) {
|
|
$qcr_created = true;
|
|
|
|
foreach ($value['insurers'] as $insurer => $id) {
|
|
if (! empty($id['id'])) {
|
|
$quote_received_insurer[] = $id['id'];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$this->myLogger->logme("error", "quote_received_insurer : " . json_encode($quote_received_insurer));
|
|
$data['type'] = 1;
|
|
|
|
//update the quote received insurer data to the lead
|
|
if (count($quote_received_insurer) != 0) {
|
|
$this->leadsModel->update($lead_id, ['quote_received_insurer' => json_encode($quote_received_insurer ?? [])]);
|
|
$this->myLogger->logme("error", "quote_received_insurer data updated in the lead: " . json_encode($quote_received_insurer));
|
|
}
|
|
|
|
// Deactivate existing RFQs for this lead and type
|
|
if (! isset($data['rfq_primaryKey']) && empty($data['rfq_primaryKey'])) {
|
|
$this->RFQModel
|
|
->where('lead_id', $lead_id)
|
|
->where('type', 1)
|
|
->where('is_active', 1)
|
|
->set('is_active', 0)
|
|
->update();
|
|
}
|
|
|
|
// Handle registration_json
|
|
if (empty($data['registration_json'])) {
|
|
// Fetch the latest registration_json if not provided
|
|
$latest = $this->RFQModel
|
|
->select('registration_json')
|
|
->where('lead_id', $lead_id)
|
|
->orderBy('id', 'DESC')
|
|
->first();
|
|
|
|
if (! empty($latest['registration_json'])) {
|
|
$data['registration_json'] = $latest['registration_json'];
|
|
}
|
|
}
|
|
|
|
// print_r($data); die;
|
|
// $data['json'] = "";
|
|
if (isset($data['rfq_primaryKey']) && ! empty($data['rfq_primaryKey'])) {
|
|
$this->RFQModel->update($data['rfq_primaryKey'], $data);
|
|
$insertId = $data['rfq_primaryKey'];
|
|
$affectedRows = db_connect()->affectedRows();
|
|
} else {
|
|
// Insert new RFQ
|
|
$insertId = $this->RFQModel->insert($data);
|
|
}
|
|
|
|
if ($insertId) {
|
|
|
|
if (empty($rfq_created)) {
|
|
$this->leadsModel->update($lead_id, ['status' => "rfq_created"]);
|
|
}
|
|
|
|
if ($qcr_created == true) {
|
|
$this->leadsModel
|
|
->where('id', $lead_id)
|
|
->whereNotIn('status', ['qcr_sent', 'lost', 'co_insurer_pending', 'won', 'completed_with_corrections', 'completed_without_corrections'])
|
|
->set(['status' => "qcr_created"])
|
|
->update();
|
|
}
|
|
|
|
$message = ($data['submit_type'] ?? '') == 'QCR' ? 'QCR saved successfully' : 'RFQ saved successfully';
|
|
return $this->respond([
|
|
'status' => true,
|
|
'id' => $insertId,
|
|
'message' => $message,
|
|
'data' => $data,
|
|
'affectedRows' => $affectedRows ?? null,
|
|
], 200);
|
|
}
|
|
|
|
$message = ($data['submit_type'] ?? '') == 'QCR' ? 'Failed to save QCR' : 'Failed to save RFQ';
|
|
return $this->respond([
|
|
'status' => false,
|
|
'id' => null,
|
|
'message' => $message,
|
|
'data' => $data,
|
|
], 200);
|
|
}
|
|
|
|
public function createQCR()
|
|
{
|
|
|
|
$data = $this->request->getPost();
|
|
$lead_id = $data['lead_id'];
|
|
$data['type'] = 2;
|
|
|
|
$this->RFQModel
|
|
->where('lead_id', $lead_id)
|
|
->where('type', 2)
|
|
->where('is_active', 1)
|
|
->set('is_active', 0)
|
|
->update();
|
|
|
|
$result = $this->RFQModel->insert($data);
|
|
|
|
if ($result) {
|
|
return $this->respond(['status' => true, 'id' => $result, 'message' => 'QCR created successfully', 'data' => $data], 200);
|
|
}
|
|
|
|
return $this->respond(['status' => false, 'id' => $result, 'message' => "Failed to create QCR", 'data' => $data], 200);
|
|
}
|
|
|
|
public function reorderProposalsByInsurerTotal(array $data): array
|
|
{
|
|
|
|
if (! isset($data['premium_data']['data'])) {
|
|
return $data;
|
|
}
|
|
|
|
$original = $data['premium_data']['data'];
|
|
$proposals = [];
|
|
$others = [];
|
|
$emptyKeyData = [];
|
|
|
|
foreach ($original as $key => $value) {
|
|
// Match only keys that look like 'Proposal X'
|
|
if (preg_match('/^(Proposal\s+\d+|Existing Renewal|Existing Rollover)$/', $key)) {
|
|
// Get the insurer entry (not 'Quote Asked')
|
|
foreach ($value as $subKey => $subVal) {
|
|
if ($subKey !== 'Quote Asked' && isset($subVal['Total'])) {
|
|
$proposals[$key] = $value;
|
|
break;
|
|
} else {
|
|
$proposals[$key] = $value;
|
|
}
|
|
}
|
|
} else {
|
|
|
|
if ($key === '' && isset($value['']) && is_array($value[''])) {
|
|
// Capture empty key to push it later
|
|
$emptyKeyData[$key] = $value;
|
|
} else {
|
|
$others[$key] = $value;
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach ($proposals as $proposalKey => &$proposal) {
|
|
$quoteAsked = $proposal['Quote Asked']; // Keep Quote Asked separately
|
|
unset($proposal['Quote Asked']);
|
|
|
|
uasort($proposal, function ($a, $b) {
|
|
return $a['Total'] <=> $b['Total']; // Ascending by Total
|
|
});
|
|
|
|
// Add Quote Asked back at the top
|
|
$proposal = array_merge(['Quote Asked' => $quoteAsked], $proposal);
|
|
}
|
|
|
|
// Sort proposals by their insurer's total
|
|
uasort($proposals, function ($a, $b) {
|
|
$totalA = 0;
|
|
$totalB = 0;
|
|
|
|
foreach ($a as $key => $val) {
|
|
if ($key !== 'Quote Asked' && isset($val['Total'])) {
|
|
$totalA = floatval($val['Total']);
|
|
break;
|
|
}
|
|
}
|
|
|
|
foreach ($b as $key => $val) {
|
|
if ($key !== 'Quote Asked' && isset($val['Total'])) {
|
|
$totalB = floatval($val['Total']);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return $totalA <=> $totalB;
|
|
});
|
|
|
|
// Merge back the sorted proposals into the full structure
|
|
$data['premium_data']['data'] = array_merge($others, $proposals, $emptyKeyData);
|
|
$data = $this->reorderProposalDataByPremiumOrder($data);
|
|
return $data;
|
|
}
|
|
|
|
private function reorderProposalDataByPremiumOrder(array $data): array
|
|
{
|
|
if (! isset($data['premium_data']['data'], $data['proposal_data']['over_all_column_data'])) {
|
|
return $data;
|
|
}
|
|
|
|
$porposalData = $data['premium_data']['data'];
|
|
$premiumProposals = array_keys($data['premium_data']['data']);
|
|
$filteredProposals = [];
|
|
|
|
//Reorder the Insurer based on the Premium data insurer
|
|
foreach ($porposalData as $key => $value) {
|
|
|
|
if (in_array($key, ['Particulars', ""])) {
|
|
continue;
|
|
}
|
|
|
|
// Ensure the premium data is an array and not empty
|
|
if (! is_array($value) || empty($value)) {
|
|
continue;
|
|
}
|
|
|
|
// Step 1: Get the premium display_name order (excluding "Quote Asked")
|
|
$premiumOrder = array_keys(array_diff_key($value, ["Quote Asked" => ""]));
|
|
|
|
// Skip if no valid order found
|
|
if (empty($premiumOrder)) {
|
|
continue;
|
|
}
|
|
|
|
// usort($data['proposal_data']['over_all_column_data'][$key]['insurers'], function($a, $b) use ($premiumOrder) {
|
|
// return array_search($a['display_name'], $premiumOrder) - array_search($b['display_name'], $premiumOrder);
|
|
// });
|
|
|
|
// Step 2: Reorder proposal insurers based on premium order
|
|
usort($data['proposal_data']['over_all_column_data'][$key]['insurers'], function ($a, $b) use ($premiumOrder) {
|
|
$posA = array_search($a['display_name'] ?? '', $premiumOrder);
|
|
$posB = array_search($b['display_name'] ?? '', $premiumOrder);
|
|
|
|
// If not found, push to the end
|
|
$posA = $posA === false ? PHP_INT_MAX : $posA;
|
|
$posB = $posB === false ? PHP_INT_MAX : $posB;
|
|
|
|
return $posA - $posB;
|
|
});
|
|
|
|
}
|
|
|
|
// Collect proposal keys that match the pattern "Proposal X"
|
|
foreach ($premiumProposals as $key) {
|
|
if (preg_match('/^(Proposal\s+\d+|Existing Renewal|Existing Rollover)$/', $key) && isset($data['proposal_data']['over_all_column_data'][$key])) {
|
|
$filteredProposals[$key] = $data['proposal_data']['over_all_column_data'][$key];
|
|
}
|
|
}
|
|
|
|
// dd($premiumProposals, $filteredProposals);
|
|
|
|
$data['proposal_data']['over_all_column_data'] = $filteredProposals;
|
|
$data = $this->reorderProposalInHeaderAndData($data);
|
|
return $data;
|
|
}
|
|
|
|
private function reorderProposalInHeaderAndData(array $data): array
|
|
{
|
|
$tableData = $data['table_data'];
|
|
$sortedProposalOrder = $data['proposal_data']['over_all_column_data'];
|
|
$headers = $tableData['headers'] ?? [];
|
|
$dataRows = $tableData['data'] ?? [];
|
|
|
|
// Step 1: Separate static and proposal headers
|
|
$staticHeaders = [];
|
|
$proposalHeaders = [];
|
|
$actionHeader = [];
|
|
foreach ($headers as $header) {
|
|
if (in_array($header['parentHeader'], array_keys($sortedProposalOrder))) {
|
|
$proposalHeaders[$header['parentHeader']] = $header;
|
|
} else {
|
|
if ($header['parentHeader'] == "Action") {
|
|
$actionHeader[] = $header;
|
|
} else {
|
|
$staticHeaders[] = $header;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Reorder the SubHeader of the Proposel
|
|
foreach ($sortedProposalOrder as $proposalKey => $proposalData) {
|
|
// Skip if insurers or subHeaders are missing
|
|
if (
|
|
! isset($proposalData['insurers']) ||
|
|
! is_array($proposalData['insurers']) ||
|
|
! isset($proposalHeaders[$proposalKey]['subHeaders']) ||
|
|
! is_array($proposalHeaders[$proposalKey]['subHeaders'])
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
// Keep "Quote Asked" fixed at index 0
|
|
$newSubHeaders = ["Quote Asked"];
|
|
|
|
// Add insurers in the sorted order
|
|
foreach ($proposalData['insurers'] as $insurer) {
|
|
if (in_array($insurer['display_name'], $proposalHeaders[$proposalKey]['subHeaders'])) {
|
|
$newSubHeaders[] = $insurer['display_name'];
|
|
}
|
|
}
|
|
|
|
// Replace the subHeaders in the header array
|
|
$proposalHeaders[$proposalKey]['subHeaders'] = $newSubHeaders;
|
|
}
|
|
|
|
// dd($staticHeaders, $proposalHeaders, $sortedProposalOrder);
|
|
|
|
// Step 2: Reorder headers
|
|
$reorderedHeaders = [];
|
|
foreach ($sortedProposalOrder as $proposalKey => $proposalValue) {
|
|
if (isset($proposalHeaders[$proposalKey])) {
|
|
$reorderedHeaders[] = $proposalHeaders[$proposalKey];
|
|
}
|
|
}
|
|
|
|
// print_rr($reorderedHeaders); die;
|
|
$proposel_count = 1;
|
|
foreach ($reorderedHeaders as $key => &$value) {
|
|
if (! in_array($value['parentHeader'], ["Existing Renewal", "Existing Rollover"])) {
|
|
$value['parentHeader'] = 'Proposal ' . $proposel_count;
|
|
$proposel_count++;
|
|
}
|
|
}
|
|
unset($value);
|
|
|
|
//merge the all headers
|
|
$reorderedHeaders = array_merge($staticHeaders, $reorderedHeaders, $actionHeader);
|
|
|
|
// Step 3: Reorder each row's `data` by matching parentth
|
|
foreach ($dataRows as $dataRowIndex => &$row) {
|
|
$staticData = [];
|
|
$proposalData = [];
|
|
$actionData = [];
|
|
|
|
foreach ($row['data'] as $entry) {
|
|
if (in_array($entry['parentth'], array_keys($sortedProposalOrder))) {
|
|
$proposalData[$entry['parentth']][] = $entry;
|
|
} else {
|
|
if ($entry['parentth'] == "Action") {
|
|
$actionData[] = $entry;
|
|
} else {
|
|
$staticData[] = $entry;
|
|
}
|
|
}
|
|
}
|
|
|
|
$reorderedProposalData = [];
|
|
foreach ($sortedProposalOrder as $proposalKey => $proposalValue) {
|
|
if (isset($proposalData[$proposalKey])) {
|
|
foreach ($proposalData[$proposalKey] as $entry) {
|
|
$reorderedProposalData[] = $entry;
|
|
}
|
|
}
|
|
}
|
|
|
|
$dubParTh = "";
|
|
$increament = 0;
|
|
foreach ($reorderedProposalData as $key => &$value) {
|
|
|
|
if ($dubParTh == $value['parentth']) {
|
|
if (! in_array($value['parentth'], ["Existing Renewal", "Existing Rollover"])) {
|
|
$value['parentth'] = 'Proposal ' . ($increament);
|
|
}
|
|
} else {
|
|
$dubParTh = $value['parentth'];
|
|
if (! in_array($value['parentth'], ["Existing Renewal", "Existing Rollover"])) {
|
|
$increament = $increament + 1;
|
|
$value['parentth'] = 'Proposal ' . ($increament);
|
|
}
|
|
}
|
|
}
|
|
unset($value);
|
|
|
|
//Reorder the Row Data based on the Insurer
|
|
$reorderedProposalData = $this->reorderProposalRowData($reorderedProposalData, $proposalHeaders);
|
|
|
|
// print_rr($reorderedProposalData); die;
|
|
|
|
$row['data'] = array_merge($staticData, $reorderedProposalData, $actionData);
|
|
}
|
|
|
|
$data['table_data']['headers'] = $reorderedHeaders;
|
|
$data['table_data']['data'] = $dataRows;
|
|
|
|
$renumberedArray = $this->renumberProposalKeys($data['proposal_data']['over_all_column_data']);
|
|
$updatedDataSet = $this->renumberProposalKeys($data['premium_data']['data']);
|
|
$data['proposal_data']['over_all_column_data'] = ! empty($renumberedArray) ? $renumberedArray : $data['proposal_data']['over_all_column_data'];
|
|
$data['premium_data']['data'] = ! empty($updatedDataSet) ? $updatedDataSet : $data['premium_data']['data'];
|
|
|
|
return $data;
|
|
}
|
|
|
|
private function reorderProposalRowData(array $proposalRowData, array $proposalHeaderData): array
|
|
{
|
|
$newRowData = [];
|
|
|
|
// Group rows by parentth
|
|
$groupedRows = [];
|
|
foreach ($proposalRowData as $row) {
|
|
if (! isset($row['parentth'])) {
|
|
continue; // skip invalid rows
|
|
}
|
|
$groupedRows[$row['parentth']][] = $row;
|
|
}
|
|
|
|
// Reorder each group's rows based on header subHeaders
|
|
foreach ($proposalHeaderData as $proposalKey => $headerInfo) {
|
|
if (
|
|
! isset($groupedRows[$proposalKey]) ||
|
|
! isset($headerInfo['subHeaders']) ||
|
|
! is_array($headerInfo['subHeaders'])
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
$order = $headerInfo['subHeaders'];
|
|
$rows = $groupedRows[$proposalKey];
|
|
|
|
// Sort whole rows according to subth position in $order
|
|
usort($rows, function ($a, $b) use ($order) {
|
|
return array_search($a['subth'], $order) - array_search($b['subth'], $order);
|
|
});
|
|
|
|
// Append sorted rows to final array
|
|
$newRowData = array_merge($newRowData, $rows);
|
|
}
|
|
|
|
return $newRowData;
|
|
}
|
|
|
|
private function renumberProposalKeys(array $input): array
|
|
{
|
|
$result = [];
|
|
$counter = 1;
|
|
|
|
foreach ($input as $key => $value) {
|
|
if (strpos($key, 'Proposal') === 0) {
|
|
$newKey = 'Proposal ' . $counter++;
|
|
$result[$newKey] = $value;
|
|
} else {
|
|
$result[$key] = $value;
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
private function saveLeadInstallmentDetails(int $lead_id, $installments): array
|
|
{
|
|
if (is_string($installments)) {
|
|
$installments = json_decode($installments, true) ?? [];
|
|
}
|
|
|
|
if (! is_array($installments) || empty($installments)) {
|
|
return [];
|
|
}
|
|
|
|
$existingInstallments = $this->leadInstallmentPaymentDetails
|
|
->where('lead_id', $lead_id)
|
|
->where('is_active', 1)
|
|
->orderBy('id', 'ASC')
|
|
->findAll();
|
|
|
|
$savedInstallments = [];
|
|
|
|
foreach ($installments as $index => $installment) {
|
|
if (! is_array($installment)) {
|
|
continue;
|
|
}
|
|
|
|
$utrNo = isset($installment['utr_no']) ? trim((string) $installment['utr_no']) : '';
|
|
|
|
$data = [
|
|
'lead_id' => $lead_id,
|
|
'installment_amount' => $installment['installment_amount'] ?? null,
|
|
'payment_date' => ! empty($installment['payment_date'])
|
|
? change_date_format($installment['payment_date'])
|
|
: null,
|
|
'utr_no' => $utrNo !== '' ? $utrNo : null,
|
|
];
|
|
|
|
$installmentId = ! empty($installment['id']) ? (int) $installment['id'] : null;
|
|
|
|
if (! $installmentId && isset($existingInstallments[$index]['id'])) {
|
|
$installmentId = (int) $existingInstallments[$index]['id'];
|
|
}
|
|
|
|
if ($installmentId) {
|
|
$this->leadInstallmentPaymentDetails->update($installmentId, $data);
|
|
$data['id'] = $installmentId;
|
|
} else {
|
|
$data['is_active'] = 1;
|
|
$newId = $this->leadInstallmentPaymentDetails->insert($data);
|
|
$data['id'] = $newId;
|
|
}
|
|
|
|
$savedInstallments[] = $data;
|
|
}
|
|
|
|
return $savedInstallments;
|
|
}
|
|
|
|
public function removeInstallments()
|
|
{
|
|
$id = $this->request->getGet('id');
|
|
// print_r($id); die;
|
|
if (! empty($id)) {
|
|
$this->leadInstallmentPaymentDetails->whereIn('id', $id)->set(['is_active' => 0])->update();
|
|
} else {
|
|
return $this->respond(['status' => false, 'message' => 'Could not be removed.'], 200);
|
|
}
|
|
|
|
if ($this->request->getGet('lead_id')) {
|
|
$lead_id = $this->request->getGet('lead_id');
|
|
$data = [
|
|
'no_of_installment' => 0,
|
|
'is_installment' => 0,
|
|
];
|
|
$this->leadsModel->where('id', $lead_id)->set($data)->update();
|
|
}
|
|
|
|
return $this->respond(['status' => true, 'message' => 'Removed successfully'], 200);
|
|
}
|
|
|
|
//-----RFQ and QCR EXPORT------------------------------------------------------------------------------------------------
|
|
|
|
//export main route function
|
|
public function exportQCRandRFQ($lead_id, $type, $lead_form_type)
|
|
{
|
|
$this->exportExcelForQCRandRFQ($lead_id, $type, $lead_form_type);
|
|
}
|
|
|
|
//FOR EXCEL
|
|
public function exportExcelForQCRandRFQ($lead_id, $type, $lead_form_type = 1)
|
|
{
|
|
if ($lead_form_type == 2) {
|
|
$filepath = $this->constructNonEbExcelToSaveTemp($lead_id, $type);
|
|
} else {
|
|
$filepath = $this->constructExcelToSaveTemp($lead_id, $type);
|
|
}
|
|
|
|
$lead_data = $this->RFQModel->getRFQTableDataWithLeadIDAndType($lead_id, $type);
|
|
// dd($filepath);
|
|
|
|
//Excel merging part
|
|
if ($lead_data['file_name'] != null && $lead_data['file_name'] != '') {
|
|
|
|
$temp_file_path = $filepath['filePath'];
|
|
$temp_file_name = $filepath['fileName'];
|
|
$lead_file_path = storage_ensure_local_file(WRITEPATH . 'uploads/lead_files', $lead_data['file_name']);
|
|
|
|
// dd($lead_data, $temp_file_path, $temp_file_name, $lead_file_path);
|
|
|
|
if (! empty($lead_file_path) && is_file($lead_file_path)) {
|
|
$filePaths = [
|
|
['file_path' => $temp_file_path, 'sheets' => []],
|
|
['file_path' => $lead_file_path, 'sheets' => []],
|
|
];
|
|
// $outputPath = dirname($temp_file_path) . '/' . 'merged_' . $temp_file_name;
|
|
$result = ExcelMergeHelper::mergeExcelFiles($filePaths, $temp_file_path);
|
|
// print_rr($result);
|
|
}
|
|
}
|
|
|
|
$filepath = $filepath['filePath'];
|
|
|
|
if (file_exists($filepath)) {
|
|
// Set headers to force download
|
|
header('Content-Description: File Transfer');
|
|
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
|
header('Content-Disposition: attachment; filename="' . basename($filepath) . '"');
|
|
header('Content-Length: ' . filesize($filepath));
|
|
header('Pragma: public');
|
|
|
|
// Output the file content
|
|
readfile($filepath);
|
|
|
|
// Delete the file after download
|
|
unlink($filepath);
|
|
|
|
exit;
|
|
} else {
|
|
echo "File does not exist.";
|
|
}
|
|
}
|
|
|
|
//Construct excel file and save the file to the folder and return file path
|
|
public function constructExcelToSaveTemp($lead_id, $type, $propsal_and_insurer = null)
|
|
{
|
|
helper('excel_util_helper');
|
|
$rfq_data = $this->RFQModel->getRFQTableDataWithLeadIDAndType($lead_id, $type);
|
|
$claim_history = $rfq_data['claim_history'] ?? 0;
|
|
|
|
$is_placement = false;
|
|
$length = 0;
|
|
|
|
// dd($rfq_data, $lead_id, $type, $propsal_and_insurer);
|
|
// print_r($propsal_and_insurer); die;
|
|
// print_r($is_placement); die;
|
|
|
|
$data = json_decode($rfq_data['json'], true);
|
|
$sheetName = 'Worksheet';
|
|
if ($type == 2) {
|
|
$sheetName = 'QCR';
|
|
// $propsal_and_insurer = "Proposal 1-ICICIPRU-ICICI001";
|
|
$data = $this->convertJsonForQCR($data, $type);
|
|
if ($propsal_and_insurer !== null) {
|
|
list($proposal_key, $insurer_key) = explode('-', $propsal_and_insurer, 2);
|
|
$data = $this->transformProposelData($data, $proposal_key, $insurer_key);
|
|
$is_placement = true;
|
|
$sheetName = 'Placement';
|
|
}
|
|
} else if ($type == 1) {
|
|
$sheetName = 'RFQ';
|
|
$data = $this->convertJsonForQCR($data, $type);
|
|
} // dd($data);
|
|
|
|
$lead_data = [];
|
|
if (in_array((int) $rfq_data['lead_type'], [1], true)) {
|
|
|
|
if (in_array($rfq_data['policy_type_id'], [2, 3, 4, 5])) {
|
|
$lead_data = [
|
|
'Insured' => $rfq_data['client_name'],
|
|
'Policy Type' => $this->leadType[$rfq_data['lead_type']] ?? "",
|
|
|
|
'No of Employees' => $rfq_data['incept_emp_count'],
|
|
'No of Dependents' => $rfq_data['incept_dept_count'],
|
|
'Total Lives' => $rfq_data['incept_no_of_lives'],
|
|
|
|
// 'Period of Insurance ' => ! empty($rfq_data['policy_start_date']) && ! empty($rfq_data['policy_end_date']) ? date('d-m-Y', strtotime($rfq_data['policy_start_date'])) . ' to ' . date('d-m-Y', strtotime($rfq_data['policy_end_date'])) : "To be decided",
|
|
// 'Insurer' => $rfq_data['insurer_name'] ?? " - ",
|
|
// 'TPA' => $rfq_data['tpa_name'] ?? " - ",
|
|
// 'Policy Run Days' => $rfq_data['policy_run_days'],
|
|
];
|
|
} else if (in_array($rfq_data['policy_type_id'], [1, 6, 7])) {
|
|
$lead_data = [
|
|
'Insured' => $rfq_data['client_name'],
|
|
'No of Employees at Inception' => $rfq_data['incept_emp_count'],
|
|
// 'Total Sum Insured at Inception ' => $rfq_data['total_si_at_incept'],
|
|
// 'Policy Period' => ! empty($rfq_data['policy_start_date']) && ! empty($rfq_data['policy_end_date']) ? date('d-m-Y', strtotime($rfq_data['policy_start_date'])) . ' to ' . date('d-m-Y', strtotime($rfq_data['policy_end_date'])) : "To be decided",
|
|
// 'Insurer' => $rfq_data['insurer_name'] ?? " - ",
|
|
// 'TPA' => $rfq_data['tpa_name'] ?? " - ",
|
|
'Policy Type' => $this->leadType[$rfq_data['lead_type']] ?? "",
|
|
'Mortality Experience for last 3 years' => $claim_history == "1" ? "Mentioned in Claims sheet" : "Nil",
|
|
|
|
];
|
|
}else {
|
|
|
|
$lead_data = [
|
|
'Insured' => $rfq_data['client_name'],
|
|
'Policy Type' => $this->leadType[$rfq_data['lead_type']] ?? ""
|
|
];
|
|
}
|
|
|
|
} else {
|
|
|
|
if (in_array($rfq_data['policy_type_id'], [2, 3, 4, 5])) {
|
|
if ($is_placement == true) {
|
|
$lead_data = [
|
|
|
|
'Insured' => $rfq_data['client_name'],
|
|
'Policy Type' => $this->leadType[$rfq_data['lead_type']] ?? "",
|
|
|
|
// 'No of Employees at Inception' => $rfq_data['incept_emp_count'],
|
|
// 'No of Dependents at Inception' => $rfq_data['incept_dept_count'],
|
|
// 'Total Lives at Inception ' => $rfq_data['incept_no_of_lives'],
|
|
|
|
// 'No of Employees at Expiry' => $rfq_data['exp_emp_count'],
|
|
// 'No of Dependents at Expiry' => $rfq_data['exp_dept_count'],
|
|
// 'Total Lives at Expiry ' => $rfq_data['exp_no_of_lives'],
|
|
|
|
'No of Employees at Renewal' => $rfq_data['renewal_emp_count'],
|
|
'No of Dependents at Renewal' => $rfq_data['renewal_dept_count'],
|
|
'Total Lives at Renewal ' => $rfq_data['renewal_no_of_lives'],
|
|
|
|
'Period of Insurance ' => ! empty($rfq_data['policy_start_date']) && ! empty($rfq_data['policy_end_date']) ? date('d-m-Y', strtotime($rfq_data['policy_start_date'])) . ' to ' . date('d-m-Y', strtotime($rfq_data['policy_end_date'])) : "To be decided",
|
|
'Insurer' => $rfq_data['insurer_name'] ?? " - ",
|
|
'TPA' => $rfq_data['tpa_name'] ?? " - ",
|
|
|
|
// 'Policy Run Days' => $rfq_data['policy_run_days'],
|
|
// 'Inception Premium' => formatIndianCurrency($rfq_data['premium_at_inception']),
|
|
// 'Premium as on (' . date('d-m-Y', strtotime($rfq_data['incurred_claims_date'])) . ')' => formatIndianCurrency($rfq_data['premium_date']),
|
|
// 'Earned Premium' => formatIndianCurrency(intval($rfq_data['earned_premium'])),
|
|
// 'Incurred Claims as on (' . date('d-m-Y', strtotime($rfq_data['incurred_claims_date'])) . ')' => formatIndianCurrency($rfq_data['incurred_claims']),
|
|
// 'Annualised Claims' => formatIndianCurrency(intval($rfq_data['annualised_claims'])),
|
|
// 'Incurred Claims Ratio' => $rfq_data['incurred_claims_ratio'] . " %",
|
|
// 'Earned Claims Ratio' => $rfq_data['earned_claims_ratio'] . " %",
|
|
];
|
|
} else {
|
|
$lead_data = [
|
|
'Insured' => $rfq_data['client_name'],
|
|
'Policy Type' => $this->leadType[$rfq_data['lead_type']] ?? "",
|
|
|
|
'No of Employees at Inception' => $is_placement ? '-' : $rfq_data['incept_emp_count'],
|
|
'No of Dependents at Inception' => $is_placement ? '-' : $rfq_data['incept_dept_count'],
|
|
'Total Lives at Inception ' => $is_placement ? '-' : $rfq_data['incept_no_of_lives'],
|
|
|
|
'No of Employees at Expiry' => $is_placement ? '-' : $rfq_data['exp_emp_count'],
|
|
'No of Dependents at Expiry' => $is_placement ? '-' : $rfq_data['exp_dept_count'],
|
|
'Total Lives at Expiry ' => $is_placement ? '-' : $rfq_data['exp_no_of_lives'],
|
|
|
|
'No of Employees at Renewal' => $rfq_data['renewal_emp_count'],
|
|
'No of Dependents at Renewal' => $rfq_data['renewal_dept_count'],
|
|
'Total Lives at Renewal ' => $rfq_data['renewal_no_of_lives'],
|
|
|
|
'Period of Insurance ' => ! empty($rfq_data['policy_start_date']) && ! empty($rfq_data['policy_end_date'])
|
|
? date('d-m-Y', strtotime($rfq_data['policy_start_date'])) . ' to ' . date('d-m-Y', strtotime($rfq_data['policy_end_date']))
|
|
: "To be decided",
|
|
|
|
'Insurer' => $rfq_data['insurer_name'] ?? " - ",
|
|
'TPA' => $rfq_data['tpa_name'] ?? " - ",
|
|
|
|
'Policy Run Days' => $is_placement ? '-' : $rfq_data['policy_run_days'],
|
|
'Inception Premium' => $is_placement ? '-' : formatIndianCurrency($rfq_data['premium_at_inception']),
|
|
'Premium as on (' . date('d-m-Y', strtotime($rfq_data['incurred_claims_date'])) . ')' => $is_placement ? '-' : formatIndianCurrency($rfq_data['premium_date']),
|
|
'Earned Premium' => $is_placement ? '-' : formatIndianCurrency(intval($rfq_data['earned_premium'])),
|
|
'Incurred Claims as on (' . date('d-m-Y', strtotime($rfq_data['incurred_claims_date'])) . ')' => $is_placement ? '-' : formatIndianCurrency($rfq_data['incurred_claims']),
|
|
'Annualised Claims' => $is_placement ? '-' : formatIndianCurrency(intval($rfq_data['annualised_claims'])),
|
|
'Incurred Claims Ratio' => $is_placement ? '-' : $rfq_data['incurred_claims_ratio'] . " %",
|
|
'Earned Claims Ratio' => $is_placement ? '-' : $rfq_data['earned_claims_ratio'] . " %",
|
|
];
|
|
}
|
|
} else if (in_array($rfq_data['policy_type_id'], [1, 6, 7])) {
|
|
|
|
$lead_data = [
|
|
'Insured' => $rfq_data['client_name'],
|
|
'No of Employees at Inception' => $rfq_data['incept_emp_count'],
|
|
'Total Sum Insured at Inception' => $rfq_data['total_si_at_incept'],
|
|
'Premium at inception' => $rfq_data['premium_at_incept'],
|
|
'Policy Period' => ! empty($rfq_data['policy_start_date']) && ! empty($rfq_data['policy_end_date']) ? date('d-m-Y', strtotime($rfq_data['policy_start_date'])) . ' to ' . date('d-m-Y', strtotime($rfq_data['policy_end_date'])) : "To be decided",
|
|
'Policy Type' => $this->leadType[$rfq_data['lead_type']] ?? "",
|
|
'Existing Insurer' => $rfq_data['insurer_name'],
|
|
'No of Employees at Renewal' => $rfq_data['renewal_emp_count'],
|
|
'Total Sum Insured at Renewal' => $rfq_data['total_si_at_renewal'],
|
|
'Claims Experience for last 3 years' => $claim_history == "1" ? "Mentioned in Claims sheet" : "Nil",
|
|
// 'Insurer' => $rfq_data['insurer_name'] ?? " - ",
|
|
// 'TPA' => $rfq_data['tpa_name'] ?? " - ",
|
|
// 'Total Lives at Inception' => $rfq_data['total_lives_at_incept'],
|
|
];
|
|
} else {
|
|
$lead_data = [
|
|
'Insured' => $rfq_data['client_name'],
|
|
'Policy Type' => $this->leadType[$rfq_data['lead_type']] ?? ""
|
|
];
|
|
}
|
|
}
|
|
// print_r($lead_data); die;
|
|
|
|
$spreadsheet = new Spreadsheet();
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
$sheet->setTitle($sheetName);
|
|
|
|
// Start with lead_data at the top
|
|
$rowNumber = 1;
|
|
|
|
$mergeRange1 = "A{$rowNumber}:B{$rowNumber}";
|
|
// $sheet->mergeCells($mergeRange1);
|
|
$sheet->setCellValue("A{$rowNumber}", "Nhance India Insurance Broking Pvt Ltd");
|
|
$sheet->getStyle("A{$rowNumber}")->applyFromArray([
|
|
'font' => [
|
|
'bold' => true,
|
|
'size' => 23,
|
|
],
|
|
'alignment' => [
|
|
'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
|
|
'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
|
|
],
|
|
]);
|
|
|
|
// Apply center alignment to the cell
|
|
// $sheet->getStyle("C{$rowNumber}")->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
|
// $sheet->getStyle("C{$rowNumber}")->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER);
|
|
|
|
$rowNumber = $rowNumber + 1;
|
|
|
|
// Initialize max width tracking variables
|
|
$maxWidthA = 0;
|
|
$maxWidthB = 0;
|
|
|
|
// dd($lead_data);
|
|
|
|
if(! empty($lead_data)) {
|
|
foreach ($lead_data as $key => $value) {
|
|
|
|
// Merge A:B for key and C:D for value
|
|
$mergeRangeKey = "A{$rowNumber}:B{$rowNumber}";
|
|
// $mergeRangeValue = "C{$rowNumber}";
|
|
$sheet->mergeCells($mergeRangeKey);
|
|
// $sheet->mergeCells($mergeRangeValue);
|
|
|
|
// Set values in merged cells
|
|
$sheet->setCellValue("A{$rowNumber}", $key);
|
|
$sheet->setCellValue("C{$rowNumber}", $value);
|
|
|
|
// // Apply styles for alignment and bold text in A:B
|
|
// $sheet->getStyle($mergeRangeKey)->applyFromArray([
|
|
// 'font' => ['bold' => true],
|
|
// 'alignment' => [
|
|
// 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
|
|
// 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
|
|
// ],
|
|
// ]);
|
|
|
|
// Apply bold style to B column if the key is "Insured"
|
|
if ($key == "Insured") {
|
|
$sheet->getStyle("C{$rowNumber}")->applyFromArray([
|
|
'font' => ['bold' => true],
|
|
]);
|
|
}
|
|
|
|
// Track max width needed for columns
|
|
$maxWidthA = max($maxWidthA, mb_strlen($key));
|
|
$maxWidthB = max($maxWidthB, mb_strlen($value));
|
|
|
|
$rowNumber++;
|
|
}
|
|
}
|
|
|
|
// Set column width based on max content length (adjusted for padding)
|
|
$sheet->getColumnDimension('A')->setWidth($maxWidthA * 1.2);
|
|
// $sheet->getColumnDimension('B')->setWidth($maxWidthA * 1.5);
|
|
$sheet->getColumnDimension('C')->setWidth(35);
|
|
|
|
// $rowNumber += 2;
|
|
|
|
// Add headers and subheaders
|
|
$headers = $data['table_data']['headers'];
|
|
|
|
$sheet->setCellValue("A{$rowNumber}", "Details of Coverage");
|
|
$sheet->getStyle("A{$rowNumber}")->applyFromArray([
|
|
'font' => [
|
|
'bold' => true,
|
|
],
|
|
'fill' => [
|
|
'fillType' => Fill::FILL_SOLID,
|
|
'startColor' => ['rgb' => 'ADD8E6'],
|
|
],
|
|
'borders' => [
|
|
'allBorders' => [
|
|
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
|
|
'color' => ['argb' => 'FF000000'], // Black color
|
|
],
|
|
],
|
|
]);
|
|
|
|
if ($type == 2) {
|
|
$subheader_count = array_sum(
|
|
array_map(
|
|
fn($header) => count(array_filter(
|
|
$header['subHeaders'],
|
|
fn($sub) => $sub !== "Quote Asked"
|
|
)),
|
|
$data['table_data']['headers']
|
|
)
|
|
);
|
|
} else {
|
|
$subheader_count = array_sum(array_map(fn($header) => count($header['subHeaders']), $data['table_data']['headers']));
|
|
}
|
|
|
|
if ($is_placement == false) {
|
|
$subheader_count = $subheader_count - 2;
|
|
}
|
|
|
|
$headerCount = count($data['table_data']['headers']);
|
|
$lastColumn = Coordinate::stringFromColumnIndex($subheader_count);
|
|
// dd( $headerCount, $lastColumn);
|
|
|
|
// Merge cells from A to the last column
|
|
$mergeRange = "A{$rowNumber}:{$lastColumn}{$rowNumber}";
|
|
|
|
$sheet->getStyle($mergeRange)->applyFromArray([
|
|
'borders' => [
|
|
'allBorders' => [
|
|
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
|
|
'color' => ['argb' => 'FF000000'], // Black color
|
|
],
|
|
],
|
|
]);
|
|
|
|
$sheet->mergeCells($mergeRange);
|
|
$rowNumber_for_remove_quote_asked = $rowNumber;
|
|
$rowNumber = $rowNumber + 1;
|
|
|
|
if ($type == 2) {
|
|
$subHeaderRow = $rowNumber + 1;
|
|
} else {
|
|
// $subHeaderRow = $rowNumber_for_remove_quote_asked;
|
|
$subHeaderRow = $rowNumber + 1;
|
|
}
|
|
|
|
$columnLetter = 'A';
|
|
$header_actual_count = 0;
|
|
$headerIndex = 0;
|
|
foreach ($headers as $header) {
|
|
// Kint::dump($header);
|
|
|
|
if ($is_placement == true) {
|
|
//for placement proposal only
|
|
$nxt_ro = $rowNumber + 1;
|
|
$sheet->mergeCells("C{$rowNumber}:C{$nxt_ro}");
|
|
}
|
|
|
|
if (in_array($header['parentHeader'], ['Item Key', 'Action'])) {
|
|
continue;
|
|
}
|
|
|
|
if (! in_array($header['parentHeader'], ['Item Key', 'Action', 'Sno', 'Particulars'])) {
|
|
$header_actual_count++;
|
|
|
|
//Quote asked not showed in the QCR excel so some proposel has only one Quote Asked, So that case avoid the proposel name
|
|
$subHeaderCount = count($header['subHeaders'] ?? []) ?? 0;
|
|
if ($subHeaderCount <= 1 && $type == 2 && $is_placement == false) {
|
|
// print_rr($header);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if ($header['parentHeader'] === 'Sno') {
|
|
$header['parentHeader'] = 'S.No.';
|
|
$sheet->getColumnDimension('A')->setWidth(10);
|
|
|
|
//merge the 2 row cells of the S.No.
|
|
$nxt_ro = $rowNumber + 1;
|
|
$sheet->mergeCells("{$columnLetter}{$rowNumber}:{$columnLetter}{$nxt_ro}");
|
|
}
|
|
|
|
if ($header['parentHeader'] === 'Particulars') {
|
|
$sheet->getColumnDimension('B')->setWidth(35);
|
|
|
|
//merge the 2 row cells of the particulars
|
|
$nxt_ro = $rowNumber + 1;
|
|
$sheet->mergeCells("{$columnLetter}{$rowNumber}:{$columnLetter}{$nxt_ro}");
|
|
}
|
|
|
|
$startColumn = $columnLetter; // Start of the current header range
|
|
if ($type == 2) {
|
|
$subHeaderCount = count(array_filter($header['subHeaders'], function ($subHeader) {
|
|
return $subHeader !== "Quote Asked";
|
|
}));
|
|
} else {
|
|
$subHeaderCount = count($header['subHeaders']); // Number of subheaders for this parent header
|
|
}
|
|
|
|
// Set parent header value
|
|
if ($is_placement == true && ! in_array($header['parentHeader'], ['Particulars', 'S.No.'])) {
|
|
$sheet->setCellValue("{$startColumn}{$rowNumber}", "Terms");
|
|
} else {
|
|
if (in_array($header['parentHeader'], ["Existing Renewal", "Existing Rollover"])) {
|
|
$sheet->setCellValue("{$startColumn}{$rowNumber}", "Existing Terms");
|
|
} else if (in_array($header['parentHeader'], ["Particulars", "S.No."])) {
|
|
$sheet->setCellValue("{$startColumn}{$rowNumber}", $header['parentHeader']);
|
|
} else {
|
|
$headerIndex = $headerIndex + 1;
|
|
$sheet->setCellValue("{$startColumn}{$rowNumber}", "Proposal Terms " . $headerIndex);
|
|
}
|
|
}
|
|
|
|
$sheet->getStyle("{$startColumn}{$rowNumber}")->applyFromArray([
|
|
'font' => ['bold' => true],
|
|
'alignment' => [
|
|
'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
|
|
'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
|
|
],
|
|
]);
|
|
|
|
// Merge header cells if it spans multiple subheaders
|
|
if ($subHeaderCount > 1) {
|
|
$endColumn = Coordinate::stringFromColumnIndex(Coordinate::columnIndexFromString($startColumn) + $subHeaderCount - 1);
|
|
$sheet->mergeCells("{$startColumn}{$rowNumber}:{$endColumn}{$rowNumber}");
|
|
} else {
|
|
$endColumn = $startColumn; // No merge needed if only one subheader
|
|
}
|
|
|
|
// Add subheaders
|
|
foreach ($header['subHeaders'] as $subHeader) {
|
|
|
|
if ($type == 2 && in_array($subHeader, ['Quote Asked'])) {
|
|
continue;
|
|
}
|
|
|
|
if ($is_placement == false) {
|
|
$sheet->setCellValue("{$columnLetter}{$subHeaderRow}", $subHeader);
|
|
}
|
|
|
|
if ($columnLetter != "A" && $columnLetter != "B" && $columnLetter != "C") {
|
|
$sheet->getColumnDimension($columnLetter)->setWidth(35);
|
|
} else {
|
|
$sheet->getColumnDimension('A')->setWidth(10);
|
|
}
|
|
|
|
if ($is_placement == false) {
|
|
$sheet->getStyle("{$columnLetter}{$subHeaderRow}")->applyFromArray([
|
|
'font' => ['bold' => true],
|
|
'alignment' => [
|
|
'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
|
|
'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
|
|
],
|
|
]);
|
|
}
|
|
|
|
$columnLetter++; // Move to the next column for subheaders
|
|
// Kint::dump($subHeader);
|
|
$length++;
|
|
}
|
|
}
|
|
|
|
if ($header_actual_count == 1 && $type == 1) {
|
|
$sheet->getColumnDimension('B')->setWidth(80);
|
|
} else {
|
|
$sheet->getColumnDimension('B')->setWidth(35);
|
|
}
|
|
|
|
// Apply border to the header range
|
|
$prevColumn1 = $this->getPreviousColumn($columnLetter);
|
|
$headerRange = "A{$rowNumber}:" . "{$prevColumn1}" . "{$subHeaderRow}";
|
|
$sheet->getStyle($headerRange)->applyFromArray([
|
|
'borders' => [
|
|
'allBorders' => [
|
|
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
|
|
'color' => ['argb' => 'FF000000'], // Black color
|
|
],
|
|
],
|
|
]);
|
|
|
|
// Increase row height for headers and subheaders
|
|
$sheet->getRowDimension($rowNumber)->setRowHeight(25); // Header row height
|
|
$sheet->getRowDimension($subHeaderRow)->setRowHeight(20); // Subheader row height
|
|
|
|
if ($is_placement == true) {
|
|
$rowNumber = $subHeaderRow + 1;
|
|
} else {
|
|
$rowNumber = $subHeaderRow + 1;
|
|
}
|
|
|
|
// dd($rowNumber);
|
|
$column_data = $data['table_data']['data'];
|
|
$serial_no = 1;
|
|
$maxColumnWidths = [];
|
|
|
|
// Add table data rows
|
|
foreach ($column_data as $dataRow) {
|
|
$columnLetter = 'A';
|
|
foreach ($dataRow['data'] as $cellData) {
|
|
if (in_array($cellData['parentth'], ['Item Key', 'Action'])) {
|
|
continue;
|
|
}
|
|
|
|
if ($type == 2 && in_array($cellData['subth'], ['Quote Asked'])) {
|
|
continue;
|
|
}
|
|
|
|
if ($cellData['parentth'] == 'Sno') {
|
|
$sheet->setCellValue("{$columnLetter}{$rowNumber}", $serial_no);
|
|
} else {
|
|
$sheet->setCellValue("{$columnLetter}{$rowNumber}", $cellData['value']);
|
|
}
|
|
|
|
$columnLetter++;
|
|
}
|
|
$rowNumber++;
|
|
$serial_no++;
|
|
}
|
|
|
|
$prevColumn2 = $this->getPreviousColumn($columnLetter);
|
|
$dataRange = "A" . ($subHeaderRow + 1) . ":" . "{$prevColumn2}" . ($rowNumber - 1);
|
|
$sheet->getStyle($dataRange)->applyFromArray([
|
|
'borders' => [
|
|
'allBorders' => [
|
|
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
|
|
'color' => ['argb' => 'FF000000'], // Black color
|
|
],
|
|
],
|
|
]);
|
|
|
|
//premium data
|
|
if ($type == 2) {
|
|
|
|
if ($is_placement == true) {$columnLetterForPremium = "B";} else { $columnLetterForPremium = "B";}
|
|
$rowNumber += 2;
|
|
|
|
// Add premium data
|
|
// dd($data);
|
|
// $labelArray = ["Premium", "GST (%)", "GST Amount (₹)", "Total"];
|
|
$labelArray = ["Premium", "GST Amount (₹)", "Total"];
|
|
$premiumData = $data['premium_data']['data'];
|
|
// dd($premiumData);
|
|
// $premium = [$labelArray[0]];
|
|
// $gst = [$labelArray[1]];
|
|
// $gstAmt = [$labelArray[1]];
|
|
// $total = [$labelArray[2]];
|
|
|
|
// if($is_placement == true){
|
|
$premium[] = $labelArray[0];
|
|
$gstAmt[] = $labelArray[1];
|
|
$total[] = $labelArray[2];
|
|
// }
|
|
|
|
foreach ($premiumData as $proposal => $insurers) {
|
|
if ($proposal != 'Particulars') {
|
|
foreach ($insurers as $insurer => $values) {
|
|
if ($insurer == 'Quote Asked') {
|
|
// $premium[] = count($insurers ?? []) > 1 ? $labelArray[0] : "";
|
|
// $gst[] = "";
|
|
// $gstAmt[] = count($insurers ?? []) > 1 ? $labelArray[1] : "";
|
|
// $total[] = count($insurers ?? []) > 1 ? $labelArray[2] : "";
|
|
} else {
|
|
$premium[] = formatIndianCurrency($values[$labelArray[0]]);
|
|
// $gst[] = $values[$labelArray[1]];
|
|
$gstAmt[] = formatIndianCurrency($values[$labelArray[1]]);
|
|
$total[] = formatIndianCurrency($values[$labelArray[2]]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// dd([$premium, $gstAmt, $total]); die;
|
|
|
|
foreach ([$premium, $gstAmt, $total] as $index => $rowData) {
|
|
$columnLetter = $columnLetterForPremium;
|
|
foreach ($rowData as $key => $value) {
|
|
$sheet->setCellValue("{$columnLetter}{$rowNumber}", $value);
|
|
if (in_array($value, $labelArray)) {
|
|
$sheet->getStyle("{$columnLetter}{$rowNumber}")->applyFromArray(['font' => ['bold' => true]]);
|
|
}
|
|
$columnLetter++;
|
|
}
|
|
$rowNumber++;
|
|
}
|
|
|
|
if ($is_placement == true) {
|
|
$prevColumn3 = $this->getPreviousColumn($columnLetter);
|
|
} else {
|
|
$prevColumn3 = $this->getPreviousColumn($columnLetter, 2);
|
|
}
|
|
|
|
$premiumRange = $columnLetterForPremium . ($rowNumber - 3) . ":" . "{$prevColumn3}" . ($rowNumber - 1);
|
|
// dd($prevColumn3, $premiumRange, $this->getPreviousColumn($columnLetter, 2), $columnLetter, $rowNumber);
|
|
|
|
$sheet->getStyle($premiumRange)->applyFromArray([
|
|
'borders' => [
|
|
'allBorders' => [
|
|
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
|
|
'color' => ['argb' => 'FF000000'], // Black color
|
|
],
|
|
],
|
|
]);
|
|
}
|
|
|
|
//set imgage and align the row and column
|
|
if ($type == 2) {
|
|
if ($is_placement == true) {
|
|
$columnLetter_img = $this->getPreviousColumn($columnLetter);
|
|
} else {
|
|
$columnLetter_img = $this->getPreviousColumn($columnLetter, 2);
|
|
}
|
|
} else {
|
|
$columnLetter_img = $this->getPreviousColumn($columnLetter);
|
|
}
|
|
|
|
$company_name = $this->getPreviousColumn($columnLetter_img);
|
|
$mergeRange1 = "A1:{$company_name}1";
|
|
$sheet->mergeCells($mergeRange1);
|
|
|
|
$rowCount = count($lead_data);
|
|
for ($i = 2; $i <= $rowCount + 1; $i++) {
|
|
$mergeRange1 = "C{$i}:{$columnLetter_img}{$i}";
|
|
$sheet->mergeCells($mergeRange1);
|
|
$sheet->getStyle($mergeRange1)->applyFromArray([
|
|
'borders' => [
|
|
'allBorders' => [
|
|
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
|
|
'color' => ['argb' => 'FF000000'], // Black color
|
|
],
|
|
],
|
|
]);
|
|
}
|
|
|
|
$sheet->getColumnDimension($columnLetter_img)->setWidth(35);
|
|
$sheet->getRowDimension(1)->setRowHeight(50); // Adjust as needed
|
|
|
|
$drawing = new Drawing();
|
|
$path = ROOTPATH . "public/assets/images/Nhance-Logo-Final.png"; // Use FCPATH for server path
|
|
$drawing->setPath($path);
|
|
$drawing->setCoordinates("{$columnLetter_img}1"); // Set position in column B
|
|
$drawing->setHeight(35); // Adjust image
|
|
$offsetX = 35;
|
|
$drawing->setOffsetX($offsetX); // Adjust horizontal offset
|
|
$drawing->setOffsetY(10); // Adjust vertical offset
|
|
$drawing->setWorksheet($sheet);
|
|
//end
|
|
|
|
// Auto-size columns
|
|
// foreach ($sheet->getColumnIterator() as $column) {
|
|
// $sheet->getColumnDimension($column->getColumnIndex())->setAutoSize(true);
|
|
// }
|
|
|
|
$dataRange = $sheet->calculateWorksheetDimension();
|
|
$sheet->getStyle($dataRange)->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER)->setVertical(Alignment::VERTICAL_CENTER)->setWrapText(true);
|
|
$sheet->getStyle('A1')->applyFromArray([
|
|
'alignment' => [
|
|
'wrapText' => false, // Disables text wrapping for A1
|
|
],
|
|
]);
|
|
|
|
// Apply border to the entire sheet
|
|
preg_match('/([A-Z]+)(\d+):([A-Z]+)(\d+)/', $dataRange, $matches);
|
|
|
|
if ($matches) {
|
|
$startColumn = $matches[1]; // A
|
|
$startRow = $matches[2]; // 1
|
|
$endColumn = $matches[3]; // G
|
|
$endRow = $matches[4]; // 75
|
|
|
|
// Convert column letter to index, reduce by 1, and convert back
|
|
$endColumnIndex = Coordinate::columnIndexFromString($endColumn) - 1;
|
|
$newEndColumn = Coordinate::stringFromColumnIndex($endColumnIndex);
|
|
|
|
// Generate the new range (e.g., "A1:F75" instead of "A1:G75")
|
|
$newDataRange = "{$startColumn}{$startRow}:{$newEndColumn}{$endRow}";
|
|
// $sheet->getStyle($newDataRange)->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);
|
|
}
|
|
|
|
$lastRow = count($lead_data) + 1;
|
|
$leadRange = "A1:{$columnLetter_img}{$lastRow}";
|
|
|
|
$sheet->getStyle($leadRange)->applyFromArray([
|
|
'borders' => [
|
|
'allBorders' => [
|
|
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
|
|
'color' => ['argb' => 'FF000000'], // Black color
|
|
],
|
|
],
|
|
]);
|
|
|
|
// Set filename
|
|
$string = ($type == 2) ? ($is_placement == true ? 'Placement' : 'QCR') : 'RFQ';
|
|
$current_year = date('Y');
|
|
$next_year = $current_year + 1;
|
|
$policy_year = "$current_year-$next_year";
|
|
|
|
if (! empty($rfq_data['policy_end_date'])) {
|
|
|
|
$policy_expiry = strtotime($rfq_data['policy_end_date']);
|
|
$formatted_policy = date("d-m-Y", $policy_expiry);
|
|
$filename = "{$rfq_data['client_name']}_{$rfq_data['policy_type']}_{$string}_" . $policy_year . '(Due On ' . $formatted_policy . ')' . '.xlsx';
|
|
} else {
|
|
|
|
$filename = "{$rfq_data['client_name']}_{$rfq_data['policy_type']}_{$string}_" . $policy_year . '_' . '.xlsx';
|
|
}
|
|
|
|
$filenameBase = pathinfo($filename, PATHINFO_FILENAME);
|
|
$filenameBase = preg_replace('/[^a-zA-Z0-9\-_ ]/u', '', $filenameBase);
|
|
$filenameBase = preg_replace('/\s+/', ' ', trim($filenameBase));
|
|
$filename = ($filenameBase !== '' ? $filenameBase : 'export') . '.xlsx';
|
|
|
|
//claim history new sheet;
|
|
if ($claim_history == 1 && !empty($rfq_data['fin_years_claims'])) {
|
|
|
|
$claim_details = $this->sanitizeClaimDetailsForExport(
|
|
json_decode($rfq_data['fin_years_claims'], true) ?? []
|
|
);
|
|
|
|
if (! empty($claim_details['finyear'])) {
|
|
|
|
// Get headers dynamically
|
|
$headers = array_map(function ($key) {
|
|
return ucwords(str_replace('_', ' ', $key));
|
|
}, array_keys($claim_details['finyear'][0]));
|
|
|
|
$newSheet = new Worksheet($spreadsheet, 'Claims Experience');
|
|
$spreadsheet->addSheet($newSheet);
|
|
$spreadsheet->setActiveSheetIndexByName('Claims Experience');
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
|
|
// Set headers
|
|
$sheet->fromArray($headers, null, 'A1');
|
|
|
|
// Apply background color and bold style to headers
|
|
$headerCellRange = 'A1:' . chr(64 + count($headers)) . '1'; // e.g., A1:G1
|
|
|
|
$sheet->getStyle($headerCellRange)->getFont()->setBold(true);
|
|
$sheet->getStyle($headerCellRange)->getFill()->setFillType(Fill::FILL_SOLID)->getStartColor()->setRGB('ADD8E6');
|
|
|
|
// Add border to header
|
|
$sheet->getStyle($headerCellRange)->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);
|
|
|
|
// Fill data and apply borders
|
|
$row = 2;
|
|
foreach ($claim_details['finyear'] as $record) {
|
|
$col = 'A';
|
|
foreach ($record as $array_key => $value) {
|
|
$label = ucwords(str_replace('_', ' ', ($value ?? "")));
|
|
if (in_array($array_key, ['sum_insured', 'claim_amount', 'settled'])) {
|
|
$label = formatIndianCurrency(intval($label));
|
|
}
|
|
$sheet->setCellValue($col . $row, $label);
|
|
$col++;
|
|
}
|
|
|
|
// Apply border to each data row
|
|
$sheet->getStyle('A' . $row . ':' . chr(64 + count($headers)) . $row)
|
|
->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);
|
|
|
|
$row++;
|
|
}
|
|
// Auto-size all columns based on header count
|
|
for ($i = 0; $i < count($headers); $i++) {
|
|
$colLetter = chr(65 + $i); // 'A', 'B', etc.
|
|
$sheet->getColumnDimension($colLetter)->setAutoSize(true);
|
|
}
|
|
|
|
// Enable wrap text for all cells
|
|
// $maxColLetter = chr(64 + count($headers)); // Last column letter
|
|
// $sheet->getStyle("A2:{$maxColLetter}{$row}")->getAlignment()->setWrapText(true);
|
|
|
|
// // Optional: center vertically for neatness
|
|
// $sheet->getStyle("A2:{$maxColLetter}{$row}")->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER);
|
|
|
|
$maxColLetter = chr(64 + count($headers));
|
|
$dataRange = "A1:{$maxColLetter}" . ($row - 1);
|
|
|
|
$sheet->getStyle($dataRange)->getAlignment()
|
|
->setWrapText(true)
|
|
->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER)
|
|
->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER);
|
|
|
|
// Optional: Make row height auto (helps when wrap text is on)
|
|
for ($i = 2; $i < $row; $i++) {
|
|
$sheet->getRowDimension($i)->setRowHeight(-1);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// Save to temporary location
|
|
$uploadFilePath = WRITEPATH . 'tmp/' . $filename;
|
|
$writer = new Xlsx($spreadsheet);
|
|
$writer->save($uploadFilePath);
|
|
|
|
return [
|
|
'filePath' => $uploadFilePath,
|
|
'fileName' => $filename,
|
|
];
|
|
}
|
|
|
|
//Merge RFQ/QCR file with lead members file
|
|
public function mergeQuoteExcelFileWithMembersListExcelFile($lead_id, $type, $source_file_path)
|
|
{
|
|
$rfq_data = $this->RFQModel->getRFQTableDataWithLeadIDAndType($lead_id, $type);
|
|
|
|
if ($source_file_path && $rfq_data['file_name']) {
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public function calculateMembersDemography($params, $returnType = null)
|
|
{
|
|
$lead_id = $params['lead_id'];
|
|
$lead_data = $this->leadsModel->find((int) $lead_id);
|
|
|
|
if (! $lead_data) {
|
|
return ['status' => 'failed', 'message' => 'Opportunity data not found'];
|
|
}
|
|
|
|
$file_name_with_path = ! empty($lead_data['file_name'])
|
|
? storage_ensure_local_file(WRITEPATH . 'uploads/lead_files', $lead_data['file_name'])
|
|
: null;
|
|
|
|
try {
|
|
if ($lead_data['file_name']) {
|
|
//check physical file
|
|
if (empty($file_name_with_path) || ! file_exists($file_name_with_path)) {
|
|
//file not found update status and reason
|
|
$message = "Lead Physcial file not found";
|
|
// echo $message;
|
|
$this->myLogger->logme('error', ($message . ' for file ' . ($lead_data['file_name'] ?? '')));
|
|
return ['status' => 'failed', 'message' => 'no physical file'];
|
|
}
|
|
|
|
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file_name_with_path);
|
|
|
|
//get members data
|
|
$members_sheet = $spreadsheet->getSheet(0);
|
|
$highestRowAndColumn = $members_sheet->getHighestRowAndColumn();
|
|
// dd($highestRowAndColumn);
|
|
$uncleaned_members = $members_sheet->rangeToArray('A1:' . $highestRowAndColumn['column'] . $highestRowAndColumn['row']);
|
|
$members = ExcelSanitizeHelper::sanitizeArrayData($uncleaned_members);
|
|
//get age band data
|
|
$age_band_sheet = $spreadsheet->getSheet(1);
|
|
$highestRowAndColumn = $age_band_sheet->getHighestRowAndColumn();
|
|
$age_band_data = $age_band_sheet->rangeToArray('A1:' . $highestRowAndColumn['column'] . $highestRowAndColumn['row']);
|
|
|
|
//check age or dob column
|
|
$members_heading = $members[0];
|
|
$available_col = null;
|
|
$col_index = null;
|
|
|
|
if (in_array('age', array_map('strtolower', $members_heading))) {
|
|
$available_col = 'age';
|
|
$col_index = array_search('age', array_map('strtolower', $members_heading));
|
|
} elseif (in_array('dob', array_map('strtolower', $members_heading))) {
|
|
$available_col = 'dob';
|
|
$col_index = array_search('dob', array_map('strtolower', $members_heading));
|
|
}
|
|
|
|
if ($available_col == null) {
|
|
$message = 'No DOB or Age column ';
|
|
$this->myLogger->logme('error', ($message . $file_name_with_path));
|
|
return ['status' => 'failed', 'message' => $message];
|
|
}
|
|
|
|
try {
|
|
$classifiers = $this->getDemographyData($members, $age_band_data, $members_heading, $available_col, $col_index);
|
|
} catch (Exception $e) {
|
|
return ['status' => 'fail', 'message' => $e->getMessage()];
|
|
}
|
|
|
|
//for this to view the demography in the RFQ and QCR page to using internal
|
|
if ($returnType == "internal") {
|
|
return ['data' => $classifiers];
|
|
// print_rr($classifiers); die;
|
|
}
|
|
|
|
try {
|
|
$result = $this->generateClassifierSpreadsheet($classifiers, WRITEPATH . 'uploads/lead_files/');
|
|
if ($result['success']) {
|
|
$this->myLogger->logme('error', "Spreadsheet generated successfully!");
|
|
|
|
echo "Location: " . $result['fullpath'] . "\n";
|
|
echo "Filename: " . $result['filename'] . "\n";
|
|
$filePaths = [
|
|
['file_path' => $file_name_with_path, 'sheets' => [0, 1]],
|
|
['file_path' => $result['fullpath'], 'sheets' => []],
|
|
];
|
|
$outputPath = $file_name_with_path;
|
|
$result_merge = ExcelMergeHelper::mergeExcelFiles($filePaths, $outputPath);
|
|
if ($result_merge) {
|
|
storage_mirror_generated_file($outputPath, WRITEPATH . 'uploads/lead_files', $lead_data['file_name']);
|
|
// Call the delete function after the file is successfully created
|
|
$deleteResponse = $this->deleteGeneratedFile($result['fullpath']);
|
|
|
|
// Add delete message to response
|
|
$response['deleteMessage'] = $deleteResponse['message'];
|
|
return ['status' => 'success', 'message' => 'Member_Data Merged Suceesfully'];
|
|
}
|
|
} else {
|
|
echo "Error generating spreadsheet: " . $result['error'];
|
|
}
|
|
} catch (Exception $e) {
|
|
echo "Error: " . $e->getMessage();
|
|
return ['status' => 'fail', 'message' => $e->getMessage()];
|
|
}
|
|
} else {
|
|
$this->myLogger->logme('error', (' no file found ' . $file_name_with_path));
|
|
return ['status' => 'failed', 'message' => 'no file found'];
|
|
}
|
|
|
|
} catch (Exception $e) {
|
|
$this->myLogger->logme("error", "Exception: " . $e->getMessage() . " --- Line: " . $e->getLine() . " --- Trace: " . $e->getTraceAsString());
|
|
return ['status' => 'fail', 'error' => "File not found / Wrong file"];
|
|
}
|
|
}
|
|
|
|
public function getDemographyData($members, $age_band_data, $members_heading, $available_col, $col_index)
|
|
{
|
|
$first_loop = 0;
|
|
// $col_index_si = array_search('si enhancement', array_map('strtolower', $members_heading));
|
|
$col_index_si = array_search('si', array_map('strtolower', $members_heading));
|
|
$col_index_relationship = array_search('relationship', array_map('strtolower', $members_heading));
|
|
$relations = [];
|
|
$si_amt = ['general']; // Initialize with 'general' as per first loop condition
|
|
|
|
// First pass - collect unique relations and SI amounts
|
|
foreach ($members as $member) {
|
|
if ($first_loop == 0) {
|
|
$first_loop++;
|
|
continue;
|
|
}
|
|
if ($member == null) {
|
|
continue;
|
|
}
|
|
|
|
if (! in_array($member[$col_index_relationship], $relations) && $member[$col_index_relationship] != null) {
|
|
$relations[] = $member[$col_index_relationship];
|
|
}
|
|
|
|
if (! in_array($member[$col_index_si], $si_amt) && $member[$col_index_si] != null) {
|
|
$si_amt[] = $member[$col_index_si];
|
|
}
|
|
}
|
|
// Initialize classifier array
|
|
$classifiers = [];
|
|
foreach ($si_amt as $si) {
|
|
$classifiers[$si] = [];
|
|
// Initialize relation counts including Grand Total row
|
|
foreach ($relations as $relation) {
|
|
$classifiers[$si][$relation] = [];
|
|
foreach ($age_band_data as $age_bands) {
|
|
foreach ($age_bands as $age_interval) {
|
|
$classifiers[$si][$relation][$age_interval] = 0;
|
|
}
|
|
}
|
|
// Add Grand Total column for each relation echo('test passed 3.5');
|
|
|
|
$classifiers[$si][$relation]['Grand Total'] = 0;
|
|
}
|
|
// Initialize Grand Total row
|
|
$classifiers[$si]['Grand Total'] = [];
|
|
foreach ($age_band_data as $age_bands) {
|
|
foreach ($age_bands as $age_interval) {
|
|
$classifiers[$si]['Grand Total'][$age_interval] = 0;
|
|
}
|
|
}
|
|
// Add grand total of grand totals
|
|
$classifiers[$si]['Grand Total']['Grand Total'] = 0;
|
|
}
|
|
// Process members and count them
|
|
foreach ($members as $member) {
|
|
if ($first_loop == 0) {
|
|
$first_loop++;
|
|
continue;
|
|
}
|
|
// Get age
|
|
$age = $this->getAge($available_col, $member, $col_index);
|
|
|
|
$relation = $member[$col_index_relationship];
|
|
$member_si = $member[$col_index_si];
|
|
|
|
// Find the correct age band (only once per member)
|
|
$found_band = false;
|
|
foreach ($age_band_data as $age_bands) {
|
|
if ($found_band) {
|
|
break;
|
|
}
|
|
|
|
foreach ($age_bands as $age_band) {
|
|
//get Min and Max Age
|
|
list($min_age, $max_age) = $this->getAgeRange($age_band);
|
|
|
|
// If age fits in this band
|
|
if ($age >= $min_age && $age <= $max_age) {
|
|
// Update counts for general category
|
|
if (isset($classifiers['general'][$relation][$age_band])) {
|
|
// Increment count for specific relation and age band
|
|
$classifiers['general'][$relation][$age_band]++;
|
|
// Update row total (Grand Total column)
|
|
$classifiers['general'][$relation]['Grand Total']++;
|
|
// Update column total (Grand Total row)
|
|
$classifiers['general']['Grand Total'][$age_band]++;
|
|
// Update grand total of grand totals
|
|
$classifiers['general']['Grand Total']['Grand Total']++;
|
|
}
|
|
|
|
// Update counts for specific SI category
|
|
if (isset($classifiers[$member_si][$relation][$age_band])) {
|
|
// Increment count for specific relation and age band
|
|
$classifiers[$member_si][$relation][$age_band]++;
|
|
// Update row total (Grand Total column)
|
|
$classifiers[$member_si][$relation]['Grand Total']++;
|
|
// Update column total (Grand Total row)
|
|
$classifiers[$member_si]['Grand Total'][$age_band]++;
|
|
// Update grand total of grand totals
|
|
$classifiers[$member_si]['Grand Total']['Grand Total']++;
|
|
}
|
|
|
|
$found_band = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return $classifiers;
|
|
}
|
|
|
|
public function generateClassifierSpreadsheet($classifiers, $outputDir = 'exports')
|
|
{
|
|
if (! file_exists($outputDir)) {
|
|
if (! mkdir($outputDir, 0755, true)) {
|
|
throw new Exception("Failed to create directory: $outputDir");
|
|
}
|
|
}
|
|
|
|
// Check if directory is writable
|
|
if (! is_writable($outputDir)) {
|
|
throw new Exception("Directory is not writable: $outputDir");
|
|
}
|
|
|
|
// Generate unique filename
|
|
$timestamp = date('Y-m-d_His');
|
|
$filename = "member_classification_{$timestamp}.xlsx";
|
|
$filepath = $outputDir . DIRECTORY_SEPARATOR . $filename;
|
|
|
|
// Check if file already exists (shouldn't happen with timestamp, but just in case)
|
|
if (file_exists($filepath)) {
|
|
$counter = 1;
|
|
while (file_exists($outputDir . DIRECTORY_SEPARATOR . "member_classification_{$timestamp}_{$counter}.xlsx")) {
|
|
$counter++;
|
|
}
|
|
$filename = "member_classification_{$timestamp}_{$counter}.xlsx";
|
|
$filepath = $outputDir . DIRECTORY_SEPARATOR . $filename;
|
|
}
|
|
|
|
$spreadsheet = new Spreadsheet();
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
$sheet->setTitle('Demography_Data');
|
|
|
|
// Get all age bands
|
|
$age_bands = array_keys(reset($classifiers['general']));
|
|
array_pop($age_bands); // Remove 'Grand Total'
|
|
$age_bands[] = 'Grand Total'; // Add it back at the end
|
|
|
|
$currentRow = 5; // Start from row 5 to match the example
|
|
|
|
// Function to write section data
|
|
$writeSectionData = function ($data, $sheet, &$currentRow, $si_type) use ($age_bands) {
|
|
// Add section header for the SI type
|
|
$sheet->setCellValue('B' . $currentRow, strtoupper($si_type));
|
|
|
|
// Style section header
|
|
$sheet->getStyle('B' . $currentRow)->applyFromArray([
|
|
'font' => ['bold' => true, 'size' => 14],
|
|
'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER],
|
|
]);
|
|
|
|
$currentRow++; // Move to the next row after the section header
|
|
|
|
// Set headers for the data table
|
|
$sheet->setCellValue('B' . $currentRow, 'Relationship');
|
|
$col = 'C';
|
|
foreach ($age_bands as $band) {
|
|
$sheet->setCellValue($col . $currentRow, $band);
|
|
$col++;
|
|
}
|
|
|
|
// Style headers
|
|
$lastCol = chr(ord('B') + count($age_bands));
|
|
$headerRange = 'B' . $currentRow . ':' . $lastCol . $currentRow;
|
|
$sheet->getStyle($headerRange)->applyFromArray([
|
|
'font' => ['bold' => true],
|
|
'borders' => [
|
|
'allBorders' => [
|
|
'borderStyle' => Border::BORDER_THIN,
|
|
'color' => ['rgb' => '000000'],
|
|
],
|
|
],
|
|
'alignment' => [
|
|
'horizontal' => Alignment::HORIZONTAL_CENTER,
|
|
],
|
|
]);
|
|
|
|
$currentRow++;
|
|
|
|
// Write data rows
|
|
foreach ($data as $relation => $values) {
|
|
if ($relation !== 'Grand Total') {
|
|
$sheet->setCellValue('B' . $currentRow, $relation);
|
|
$col = 'C';
|
|
foreach ($age_bands as $band) {
|
|
$value = $values[$band] ?: ''; // Convert 0 to empty string
|
|
$sheet->setCellValue($col . $currentRow, $value);
|
|
$col++;
|
|
}
|
|
|
|
// Style data row
|
|
$dataRange = 'B' . $currentRow . ':' . $lastCol . $currentRow;
|
|
$sheet->getStyle($dataRange)->applyFromArray([
|
|
'borders' => [
|
|
'allBorders' => [
|
|
'borderStyle' => Border::BORDER_THIN,
|
|
'color' => ['rgb' => '000000'],
|
|
],
|
|
],
|
|
'alignment' => [
|
|
'horizontal' => Alignment::HORIZONTAL_CENTER,
|
|
],
|
|
]);
|
|
|
|
$currentRow++;
|
|
}
|
|
}
|
|
|
|
// Add Grand Total row
|
|
$sheet->setCellValue('B' . $currentRow, 'Grand Total');
|
|
$col = 'C';
|
|
foreach ($age_bands as $band) {
|
|
$sheet->setCellValue($col . $currentRow, $data['Grand Total'][$band]);
|
|
$col++;
|
|
}
|
|
|
|
// Style Grand Total row
|
|
$totalRange = 'B' . $currentRow . ':' . $lastCol . $currentRow;
|
|
$sheet->getStyle($totalRange)->applyFromArray([
|
|
'font' => ['bold' => true],
|
|
'borders' => [
|
|
'allBorders' => [
|
|
'borderStyle' => Border::BORDER_THIN,
|
|
'color' => ['rgb' => '000000'],
|
|
],
|
|
],
|
|
'fill' => [
|
|
'fillType' => Fill::FILL_SOLID,
|
|
'startColor' => ['rgb' => 'F2F2F2'],
|
|
],
|
|
'alignment' => [
|
|
'horizontal' => Alignment::HORIZONTAL_CENTER,
|
|
],
|
|
]);
|
|
|
|
$currentRow += 3; // Add gap after each section
|
|
};
|
|
|
|
// Write each SI section with gaps
|
|
foreach ($classifiers as $si_type => $data) {
|
|
$writeSectionData($data, $sheet, $currentRow, $si_type);
|
|
}
|
|
|
|
// Auto-size columns
|
|
foreach (range('B', chr(ord('B') + count($age_bands))) as $col) {
|
|
$sheet->getColumnDimension($col)->setAutoSize(true);
|
|
}
|
|
|
|
// Create Excel file
|
|
try {
|
|
// Create Excel file
|
|
$writer = new Xlsx($spreadsheet);
|
|
$writer->save($filepath);
|
|
|
|
// Verify file was created successfully
|
|
if (! file_exists($filepath)) {
|
|
throw new Exception("Failed to create file: $filepath");
|
|
}
|
|
|
|
// Return the file info after creation
|
|
$response = [
|
|
'success' => true,
|
|
'filepath' => $filepath,
|
|
'filename' => $filename,
|
|
'fullpath' => realpath($filepath),
|
|
];
|
|
|
|
return $response;
|
|
} catch (Exception $e) {
|
|
return [
|
|
'success' => false,
|
|
'error' => $e->getMessage(),
|
|
];
|
|
}
|
|
}
|
|
|
|
// Function to delete generated file
|
|
public function deleteGeneratedFile($filePath)
|
|
{
|
|
try {
|
|
if (file_exists($filePath)) {
|
|
unlink($filePath); // Delete the file
|
|
return [
|
|
'success' => true,
|
|
'message' => "File deleted successfully",
|
|
];
|
|
} else {
|
|
return [
|
|
'success' => false,
|
|
'message' => "File does not exist",
|
|
];
|
|
}
|
|
} catch (Exception $e) {
|
|
return [
|
|
'success' => false,
|
|
'error' => $e->getMessage(),
|
|
];
|
|
}
|
|
}
|
|
|
|
public function getAge($available_col, $member, $col_index)
|
|
{
|
|
if ($available_col == 'age') {
|
|
$age = $member[$col_index];
|
|
} else {
|
|
$dob = $member[$col_index];
|
|
if ($dob == 'DOB') {
|
|
return;
|
|
}
|
|
$dobDate = \DateTime::createFromFormat('d-M-Y', $dob);
|
|
$currentDate = new \DateTime();
|
|
if ($dobDate == false) {
|
|
$this->myLogger->logme('error', $dob . 'is not valid');
|
|
return;
|
|
}
|
|
$age = $currentDate->diff($dobDate)->y;
|
|
}
|
|
return $age;
|
|
}
|
|
|
|
public function getAgeRange($age_band)
|
|
{
|
|
$age_band = trim($age_band);
|
|
// Parse age range
|
|
if (strpos($age_band, '-') === false) {
|
|
$min_age = (int) filter_var($age_band, FILTER_SANITIZE_NUMBER_INT);
|
|
$max_age = PHP_INT_MAX;
|
|
} else {
|
|
$parts = explode("-", $age_band);
|
|
$min_age = (int) $parts[0];
|
|
$max_age = (int) $parts[1];
|
|
}
|
|
|
|
return [$min_age, $max_age];
|
|
}
|
|
|
|
//this funciton for send mail to insurer and client with either RFQ/QCR
|
|
public function sendMailWithAttachement()
|
|
{
|
|
helper('excel_util_helper');
|
|
helper('MailHelper');
|
|
helper('ExcelMergeHelper');
|
|
$params = $this->request->getPost();
|
|
|
|
// print_r($params); die;
|
|
|
|
$lead_id = (int) $params['lead_id'];
|
|
$file_type = $params['file_type']; //rfq or qcr
|
|
$recipient_type = $params['recipient_type']; //insurer or client or internal or placement
|
|
$recipient_mail = $params['recipient_mail']; // - only primary key of contacts
|
|
$recipient_mail = json_decode($params['recipient_mail'], true); // - only primary key of contacts
|
|
$propsal_and_insurer = isset($params['proposal_insurer']) ? $params['proposal_insurer'] : null;
|
|
$mail_content = $params['mail_content'];
|
|
$mail_subject = $params['subject'];
|
|
$attachment_file_ids = $params['selected_attachment_files'];
|
|
|
|
$from_mail = getenv('email.fromEmail');
|
|
if (in_array($recipient_type, ['placement', 'insurer', 'internal'])) {
|
|
$from_mail = getenv('LEAD_INSURER_FROM_MAIL_ID');
|
|
} else if (in_array($recipient_type, ['client'])) {
|
|
$from_mail = getenv('LEAD_CLIENT_FROM_MAIL_ID');
|
|
}
|
|
|
|
$type = "";
|
|
$insurer_ids = null;
|
|
if (in_array($recipient_type, ['placement'])) {
|
|
$type = "placement";
|
|
} else if (in_array($recipient_type, ['insurer'])) {
|
|
$type = "insurer";
|
|
$insurer_ids = json_decode($params['insurer_ids'] ?? "", true) ?? [];
|
|
} else if (in_array($recipient_type, ['internal'])) {
|
|
$type = "internal";
|
|
} else if (in_array($recipient_type, ['client'])) {
|
|
$type = "client";
|
|
}
|
|
|
|
// print_r($insurer_ids); die;
|
|
|
|
if ($recipient_type === 'placement') {
|
|
|
|
$lead_data = $this->leadsModel->find((int) $lead_id);
|
|
|
|
$data = [];
|
|
|
|
if (! empty($params['policy_start_date'])) {
|
|
$converted_start = change_date_format($params['policy_start_date']); // converts to Y-m-d
|
|
if ($converted_start !== $lead_data['policy_start_date']) {
|
|
$data['policy_start_date'] = $converted_start;
|
|
}
|
|
}
|
|
|
|
if (! empty($params['policy_end_date'])) {
|
|
$converted_end = change_date_format($params['policy_end_date']); // converts to Y-m-d
|
|
if ($converted_end !== $lead_data['policy_end_date']) {
|
|
$data['policy_end_date'] = $converted_end;
|
|
}
|
|
}
|
|
|
|
if (! empty($data)) {
|
|
$this->leadsModel->update($lead_id, $data);
|
|
}
|
|
}
|
|
|
|
$result_data = [];
|
|
// dd($recipient_mail);
|
|
if ($recipient_type == 'insurer' && (! is_array($recipient_mail) || count($recipient_mail) == 0)) {
|
|
return $this->respond(['status' => 'failed', 'code' => 400, 'data' => '', 'messgae' => 'Recipient mail not found ! '], 200);
|
|
}
|
|
// dd();
|
|
//gather lead info
|
|
$lead_data = $this->leadsModel
|
|
->select('leads.*,policy_type.long_name,policy_type.policy_type,user_profiles.email as created_person_email')
|
|
->join('policy_type', 'leads.policy_type_id = policy_type.id', 'left')
|
|
->join('user_profiles', 'leads.created_by = user_profiles.id', 'left')
|
|
->where('leads.id', $lead_id)
|
|
->first();
|
|
|
|
// log_message('error', 'Lead Data' . json_encode($lead_data));
|
|
// print_r($lead_data ); die;
|
|
|
|
$cc_mails = [];
|
|
$bcc_mails = [];
|
|
|
|
//get CC Mails
|
|
if ($recipient_type == 'internal' || $recipient_type == 'insurer' || $recipient_type == 'client') {
|
|
|
|
$cc_data = isset($params['cc']) ? $params['cc'] : "";
|
|
$param_cc_mail = json_decode($cc_data, true);
|
|
|
|
if (isset($param_cc_mail) && is_array($param_cc_mail) && count($param_cc_mail) > 0) {
|
|
// Fetch user data where ID is in the param_cc_mail array
|
|
$userData = $this->userModel
|
|
->where('is_active', 1)
|
|
->whereIn('id', $param_cc_mail)
|
|
->findAll();
|
|
|
|
// print_r($userData); die;
|
|
|
|
// Extract emails from the fetched user data
|
|
$cc_mails = array_column($userData, 'email');
|
|
|
|
// print_r(json_encode($cc_mails)); die;
|
|
|
|
// If no emails were found, return an error response
|
|
// if (empty($cc_mails)) {
|
|
// return $this->respond(['status' => 'failed','code' => 400,'data' => '','message' => 'No valid CC mail addresses found!'], 200);
|
|
// }
|
|
|
|
} else {
|
|
// Handle case where param_cc_mail is not valid
|
|
// return $this->respond(['status' => 'failed','code' => 400,'data' => '','message' => 'CC mail not found!'], 200);
|
|
}
|
|
|
|
// Append external CC emails for client mail (sent as email strings, not user IDs)
|
|
if ($recipient_type === 'client' && ! empty($params['external_cc'])) {
|
|
$externalCCs = json_decode($params['external_cc'], true);
|
|
if (is_array($externalCCs)) {
|
|
$cc_mails = array_merge($cc_mails, array_values(array_filter(array_map('trim', $externalCCs))));
|
|
}
|
|
}
|
|
|
|
} else if ($recipient_type == 'placement') {
|
|
|
|
if(isset($params['cc']) && !empty($params['cc'])) {
|
|
if(is_array($params['cc'])) {
|
|
$cc_mails = $params['cc'];
|
|
} else {
|
|
$cc_mails = json_decode($params['cc'], true);
|
|
}
|
|
}
|
|
}
|
|
|
|
//get BCC Mails
|
|
if ($recipient_type == 'insurer' || $recipient_type == 'client') {
|
|
|
|
$bcc_data = isset($params['bcc']) ? $params['bcc'] : "";
|
|
$param_bcc_mail = json_decode($bcc_data, true);
|
|
|
|
if (isset($param_bcc_mail) && is_array($param_bcc_mail) && count($param_bcc_mail) > 0) {
|
|
// Fetch user data where ID is in the param_cc_mail array
|
|
$userData = $this->userModel
|
|
->where('is_active', 1)
|
|
->whereIn('id', $param_bcc_mail)
|
|
->findAll();
|
|
|
|
// print_r($userData); die;
|
|
|
|
// Extract emails from the fetched user data
|
|
$bcc_mails = array_column($userData, 'email');
|
|
|
|
// print_r(json_encode($cc_mails)); die;
|
|
|
|
// If no emails were found, return an error response
|
|
// if (empty($cc_mails)) {
|
|
// return $this->respond(['status' => 'failed','code' => 400,'data' => '','message' => 'No valid CC mail addresses found!'], 200);
|
|
// }
|
|
|
|
} else {
|
|
// Handle case where param_cc_mail is not valid
|
|
// return $this->respond(['status' => 'failed','code' => 400,'data' => '','message' => 'CC mail not found!'], 200);
|
|
}
|
|
}
|
|
|
|
if ($recipient_type == 'client' && ($lead_data['contact_person_email'] == '' || $lead_data['contact_person_email'] == null)) {
|
|
return $this->respond(['status' => 'failed', 'code' => 400, 'data' => '', 'messgae' => 'Recipient mail not found ! '], 200);
|
|
}
|
|
|
|
// dd($lead_data);
|
|
$reply_to = $lead_data['created_person_email'] ?? "";
|
|
|
|
//get file path to attach
|
|
|
|
if ($lead_data["lead_form_type"] == 2 && $recipient_type === 'placement') {
|
|
// For Non-EB placement: copy QCR sheet as placement file, then download it
|
|
$file_info = $this->createAndDownloadPlacementSheet($lead_data);
|
|
} else if ($lead_data["lead_form_type"] == 2) {
|
|
// For Non-EB, download RFQ/QCR file from Google Sheet based on recipient type
|
|
$file_info = $this->downloadFileFromGoogleSheet($lead_data, $recipient_type);
|
|
} else {
|
|
$file_info = $this->constructExcelToSaveTemp($lead_id, ($file_type == 'rfq' ? 1 : 2), $propsal_and_insurer);
|
|
}
|
|
|
|
// $file_info = $this->constructExcelToSaveTemp($lead_id, ($file_type == 'rfq' ? 1 : 2), $propsal_and_insurer);
|
|
log_message('error', 'File Info' . json_encode($file_info));
|
|
if ($lead_data['file_name'] != null && $lead_data['file_name'] != '') {
|
|
$temp_file_path = $file_info['filePath'];
|
|
$temp_file_name = $file_info['fileName'];
|
|
$lead_file_path = storage_ensure_local_file(WRITEPATH . 'uploads/lead_files', $lead_data['file_name']);
|
|
if (! empty($lead_file_path) && is_file($lead_file_path)) {
|
|
$filePaths = [
|
|
['file_path' => $temp_file_path, 'sheets' => []],
|
|
['file_path' => $lead_file_path, 'sheets' => []],
|
|
];
|
|
$outputPath = dirname($temp_file_path) . '/' . $temp_file_name;
|
|
$result = ExcelMergeHelper::mergeExcelFiles($filePaths, $outputPath);
|
|
// print_rr($result);
|
|
}
|
|
} else {
|
|
$result = $file_info['filePath'];
|
|
// return $this->respond(['status' => 'fail', 'code' => 200, 'messgae' => 'File Not Found'], 200);
|
|
}
|
|
|
|
// print_rr($result); die;
|
|
// print_rr($file_info);
|
|
// $file_path = WRITEPATH."uploads/excel/sample/correction.xls";
|
|
// $file_name = $file_type.'.xlsx';
|
|
// !dd($file_info);
|
|
|
|
$file_path = $result;
|
|
$file_name = basename($result);
|
|
|
|
// Attacments part
|
|
$attachments = [['fileName' => $file_name, 'filePath' => $file_path]];
|
|
$other_attachments = $this->handleMultiFileAttachments($attachment_file_ids, $lead_id);
|
|
$attachments = array_merge($attachments, $other_attachments);
|
|
// print_r($attachments); die;
|
|
|
|
//get recipient address
|
|
if ($recipient_type == 'placement') {
|
|
// Placement TO is client contact email sent directly
|
|
if(!is_array($recipient_mail)) {
|
|
$recipient_mail = [$recipient_mail];
|
|
}
|
|
$recipient_data = [];
|
|
foreach ($recipient_mail as $mail) {
|
|
$recipient_data[] = ['name' => $lead_data['contact_person_name'] ?? '', 'email' => trim($mail)];
|
|
}
|
|
} else if ($recipient_type == 'insurer') {
|
|
|
|
if(!is_array($recipient_mail)) {
|
|
$recipient_mail = [$recipient_mail];
|
|
}
|
|
$recipient_data = $this->levelContactModel
|
|
->where(['contact_type' => 'insurer', 'is_active' => 1])
|
|
->whereIn('id', $recipient_mail)
|
|
->findAll();
|
|
} else if ($recipient_type == 'client') {
|
|
|
|
$mailIDS = explode(',', $params['contact_mail']);
|
|
$recipient_data = [];
|
|
foreach ($mailIDS as $mail) {
|
|
$recipient_data[] = ['name' => $lead_data['contact_person_name'], 'email' => $mail];
|
|
}
|
|
} else {
|
|
$recipient_data = [['name' => "Team", 'email' => $params['to']]];
|
|
}
|
|
// print_r($recipient_data); die;
|
|
|
|
$subject = $file_type == 'rfq' ? 'Request for Quotation from ' . $lead_data['client_name'] . ' for ' . $lead_data['policy_type'] : 'Quotation Comparison Report for ' . $lead_data['policy_type'];
|
|
|
|
$original_message = '<div style="width:100%;max-width:600px;margin:0 auto;padding:20px;border:1px solid #e0e0e0;background-color:#f9f9f9;font-family:Arial,sans-serif;color:#333;line-height:1.6"><div style=background-color:#4a90e2;color:#fff;padding:15px;text-align:center><h1 style=margin:0;font-size:24px>Request for Quotation (RFQ)</h1></div><div style=padding:20px;background-color:#fff><h2 style=color:#4a90e2;font-size:20px;margin-top:0>Dear {{RECIPIENT_NAME}},</h2><p>We are reaching out to request a quotation for the following insurance coverage. Please review the details below and provide your quote at your earliest convenience.<h2 style=color:#4a90e2;font-size:20px;margin-top:20px>RFQ Details</h2><table data-custom-table-css="table" style=width:100%;border-collapse:collapse;margin-top:20px><tr><th style="border:1px solid #ddd;padding:10px;text-align:left;background-color:#f2f2f2">Client name<td style="border:1px solid #ddd;padding:10px;text-align:left">{{CLIENT_NAME}}<tr><th style="border:1px solid #ddd;padding:10px;text-align:left;background-color:#f2f2f2">Coverage Type<td style="border:1px solid #ddd;padding:10px;text-align:left">{{POLICY_LONG_NAME}}<tr><th style="border:1px solid #ddd;padding:10px;text-align:left;background-color:#f2f2f2">Policy Start Date<td style="border:1px solid #ddd;padding:10px;text-align:left">{{POLICY_START_DATE}}<tr><th style="border:1px solid #ddd;padding:10px;text-align:left;background-color:#f2f2f2">Policy Duration<td style="border:1px solid #ddd;padding:10px;text-align:left">{{DURATION}}</table><div style="margin-top:20px;padding:10px;background-color:#f7f7f7;border-left:4px solid #4a90e2;font-style:italic">Please note: Additional terms and details are included in the attachment for your reference.</div><p>Please feel free to reach out if you require any further information to prepare the quote. We look forward to receiving your proposal.<p>Best regards,<p><strong>Nhance India Pvt Ltd</strong><br></div><div style=margin-top:20px;font-size:12px;color:#777;text-align:center><p>© Nhance India Pvt Ltd. All rights reserved.</div></div>';
|
|
|
|
//for mail content
|
|
if (! empty($mail_content)) {
|
|
$original_message = $mail_content;
|
|
}
|
|
|
|
//for mail subject
|
|
if (! empty($mail_subject)) {
|
|
$subject = $mail_subject;
|
|
}
|
|
|
|
// print_r($subject); die;
|
|
$common = ['module' => "leads", 'pk' => $lead_id, 'mail_type' => $type, 'common' => null];
|
|
if ($recipient_data) {
|
|
foreach ($recipient_data as $position => $recipient) {
|
|
|
|
if ($recipient_type == 'insurer') {
|
|
$common['common'] = $insurer_ids[$position] ?? null;
|
|
}
|
|
|
|
$message = $original_message;
|
|
$message = str_replace("{{RECIPIENT_NAME}}", $recipient['name'] != "" ? $recipient['name'] : " ", $message);
|
|
$message = str_replace("{{CLIENT_NAME}}", $lead_data['client_name'] != "" ? $lead_data['client_name'] : "", $message);
|
|
$message = str_replace("{{POLICY_LONG_NAME}}", $lead_data['long_name'] != "" ? $lead_data['long_name'] : "", $message);
|
|
$message = str_replace("{{POLICY_START_DATE}}", change_date_format($lead_data['policy_start_date'], 'Y-m-d', 'd-m-Y'), $message);
|
|
$message = str_replace("{{DURATION}}", calculate_days_bw_dates($lead_data['policy_end_date'] ?? "", $lead_data['policy_start_date'] ?? "")->days, $message) ?? '--';
|
|
|
|
// print_rr($message);calculate_days_bw_dates
|
|
$string = implode(", ", $cc_mails);
|
|
$bcc_string = implode(", ", $bcc_mails);
|
|
|
|
$res = MailHelper::send_email(['from_mail' => $from_mail, 'mail' => $recipient['email'], 'cc' => $string, 'subject' => $subject, 'message' => $message, 'attachments' => $attachments, 'reply_to' => $reply_to, 'bcc' => $bcc_string, 'common' => $common]);
|
|
// !dd($res);
|
|
$result_data[] = ['mail' => $recipient['email'], 'status' => $res];
|
|
}
|
|
}
|
|
|
|
if ($recipient_type == 'placement' && isset($params['acm_email']) && ! empty($params['acm_email'])) {
|
|
|
|
$common['mail_type'] = "internal acm";
|
|
$acm_mail_content = '
|
|
<p>Dear Sir,</p>
|
|
<p>The placement for the <strong>{{POLICY_TYPE}}</strong> policy pertaining to <strong>{{CLIENT_NAME}}</strong> has been successfully won.</p>
|
|
<p>Please proceed with the next steps accordingly.</p>
|
|
<p>Thank You!</p><br>
|
|
<p>Best regards,</p>
|
|
|
|
<img src="{{LOGO_PATH}}" alt="Nhance Logo" width="100" style="margin-top:10px;">
|
|
';
|
|
$acm_mail_content = $this->transformMailContent($lead_data, $acm_mail_content, $data['page_name'] = 'QCR');
|
|
$res = MailHelper::send_email(['from_mail' => $from_mail, 'mail' => $params['acm_email'], 'subject' => $subject, 'message' => $acm_mail_content, 'attachments' => $attachments, 'common' => $common]);
|
|
}
|
|
|
|
$is_placement = false;
|
|
if ($recipient_type == 'placement') {
|
|
|
|
$is_placement = true;
|
|
|
|
if(isset($propsal_and_insurer)) {
|
|
|
|
if (! empty($propsal_and_insurer[0])) {
|
|
$parts = explode('-', $propsal_and_insurer, 2);
|
|
$proposal_key = $parts[0] ?? null;
|
|
$insurer_key = $parts[1] ?? null;
|
|
} else {
|
|
$proposal_key = null;
|
|
$insurer_key = null;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
$lead_update_data = [
|
|
'proposel_name' => $proposal_key ?? null ,
|
|
'insurer_name' => $insurer_key ?? null,
|
|
'insurer' => $params['insurer_and_branch'] ?? null,
|
|
];
|
|
|
|
$data = [
|
|
'proposel_data' => json_encode($lead_update_data),
|
|
'status' => 'won',
|
|
'placement_date' => ! empty($params['placement_date']) ? change_date_format($params['placement_date']) : null,
|
|
'payment_date' => ! empty($params['payment_date']) ? change_date_format($params['payment_date']) : null,
|
|
'utr_no' => $params['utr_no'] ?? null,
|
|
'is_cd' => $params['is_cd'] ?? null,
|
|
'premium_amount' => $params['premium_amount'] ?? null,
|
|
'total_amount' => $params['total_amount'] ?? null,
|
|
'cd_amount' => $params['cd_amount'] ?? null,
|
|
'no_of_installment' => $params['no_of_installment'] ?? null,
|
|
'is_installment' => $params['is_installment'] ?? null,
|
|
'acm_id' => $params['acm_pk'] ?? null,
|
|
'agreed_percentage' => $params['agreed_percentage'] ?? null,
|
|
];
|
|
|
|
if (isset($params['tpa_id']) && ! empty($params['tpa_id'])) {
|
|
list($tpaBranchId, $tpaId) = explode('-', $params['tpa_id']);
|
|
$data['tpa_branch_id'] = $tpaBranchId;
|
|
$data['tpa_id'] = $tpaId;
|
|
}
|
|
|
|
$this->leadsModel->where('id', $lead_id)->set($data)->update();
|
|
|
|
if (isset($params['installments']) && ! empty($params['installments'])) {
|
|
$this->saveLeadInstallmentDetails((int) $lead_id, $params['installments']);
|
|
}
|
|
}
|
|
|
|
if ($recipient_type == 'client') {
|
|
|
|
$this->leadsModel
|
|
->where('id', $lead_id)
|
|
->whereNotIn('status', ['lost', 'co_insurer_pending', 'won', 'completed_with_corrections', 'completed_without_corrections'])
|
|
->set(['status' => "qcr_sent"])
|
|
->update();
|
|
}
|
|
|
|
if ($recipient_type == 'insurer') {
|
|
|
|
$this->leadsModel
|
|
->where('id', $lead_id)
|
|
->whereNotIn('status', ['qcr_created', 'qcr_sent', 'lost', 'co_insurer_pending', 'won', 'completed_with_corrections', 'completed_without_corrections'])
|
|
->set(['status' => "rfq_sent"])
|
|
->update();
|
|
}
|
|
|
|
//delete attachment file
|
|
unlink($file_path);
|
|
return $this->respond(['status' => 'success', 'code' => 200, 'data' => $result_data, 'is_placement' => $is_placement], 200);
|
|
}
|
|
|
|
public function getLevelContects()
|
|
{
|
|
|
|
$data = $this->levelContactModel->getContactForRFQ();
|
|
|
|
if ($data) {
|
|
return $this->respond(['status' => true, 'data' => $data], 200);
|
|
} else {
|
|
return $this->respond(['status' => false], 200);
|
|
}
|
|
}
|
|
|
|
public function getInsurerBranchContacts($insurer_and_branch_id)
|
|
{
|
|
if (strpos($insurer_and_branch_id, '-') === false) {
|
|
return $this->respond(['status' => false, 'message' => 'Invalid ID format'], 400);
|
|
}
|
|
|
|
// Split the insurer_and_branch_id
|
|
list($insurerBranchId, $insurerId) = explode('-', $insurer_and_branch_id);
|
|
|
|
$data = $this->levelContactModel->getContactForRFQ($insurerId, $insurerBranchId);
|
|
|
|
if (! empty($data)) {
|
|
return $this->respond(['status' => true, 'data' => $data], 200);
|
|
} else {
|
|
return $this->respond(['status' => false, 'data' => $data, 'message' => 'No contacts were found for the selected insurer.'], 200);
|
|
}
|
|
}
|
|
|
|
public function transformProposelData($data, $proposel, $insurer)
|
|
{
|
|
|
|
// print_r($data['premium_data']['data']); die;
|
|
|
|
$headerData = [];
|
|
|
|
// Default headers: S. No and Particulars
|
|
$defaultHeaders = [
|
|
[
|
|
'parentHeader' => 'Sno',
|
|
'subHeaders' => ['-'],
|
|
],
|
|
[
|
|
'parentHeader' => 'Particulars',
|
|
'subHeaders' => ['-'],
|
|
],
|
|
];
|
|
|
|
// Add default headers to the result
|
|
$headerData = array_merge($headerData, $defaultHeaders);
|
|
|
|
foreach ($data['table_data']['headers'] as $header) {
|
|
// Check if the parentHeader matches the target proposal
|
|
if ($header['parentHeader'] === $proposel) {
|
|
// Check if subHeaders contain the target insurer key
|
|
foreach ($header['subHeaders'] as $subHeader) {
|
|
if ($subHeader === $insurer) {
|
|
$headerData[] = [
|
|
'parentHeader' => $header['parentHeader'],
|
|
'subHeaders' => [
|
|
// 'Quote Asked', // Default value
|
|
$subHeader, // Matched insurer key
|
|
],
|
|
];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$columnData = [];
|
|
|
|
foreach ($data['table_data']['data'] as $entry) {
|
|
|
|
$sno = $entry['SNO'];
|
|
$items = $entry['items'];
|
|
$dataEntry = $entry['data'];
|
|
|
|
$result = [
|
|
"SNO" => $sno,
|
|
"items" => $items,
|
|
"data" => [],
|
|
];
|
|
|
|
foreach ($dataEntry as $item) {
|
|
|
|
// Include Sno and Particulars by default
|
|
if (in_array($item['parentth'], ['Sno', 'Particulars'])) {
|
|
$result['data'][] = [
|
|
"parentth" => $item['parentth'],
|
|
"subth" => $item['subth'],
|
|
"value" => $item['value'],
|
|
"input_value" => $item['input_value'],
|
|
];
|
|
}
|
|
|
|
// Include Proposal with Quote Asked by default
|
|
/* For proposel do not remove it */
|
|
// if ($item['parentth'] === $proposel && $item['subth'] === "Quote Asked") {
|
|
// $result['data'][] = [
|
|
// "parentth" => $item['parentth'],
|
|
// "subth" => $item['subth'],
|
|
// "value" => $item['value'],
|
|
// "input_value" => $item['input_value']
|
|
// ];
|
|
// }
|
|
|
|
// Example of including matching specific proposals and insurers
|
|
if ($item['parentth'] === $proposel && $item['subth'] === $insurer) {
|
|
$result['data'][] = [
|
|
"parentth" => $item['parentth'],
|
|
"subth" => $item['subth'],
|
|
"value" => $item['value'],
|
|
"input_value" => $item['input_value'],
|
|
];
|
|
}
|
|
}
|
|
|
|
// Add to the final result
|
|
$columnData[] = $result;
|
|
}
|
|
|
|
$premiumData = [];
|
|
|
|
foreach ($data['premium_data']['data'] as $key => $value) {
|
|
if ($key === $proposel) {
|
|
// $premiumData[$key]['Quote Asked'] = $value['Quote Asked'];
|
|
$premiumData[$key][$insurer] = $value[$insurer];
|
|
}
|
|
}
|
|
|
|
$data['table_data']['headers'] = $headerData;
|
|
$data['table_data']['data'] = $columnData;
|
|
$data['premium_data']['data'] = $premiumData;
|
|
|
|
return $data;
|
|
}
|
|
|
|
public function convertJsonForQCR($json, $type)
|
|
{
|
|
if ($json) {
|
|
|
|
// Deep copy of JSON
|
|
$first_json = json_decode(json_encode($json), true);
|
|
// dd($first_json);
|
|
|
|
if ($type == 2) {
|
|
|
|
// Column-wise Check: Remove headers and relevant data if qcr == 0
|
|
foreach ($json['proposal_data']['over_all_column_data'] as $proposalKey => $proposalData) {
|
|
|
|
if (($proposalData['qcr'] == 0 || $proposalData['qcr'] === false) || ($proposalData['stc'] == 0 || $proposalData['stc'] === false)) {
|
|
|
|
// Remove matching parentHeader in headers
|
|
foreach ($first_json['table_data']['headers'] as $index => $header) {
|
|
if ($header['parentHeader'] === $proposalKey) {
|
|
unset($first_json['table_data']['headers'][$index]);
|
|
}
|
|
}
|
|
|
|
// Remove data entries with matching parentth
|
|
foreach ($first_json['table_data']['data'] as &$item) {
|
|
$item['data'] = array_values(array_filter($item['data'], function ($entry) use ($proposalKey) {
|
|
return $entry['parentth'] !== $proposalKey;
|
|
}));
|
|
}
|
|
|
|
// Remove proposalKey from over_all_column_data
|
|
unset($first_json['proposal_data']['over_all_column_data'][$proposalKey]);
|
|
|
|
if ($type == 2) {
|
|
// Remove proposalKey from premium_data
|
|
unset($first_json['premium_data']['data'][$proposalKey]);
|
|
}
|
|
}
|
|
|
|
// Insurer Check: Remove subHeaders and relevant data for insurers with qcr == 0
|
|
foreach ($proposalData['insurers'] as $insurerIndex => $insurer) {
|
|
if (($insurer['qcr'] === 0 || $insurer['qcr'] === false) || ($insurer['stc'] === 0 || $insurer['stc'] === false)) {
|
|
foreach ($first_json['table_data']['headers'] as &$header) {
|
|
if (isset($header['subHeaders'])) {
|
|
$header['subHeaders'] = array_values(array_filter($header['subHeaders'], function ($sub) use ($insurer) {
|
|
return $sub !== $insurer['display_name'];
|
|
}));
|
|
}
|
|
}
|
|
|
|
foreach ($first_json['table_data']['data'] as &$item) {
|
|
$item['data'] = array_values(array_filter($item['data'], function ($entry) use ($insurer) {
|
|
return $entry['subth'] !== $insurer['display_name'];
|
|
}));
|
|
}
|
|
|
|
// Remove insurer from proposal's insurers array
|
|
unset($first_json['proposal_data']['over_all_column_data'][$proposalKey]['insurers'][$insurerIndex]);
|
|
|
|
if ($type == 2) {
|
|
unset($first_json['premium_data']['data'][$proposalKey][$insurer['display_name']]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Row-wise Check: Remove rows if qcr == 0 for actions
|
|
foreach ($first_json['table_data']['data'] as $rowKey => $rowData) {
|
|
foreach ($rowData['data'] as $data) {
|
|
if ($data['parentth'] === "Action" && (isset($data['input_value']['qcr']) && $data['input_value']['qcr'] == 0) || (isset($data['input_value']['stc']) && $data['input_value']['stc'] == 0)) {
|
|
unset($first_json['table_data']['data'][$rowKey]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Reindex arrays to maintain proper structure
|
|
$first_json['table_data']['headers'] = array_values($first_json['table_data']['headers']);
|
|
$first_json['table_data']['data'] = array_values($first_json['table_data']['data']);
|
|
$first_json['proposal_data']['over_all_column_data'] = array_map(function ($proposal) {
|
|
$proposal['insurers'] = array_values($proposal['insurers']);
|
|
return $proposal;
|
|
}, $first_json['proposal_data']['over_all_column_data']);
|
|
} else {
|
|
|
|
//remove insurer as Subheaders for RFQ
|
|
foreach ($first_json['table_data']['headers'] as &$header) {
|
|
$header['subHeaders'] = array_filter($header['subHeaders'], function ($subHeader) {
|
|
return in_array($subHeader, ['Quote Asked', '-']);
|
|
});
|
|
}
|
|
|
|
//Remove insurer Row wise data for RFQ
|
|
foreach ($first_json['table_data']['data'] as &$row) {
|
|
|
|
// Filter the inner data array
|
|
$row['data'] = array_filter(
|
|
$row['data'],
|
|
function ($item) {
|
|
return in_array($item['subth'], ['Quote Asked', '-']);
|
|
}
|
|
);
|
|
|
|
$row['data'] = array_values($row['data']);
|
|
}
|
|
|
|
// Ensure to unset the reference after the loop
|
|
unset($row);
|
|
|
|
// Remove insurers from Proposal Data key for RFQ
|
|
foreach ($first_json['proposal_data']['over_all_column_data'] as $key => &$proposal) {
|
|
if (isset($proposal['insurers'])) {
|
|
// Set the insurers array to empty
|
|
$proposal['insurers'] = [];
|
|
}
|
|
}
|
|
|
|
// Ensure to reset the reference
|
|
unset($proposal);
|
|
}
|
|
|
|
return $first_json;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
//----- Featch Lead data and insert Client -------------------------------------------------------------------------------------------
|
|
|
|
public function featchLeadDataAndInsertClient($lead_id)
|
|
{
|
|
try {
|
|
$data = $this->leadsModel->where('leads.id', $lead_id)->where('leads.is_active', 1)->first();
|
|
|
|
if (! $data) {
|
|
$this->myLogger->logme('error', 'featchLeadDataAndInsertClient: Lead not found or inactive', ['lead_id' => $lead_id]);
|
|
return $this->respond(['status' => false, 'message' => 'Failed to create Client', 'data' => null], 200);
|
|
}
|
|
|
|
$result = $this->createClientWithMatchingLeadsPolicies($data);
|
|
|
|
if ($result) {
|
|
return $this->respond([
|
|
'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);
|
|
}
|
|
|
|
$this->myLogger->logme('error', 'featchLeadDataAndInsertClient: Client creation failed after processing', ['lead_id' => $lead_id]);
|
|
return $this->respond(['status' => false, 'message' => 'Failed to create client', 'data' => $data], 200);
|
|
} catch (\Throwable $e) {
|
|
$this->myLogger->logme('error', 'featchLeadDataAndInsertClient failed: ' . $e->getMessage());
|
|
return $this->respond(['status' => false, 'message' => 'Internal server error', 'error' => $e->getMessage()], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
// Reuse client/branch from a previous partial attempt (client created, policy failed).
|
|
$existingClientId = (int) ($data['is_client_created'] ?? 0);
|
|
if ($existingClientId > 0) {
|
|
$client_id = $existingClientId;
|
|
|
|
$existingBranch = $this->clientBranchModel
|
|
->where('client_id', $client_id)
|
|
->where('branch_name', $data['branch_name'] ?? null)
|
|
->where('branch_code', $data['branch_code'] ?? null)
|
|
->where('is_active', 1)
|
|
->first();
|
|
|
|
if ($existingBranch) {
|
|
$branch_id = (int) $existingBranch['id'];
|
|
} else {
|
|
$branch_id = $this->clientBranchModel->insert($this->prepareClientBranchData($data, $client_id));
|
|
if (! $branch_id) {
|
|
return false;
|
|
}
|
|
$this->levelContactModel->insert($this->prepareContactData($data, $branch_id));
|
|
}
|
|
} else {
|
|
$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: ' . $e->getMessage());
|
|
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 {
|
|
$client_data = $this->prepareClientData($data);
|
|
$client_id = $this->clientModel->insert($client_data);
|
|
|
|
if ($client_id) {
|
|
$this->createClientBranchAndContactWithLeadData($data, $client_id);
|
|
$this->leadsModel->where('id', $data['id'])->set('is_client_created', $client_id)->update();
|
|
}
|
|
|
|
return $client_id;
|
|
} catch (\Throwable $e) {
|
|
$this->myLogger->logme('error', 'createClientWithLeadData failed');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public function createClientBranchAndContactWithLeadData($data, $client_id)
|
|
{
|
|
try {
|
|
$branch_data = $this->prepareClientBranchData($data, $client_id);
|
|
$branch_id = $this->clientBranchModel->insert($branch_data);
|
|
|
|
if ($branch_id) {
|
|
$this->leadsModel->where('id', $data['id'])->set('is_client_created', $client_id)->update();
|
|
$contact_data = $this->prepareContactData($data, $branch_id);
|
|
$this->levelContactModel->insert($contact_data);
|
|
$this->createClientPolicyWithLeadData($data, $client_id, $branch_id);
|
|
}
|
|
|
|
return $branch_id;
|
|
} catch (\Throwable $e) {
|
|
$this->myLogger->logme('error', 'createClientBranchAndContactWithLeadData failed');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public function createClientPolicyWithLeadData($data, $client_id, $branch_id)
|
|
{
|
|
try {
|
|
$client_policy_data = $this->prepareClientPolicyData($data, $client_id, $branch_id);
|
|
$client_policy_id = $this->clientPolicyModel->insert($client_policy_data);
|
|
|
|
if ($client_policy_id) {
|
|
$this->leadsModel->where('id', $data['id'])->set('is_client_created', $client_id)->update();
|
|
$this->leadsModel->where('id', $data['id'])->set('is_policy_created', $client_policy_id)->update();
|
|
}
|
|
|
|
return $client_policy_id;
|
|
} catch (\Throwable $e) {
|
|
$this->myLogger->logme('error', 'createClientPolicyWithLeadData failed: ' . $e->getMessage() . ' at ' . $e->getFile() . ':' . $e->getLine());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private function prepareClientData($data)
|
|
{
|
|
return [
|
|
'client_type' => 1,
|
|
'entity_type_id' => $data['entity_type_id'] ?? null,
|
|
'client_code' => $data['client_code'] ?? null,
|
|
'client_name' => $data['client_name'] ?? null,
|
|
'short_name' => $data['client_short_name'] ?? null,
|
|
'pan' => $data['pan'] ?? null,
|
|
];
|
|
}
|
|
|
|
private function prepareClientBranchData($data, $client_id)
|
|
{
|
|
$default_unit = trim(($data['client_short_name'] ?? '') . '-' . ($data['branch_code'] ?? ''), '-');
|
|
|
|
return [
|
|
'client_id' => $client_id,
|
|
'branch_name' => $data['branch_name'],
|
|
'branch_code' => $data['branch_code'],
|
|
'gst' => $data['gst'],
|
|
'units' => json_encode([$default_unit]),
|
|
];
|
|
}
|
|
|
|
private function prepareContactData($data, $branch_id)
|
|
{
|
|
return [
|
|
'name' => $data['contact_person_name'],
|
|
'mobile' => $data['contact_person_mobile'],
|
|
'email' => $data['contact_person_email'],
|
|
'contact_type' => 'client',
|
|
'ref_id' => $branch_id,
|
|
];
|
|
}
|
|
|
|
private function prepareClientPolicyData($data, $client_id, $branch_id)
|
|
{
|
|
$proposel_data = json_decode($data['proposel_data'] ?? '', true) ?? [];
|
|
|
|
if ($data['lead_form_type'] == 1) {
|
|
// EB: insurer stored as "{insurer_branch_id}-{insurer_id}" inside proposel_data
|
|
list($insurer_branch_id, $insurer_id) = explode('-', $proposel_data['insurer'] ?? '-', 2);
|
|
} else {
|
|
// Non-EB: insurer IDs are direct columns on the lead row
|
|
$insurer_id = $data['insurer_id'] ?? null;
|
|
$insurer_branch_id = $data['insurer_branch_id'] ?? null;
|
|
}
|
|
|
|
$client_policy_data = [
|
|
'client_id' => $client_id,
|
|
'client_branch_id' => $branch_id,
|
|
'policy_type_id' => $data['policy_type_id'],
|
|
'insurer_id' => $insurer_id,
|
|
'insurer_branch_id' => $insurer_branch_id,
|
|
'tpa_id' => $data['tpa_id'],
|
|
'tpa_branch_id' => $data['tpa_branch_id'],
|
|
'policy_start_date' => $data['policy_start_date'],
|
|
'policy_end_date' => $data['policy_end_date'],
|
|
'policy_status' => 1,
|
|
'policy_entry_from' => 3,
|
|
'is_from_lead' => $data['id'],
|
|
];
|
|
|
|
$policy_type_id = $data['policy_type_id'];
|
|
if (in_array($policy_type_id, [1, 2, 6, 7])) {
|
|
$client_policy_data['is_addon'] = 1; // Base Policy
|
|
} elseif (in_array($policy_type_id, [4, 5])) {
|
|
$client_policy_data['is_addon'] = 2; // SI TOPUP
|
|
} elseif ($policy_type_id == 3) {
|
|
// if ($base_policy) {
|
|
// $data['is_addon'] = 3; // Dependent Addon
|
|
// } else {
|
|
$data['is_addon'] = 1;
|
|
// }
|
|
}
|
|
|
|
$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 {
|
|
$proposel_data = json_decode($data['proposel_data'], true);
|
|
$QCRData = $this->RFQModel->where('is_active', 1)->where('lead_id', $data['id'])->first();
|
|
|
|
if (! $QCRData) {
|
|
throw new \Exception('RFQ Data not found');
|
|
}
|
|
|
|
$JSON = json_decode($QCRData['json'], true);
|
|
$converted_json = $this->transformProposelData($JSON, $proposel_data['proposel_name'], $proposel_data['insurer_name']);
|
|
|
|
// log_message('error', 'Converted JSON: ' . json_encode($converted_json));
|
|
return $this->convertQCRJsonToPolicyTerms($converted_json, $data['policy_type_id'], $proposel_data['proposel_name'], $proposel_data['insurer_name']);
|
|
} catch (\Throwable $e) {
|
|
$this->myLogger->logme('error', 'preparePolicyTermsFromRFQ');
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public function featchClientPolicyFromLead($client_id, $branch_id, $lead_id)
|
|
{
|
|
$data = $this->leadsModel->where('leads.id', $lead_id)->where('leads.is_active', 1)->first();
|
|
|
|
if (! $data) {
|
|
return $this->respond(['status' => false, 'message' => 'Failed to create policy', 'data' => null], 200);
|
|
}
|
|
|
|
if (empty($client_id) && ! empty($data['client_id'])) {
|
|
$client_id = $data['client_id'];
|
|
}
|
|
|
|
if (empty($branch_id) && ! empty($data['client_branch_id'])) {
|
|
$branch_id = $data['client_branch_id'];
|
|
}
|
|
|
|
$result = $this->createClientPolicyWithLeadData($data, $client_id, $branch_id);
|
|
// print_r($result); die;
|
|
|
|
if ($result) {
|
|
|
|
$policy_data = $this->clientPolicyModel->where('id', $result)->where('is_active', 1)->first();
|
|
return $this->respond(['status' => true, 'message' => 'New Policy created successfully', 'client_policy_id' => $result, 'data' => $data, 'client_id' => $policy_data['client_id']], 200);
|
|
}
|
|
|
|
return $this->respond(['status' => false, 'message' => 'Failed to create policy', 'data' => $data], 200);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------
|
|
|
|
//Function for convert the RFQ and QCR Json to Policy Terms Json
|
|
public function convertQCRJsonToPolicyTerms($data, $policy_type, $proposel_name, $insurer_name)
|
|
{
|
|
// Extract special conditions from original QCR data first.
|
|
// transformProposelData drops the Quote Asked column, which is the label source.
|
|
$specialConditionTerms = $this->extractSpecialConditionsFromQCR(
|
|
$data,
|
|
$policy_type,
|
|
$proposel_name,
|
|
$insurer_name
|
|
);
|
|
|
|
//transform the data into the currernt proposel and insurere ( get single proposel )
|
|
$data = $this->transformProposelData($data, $proposel_name, $insurer_name);
|
|
|
|
$terms_array = $specialConditionTerms;
|
|
|
|
// Initialize age_ratio based on policy type
|
|
$age_ratio = $policy_type == 2 ? [
|
|
'self' => ['min' => '18', 'max' => '60'],
|
|
'spouse' => ['min' => 0, 'max' => 0],
|
|
'child' => ['min' => 0, 'max' => '25'],
|
|
'elders' => ['min' => 0, 'max' => 0],
|
|
] : [
|
|
'self' => ['min' => '18', 'max' => '60'],
|
|
];
|
|
|
|
foreach ($data['table_data']['data'] as $dataRow) {
|
|
$item = $dataRow['items'] ?? '';
|
|
|
|
foreach ($dataRow['data'] as $cellData) {
|
|
$parentth = $cellData['parentth'] ?? '';
|
|
$subth = $cellData['subth'] ?? '';
|
|
$input_value = $cellData['input_value'] != "" ? $cellData['input_value'] : ($cellData['value'] ?? '');
|
|
$value = $cellData['value'] ?? '';
|
|
|
|
if ($item == "family_composition" && $subth == $insurer_name && $policy_type == 2) {
|
|
$age_ratio_array = json_decode($input_value, true)['age_ratio'] ?? null;
|
|
if (! empty($age_ratio_array)) {
|
|
$age_ratio = $age_ratio_array;
|
|
}
|
|
}
|
|
|
|
// Skip unwanted keys
|
|
if (in_array($parentth, ['Sno', 'Item Key', 'Particulars', 'Action']) || in_array($subth, ['Quote Asked'])) {
|
|
continue;
|
|
}
|
|
|
|
// Special conditions already extracted above.
|
|
if (str_starts_with((string) $item, 'special_condition')) {
|
|
continue;
|
|
}
|
|
|
|
switch (true) {
|
|
|
|
// CASE 1: Handle sum insured
|
|
case in_array($item, ['sum_insured', 'sumInsured2']):
|
|
$si_amt = explode(',', $value);
|
|
$terms_array[$item] = $si_amt[0] ?? '';
|
|
$terms_array['multiple_sum_insured'] = array_slice($si_amt, 1);
|
|
|
|
// Add age_ratio after Sum insured
|
|
if ($policy_type == 1) {
|
|
$terms_array['age_ratio'] = $age_ratio;
|
|
}
|
|
|
|
break;
|
|
|
|
// CASE 2: Handle family floaters
|
|
case $item === 'family_composition':
|
|
$terms_array['family_floaters'] = isJsonString($input_value) ? json_decode($input_value, true) : $input_value;
|
|
|
|
// Add age_ratio after family floaters
|
|
if ($policy_type == 2) {
|
|
$terms_array['age_ratio'] = $age_ratio;
|
|
}
|
|
|
|
break;
|
|
|
|
// DEFAULT CASE :
|
|
default:
|
|
// $terms_array[$item] = isJsonString($input_value) ? (json_decode($input_value, true)['key'] ?? '') : $value;
|
|
$terms_array[$item] = $value;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return json_encode($terms_array);
|
|
}
|
|
|
|
/**
|
|
* Build special_condition_label/input arrays from QCR rows.
|
|
*
|
|
* Mapping:
|
|
* - Canonical RFQ hidden format "label--value" (or display "label - value") on insurer cell
|
|
* - Otherwise Quote Asked = label, insurer cell = value
|
|
*
|
|
* @return array<string, list<string>>
|
|
*/
|
|
private function extractSpecialConditionsFromQCR($data, $policy_type, $proposel_name, $insurer_name): array
|
|
{
|
|
$labelKey = $policy_type == 1 ? 'gpa_special_condition_label' : 'special_condition_label';
|
|
$inputKey = $policy_type == 1 ? 'gpa_special_condition_input' : 'special_condition_input';
|
|
$result = [
|
|
$labelKey => [],
|
|
$inputKey => [],
|
|
];
|
|
|
|
if (empty($data['table_data']['data']) || ! is_array($data['table_data']['data'])) {
|
|
return [];
|
|
}
|
|
|
|
foreach ($data['table_data']['data'] as $dataRow) {
|
|
$item = $dataRow['items'] ?? '';
|
|
if (! str_starts_with((string) $item, 'special_condition')) {
|
|
continue;
|
|
}
|
|
|
|
$quoteAsked = '';
|
|
$insurerDisplay = '';
|
|
$insurerInput = '';
|
|
|
|
foreach ($dataRow['data'] ?? [] as $cellData) {
|
|
$parentth = $cellData['parentth'] ?? '';
|
|
$subth = $cellData['subth'] ?? '';
|
|
|
|
if ($parentth !== $proposel_name) {
|
|
continue;
|
|
}
|
|
|
|
$cellInput = isset($cellData['input_value']) && $cellData['input_value'] !== ''
|
|
? $cellData['input_value']
|
|
: ($cellData['value'] ?? '');
|
|
$cellValue = $cellData['value'] ?? '';
|
|
|
|
if ($subth === 'Quote Asked') {
|
|
$quoteAsked = $this->normalizeSpecialConditionCellText($cellValue, $cellInput);
|
|
}
|
|
|
|
if ($subth === $insurer_name) {
|
|
$insurerDisplay = is_string($cellValue) ? trim($cellValue) : '';
|
|
$insurerInput = is_string($cellInput) ? trim((string) $cellInput) : '';
|
|
}
|
|
}
|
|
|
|
[$label, $input] = $this->parseSpecialConditionParts($insurerInput, $insurerDisplay, $quoteAsked);
|
|
|
|
if ($label === '' && $input === '') {
|
|
continue;
|
|
}
|
|
|
|
$result[$labelKey][] = $label;
|
|
$result[$inputKey][] = $input;
|
|
}
|
|
|
|
if ($result[$labelKey] === [] && $result[$inputKey] === []) {
|
|
return [];
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Prefer visible cell text; fall back to hidden input_value.
|
|
*/
|
|
private function normalizeSpecialConditionCellText($display_value, $input_value): string
|
|
{
|
|
$display = is_string($display_value) ? trim($display_value) : '';
|
|
if ($display !== '') {
|
|
return $display;
|
|
}
|
|
|
|
return is_string($input_value) ? trim($input_value) : '';
|
|
}
|
|
|
|
/**
|
|
* Parse RFQ/QCR special-condition cells into [label, value].
|
|
*
|
|
* @return array{0: string, 1: string}
|
|
*/
|
|
private function parseSpecialConditionParts($input_value, $display_value = '', $quote_asked = ''): array
|
|
{
|
|
// Prefer canonical hidden "label--value"; otherwise prefer visible insurer text
|
|
// (QCR edits often update the cell text but leave the hidden input stale/empty).
|
|
$raw = '';
|
|
if (is_string($input_value) && str_contains($input_value, '--')) {
|
|
$raw = trim($input_value);
|
|
} elseif (is_string($display_value) && trim($display_value) !== '') {
|
|
$raw = trim($display_value);
|
|
} elseif (is_string($input_value)) {
|
|
$raw = trim($input_value);
|
|
}
|
|
|
|
$quoteAsked = is_string($quote_asked) ? trim($quote_asked) : '';
|
|
|
|
if ($raw === '' && $quoteAsked === '') {
|
|
return ['', ''];
|
|
}
|
|
|
|
if ($raw !== '' && str_contains($raw, '--')) {
|
|
$parts = explode('--', $raw, 2);
|
|
return [trim($parts[0] ?? ''), trim($parts[1] ?? '')];
|
|
}
|
|
|
|
if ($raw !== '' && str_contains($raw, ' - ')) {
|
|
$parts = explode(' - ', $raw, 2);
|
|
return [trim($parts[0] ?? ''), trim($parts[1] ?? '')];
|
|
}
|
|
|
|
// QCR columns: Quote Asked = label, insurer response = value
|
|
if ($quoteAsked !== '' && $raw !== '') {
|
|
return [$quoteAsked, $raw];
|
|
}
|
|
|
|
if ($quoteAsked !== '') {
|
|
return [$quoteAsked, $quoteAsked];
|
|
}
|
|
|
|
// Single insurer cell with no Quote Asked / separator: use as label and value
|
|
return [$raw, $raw];
|
|
}
|
|
|
|
public function convertNonEbQCRJsonToPolicyTerms($allTableData)
|
|
{
|
|
|
|
if (! empty($allTableData)) {
|
|
|
|
array_pop($allTableData); // Remove the last item from the array
|
|
$terms_array = [];
|
|
|
|
foreach ($allTableData as $TableIndex => $tableGroup) {
|
|
|
|
if ($TableIndex == 0) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($tableGroup['table_data']['data'] as $dataRow) {
|
|
$item = $dataRow['items'] ?? '';
|
|
|
|
foreach ($dataRow['data'] as $cellData) {
|
|
$parentth = $cellData['parentth'] ?? '';
|
|
$subth = $cellData['subth'] ?? '';
|
|
$value = $cellData['display_content'] ?? '';
|
|
|
|
// Skip unwanted keys
|
|
if (in_array($parentth, ['SNO', 'Particulars', 'Action']) || $subth === 'Sum Insured' || $subth === 'Fidelity Limit') {
|
|
continue;
|
|
}
|
|
|
|
// Skip if item matches parentth
|
|
if ($item === $parentth) {
|
|
continue;
|
|
}
|
|
|
|
// Set the value directly, overwriting with latest encountered
|
|
if (! empty($item) && ! empty($value)) {
|
|
|
|
$finalItem = $item;
|
|
|
|
if (strpos($tableGroup['tableId'], 'summary') !== false) {
|
|
$policy_type = explode('_', $tableGroup['tableId'])[0] ?? '';
|
|
$finalItem = $policy_type . ' - ' . $item;
|
|
}
|
|
$terms_array[$finalItem] = $value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return json_encode($terms_array);
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public function getPlacementJson(array $data): ?string
|
|
{
|
|
$proposel_data = json_decode($data['proposel_data'] ?? '', true) ?? [];
|
|
$proposelName = $proposel_data['proposel_name'] ?? '';
|
|
$insurerName = $proposel_data['insurer_name'] ?? '';
|
|
|
|
// Non-EB placement JSON is filtered by the won proposal/insurer selection.
|
|
// Without that selection, skip placement terms rather than throwing.
|
|
if ($proposelName === '' || $insurerName === '') {
|
|
return null;
|
|
}
|
|
|
|
$QCRData = $this->RFQModel
|
|
->where('is_active', 1)
|
|
->where('lead_id', $data['id'])
|
|
->first();
|
|
|
|
if (! $QCRData || empty($QCRData['json'])) {
|
|
return null;
|
|
}
|
|
|
|
$jsonArray = json_decode($QCRData['json'], true);
|
|
$proposalData = array_pop($jsonArray); // Get last item and remove it from the array
|
|
|
|
if (empty($jsonArray)) {
|
|
return null;
|
|
}
|
|
|
|
$placement_json_data = array_map(function ($jsonData) use ($proposelName, $insurerName) {
|
|
return $this->transformNonEbProposelData(
|
|
$jsonData,
|
|
$proposelName,
|
|
$insurerName,
|
|
null,
|
|
1
|
|
);
|
|
}, $jsonArray);
|
|
|
|
if (! empty($proposalData['proposal_data']['over_all_column_data']) && is_array($proposalData['proposal_data']['over_all_column_data'])) {
|
|
foreach ($proposalData['proposal_data']['over_all_column_data'] as $key => &$proposal) {
|
|
// Keep only the required proposal
|
|
if ($key !== $proposelName) {
|
|
unset($proposalData['proposal_data']['over_all_column_data'][$key]);
|
|
} else {
|
|
// Within the matched proposal, filter insurers
|
|
if (! empty($proposal['insurers'])) {
|
|
$proposal['insurers'] = array_values(array_filter($proposal['insurers'], function ($insurer) use ($insurerName) {
|
|
return ($insurer['display_name'] ?? null) === $insurerName;
|
|
}));
|
|
}
|
|
}
|
|
}
|
|
unset($proposal); // Good practice after foreach by reference
|
|
}
|
|
|
|
$placement_json_data[] = $proposalData;
|
|
|
|
return json_encode($placement_json_data);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
|
|
public function transformMailContent($lead_data, $mail_content, $page_name)
|
|
{
|
|
$current_year = date('Y');
|
|
$next_year = $current_year + 1;
|
|
$policy_year = "$current_year-$next_year";
|
|
$page_name = $page_name == "QCR" ? "Quote Comparison Report" : $page_name;
|
|
$log_path = base_url() . '/public/assets/images/Nhance-Logo-Final.png';
|
|
// $log_path ='https://venbait.in/nhance/dev/public/assets/images/Nhance-Logo-Final.png';
|
|
// dd($log_path);
|
|
|
|
$policy_expiry = strtotime($lead_data['policy_end_date']);
|
|
|
|
$formatted_policy = date("d-m-Y", $policy_expiry);
|
|
$logged_user_id = get_session_userid();
|
|
|
|
$logged_user_data = $this->userModel->where("id", $logged_user_id)->where("is_active", 1)->first();
|
|
|
|
if ($lead_data) {
|
|
|
|
// Replacing placeholders with actual values
|
|
$message = $mail_content;
|
|
$message = str_replace("{{CLIENT_NAME}}", $lead_data['client_name'] ?? "Valued Client", $message);
|
|
$message = str_replace("{{POLICY_LONG_NAME}}", $lead_data['long_name'] ?? $lead_data['policy_type'] ?? "Insurance Policy", $message);
|
|
$message = str_replace("{{POLICY_TYPE}}", $lead_data['policy_type'] ?? "Insurance Policy", $message);
|
|
$message = str_replace("{{RFQ_OR_QCR}}", $page_name, $message);
|
|
$message = str_replace("{{POLICY_YEAR}}", $policy_year, $message);
|
|
$message = str_replace("{{POLICY_END_DATE}}", " (Due On " . $formatted_policy . ")", $message);
|
|
|
|
$message = str_replace("{{LOGGED_USER_NAME}}", ucfirst($logged_user_data['first_name'] ?? "") . " " . ucfirst($logged_user_data['last_name'] ?? ""), $message);
|
|
$message = str_replace("{{LOGGED_USER_EMAIL}}", $logged_user_data['email'] ?? "", $message);
|
|
$message = str_replace("{{LOGGED_USER_MOBILE}}", $logged_user_data['mobile'] ?? "", $message);
|
|
$message = str_replace("{{LOGO_PATH}}", $log_path ?? "", $message);
|
|
|
|
return $message;
|
|
} else {
|
|
return ''; // Return empty if no lead data found
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return subject and mail content for a lead and a given template type.
|
|
*
|
|
* GET params:
|
|
* - lead_id (int, required)
|
|
* - template_type (string, one of: rfq, qcr, placement; default: rfq)
|
|
*
|
|
* Response:
|
|
* {
|
|
* status: 'success'|'error',
|
|
* code: 200|4xx|5xx,
|
|
* subject: string,
|
|
* mail_content: string,
|
|
* message: string
|
|
* }
|
|
*/
|
|
public function getLeadMailTemplate()
|
|
{
|
|
try {
|
|
$leadId = (int) $this->request->getGet('lead_id');
|
|
$templateType = strtolower((string) $this->request->getGet('template_type'));
|
|
|
|
if ($leadId <= 0) {
|
|
return $this->respond(
|
|
['status' => 'error', 'code' => 400, 'message' => 'Invalid lead id'],
|
|
400
|
|
);
|
|
}
|
|
|
|
if (! in_array($templateType, ['rfq', 'qcr', 'placement'], true)) {
|
|
// Default to RFQ if not provided or invalid
|
|
$templateType = 'rfq';
|
|
}
|
|
|
|
// Fetch master lead data similar to sendMailWithAttachement / viewRFQ
|
|
$lead_data = $this->leadsModel
|
|
->select('
|
|
leads.*,
|
|
policy_type.long_name,
|
|
policy_type.policy_type,
|
|
user_profiles.email as created_person_email
|
|
')
|
|
->join('policy_type', 'leads.policy_type_id = policy_type.id', 'left')
|
|
->join('user_profiles', 'leads.created_by = user_profiles.id', 'left')
|
|
->where('leads.id', $leadId)
|
|
->where('leads.is_active', 1)
|
|
->first();
|
|
|
|
if (! $lead_data) {
|
|
$this->myLogger->logme('error', "MAIL TEMPLATE: lead not found | lead_id={$leadId}");
|
|
return $this->respond(
|
|
['status' => 'error', 'code' => 404, 'message' => 'Lead not found'],
|
|
404
|
|
);
|
|
}
|
|
|
|
// Determine page name and mail template type
|
|
if ($templateType === 'qcr') {
|
|
$pageName = 'QCR';
|
|
$mailTemplateId = '';
|
|
} elseif ($templateType === 'placement') {
|
|
$pageName = 'Placement';
|
|
$mailTemplateId = 'placement';
|
|
} else {
|
|
// rfq
|
|
$pageName = 'RFQ';
|
|
$mailTemplateId = '';
|
|
}
|
|
|
|
$rawMailTemplate = $this->getMailTemplate($mailTemplateId);
|
|
$rawSubjectTemplate = $this->getSubjectTemplate($lead_data);
|
|
|
|
$mail_content = $this->transformMailContent($lead_data, $rawMailTemplate, $pageName);
|
|
$subject = $this->transformMailContent($lead_data, $rawSubjectTemplate, $pageName);
|
|
|
|
|
|
//attachement files
|
|
$attachments = $this->leadFilesModel
|
|
->where('lead_id', $leadId)
|
|
->where('type !=', 2)
|
|
->where('is_active', 1)
|
|
->findAll();
|
|
|
|
$attachment_html = view('rfq/attachment_files', ['multi_file_data' => $attachments]);
|
|
|
|
return $this->respond(
|
|
[
|
|
'status' => 'success',
|
|
'code' => 200,
|
|
'subject' => $subject,
|
|
'mail_content' => $mail_content,
|
|
'message' => 'Mail template generated successfully',
|
|
'attachment_html' => $attachment_html,
|
|
],
|
|
200
|
|
);
|
|
} catch (\Throwable $e) {
|
|
$errorDetails = [
|
|
'message' => $e->getMessage(),
|
|
'file' => $e->getFile(),
|
|
'line' => $e->getLine(),
|
|
];
|
|
|
|
$this->myLogger->logme(
|
|
'error',
|
|
'MAIL TEMPLATE: exception occurred | ' . json_encode($errorDetails)
|
|
);
|
|
|
|
return $this->respond(
|
|
[
|
|
'status' => 'error',
|
|
'code' => 500,
|
|
'message' => 'Failed to generate mail template',
|
|
],
|
|
500
|
|
);
|
|
}
|
|
}
|
|
|
|
private function normalizeClaimHistoryPostData(): void
|
|
{
|
|
$post = $this->request->getPost();
|
|
|
|
if ((int) ($post['claim_history'] ?? 0) !== 1) {
|
|
return;
|
|
}
|
|
|
|
$rows = $this->getFinyearRowsFromPost($post);
|
|
|
|
if ($rows === []) {
|
|
return;
|
|
}
|
|
|
|
$leadFormType = (int) ($post['lead_form_type'] ?? 1);
|
|
$claimArrays = $leadFormType === 2
|
|
? $this->buildNonEbClaimHistoryPostArrays($rows)
|
|
: $this->buildEbClaimHistoryPostArrays($rows);
|
|
|
|
$this->request->setGlobal('post', array_merge($post, $claimArrays));
|
|
}
|
|
|
|
/**
|
|
* Remove internal nil_claims flag from stored/exported claim rows.
|
|
*
|
|
* @param array<string, mixed> $claimDetails
|
|
*
|
|
* @return array<string, mixed>
|
|
*/
|
|
private function sanitizeClaimDetailsForExport(array $claimDetails): array
|
|
{
|
|
if (empty($claimDetails['finyear']) || ! is_array($claimDetails['finyear'])) {
|
|
return $claimDetails;
|
|
}
|
|
|
|
$claimDetails['finyear'] = array_map(static function ($record) {
|
|
if (! is_array($record)) {
|
|
return $record;
|
|
}
|
|
|
|
unset($record['nil_claims']);
|
|
|
|
return $record;
|
|
}, $claimDetails['finyear']);
|
|
|
|
return $claimDetails;
|
|
}
|
|
|
|
/**
|
|
* @return list<array<string, mixed>>
|
|
*/
|
|
private function getFinyearRowsFromPost(array $postData): array
|
|
{
|
|
$jsonPayload = $postData['finyear'] ?? $postData['fin_years_claims'] ?? null;
|
|
|
|
if (! is_string($jsonPayload) || $jsonPayload === '') {
|
|
return [];
|
|
}
|
|
|
|
$decoded = json_decode($jsonPayload, true);
|
|
|
|
if (! is_array($decoded) || empty($decoded['finyear']) || ! is_array($decoded['finyear'])) {
|
|
return [];
|
|
}
|
|
|
|
return $decoded['finyear'];
|
|
}
|
|
|
|
/**
|
|
* @param list<array<string, mixed>> $rows
|
|
*
|
|
* @return array<string, list<string>>
|
|
*/
|
|
private function buildEbClaimHistoryPostArrays(array $rows): array
|
|
{
|
|
$arrays = [
|
|
'first_year' => [],
|
|
'nil_claims' => [],
|
|
'emp_id' => [],
|
|
'emp_name' => [],
|
|
'gender' => [],
|
|
'designation' => [],
|
|
'sum_insured' => [],
|
|
'first_death_date' => [],
|
|
'first_cause_of_death' => [],
|
|
'first_claim_amount' => [],
|
|
];
|
|
|
|
foreach ($rows as $row) {
|
|
$isNil = ! empty($row['nil_claims']);
|
|
|
|
$arrays['first_year'][] = (string) ($row['year'] ?? '');
|
|
$arrays['nil_claims'][] = $isNil ? '1' : '0';
|
|
|
|
if ($isNil) {
|
|
$arrays['emp_id'][] = 'Nil';
|
|
$arrays['emp_name'][] = 'Nil';
|
|
$arrays['gender'][] = 'Nil';
|
|
$arrays['designation'][] = 'Nil';
|
|
$arrays['sum_insured'][] = 'Nil';
|
|
$arrays['first_death_date'][] = 'Nil';
|
|
$arrays['first_cause_of_death'][] = 'Nil';
|
|
$arrays['first_claim_amount'][] = 'Nil';
|
|
} else {
|
|
$arrays['emp_id'][] = (string) ($row['emp_id'] ?? '');
|
|
$arrays['emp_name'][] = (string) ($row['emp_name'] ?? '');
|
|
$arrays['gender'][] = (string) ($row['gender'] ?? '');
|
|
$arrays['designation'][] = (string) ($row['designation'] ?? '');
|
|
$arrays['sum_insured'][] = (string) ($row['sum_insured'] ?? '');
|
|
$arrays['first_death_date'][] = (string) ($row['death_date'] ?? '');
|
|
$arrays['first_cause_of_death'][] = (string) ($row['cause_of_death'] ?? '');
|
|
$arrays['first_claim_amount'][] = (string) ($row['settled'] ?? ($row['claim_amount'] ?? ''));
|
|
}
|
|
}
|
|
|
|
return $arrays;
|
|
}
|
|
|
|
/**
|
|
* @param list<array<string, mixed>> $rows
|
|
*
|
|
* @return array<string, list<string>>
|
|
*/
|
|
private function buildNonEbClaimHistoryPostArrays(array $rows): array
|
|
{
|
|
$arrays = [
|
|
'first_year' => [],
|
|
'nil_claims' => [],
|
|
'first_policy_type_' => [],
|
|
'first_date_of_loss_' => [],
|
|
'first_cause_of_loss' => [],
|
|
'first_claim_amount' => [],
|
|
'first_settled_amount' => [],
|
|
'first_claim_status' => [],
|
|
];
|
|
|
|
foreach ($rows as $row) {
|
|
$isNil = ! empty($row['nil_claims']);
|
|
|
|
$arrays['first_year'][] = (string) ($row['year'] ?? '');
|
|
$arrays['nil_claims'][] = $isNil ? '1' : '0';
|
|
|
|
if ($isNil) {
|
|
$arrays['first_policy_type_'][] = 'Nil';
|
|
$arrays['first_date_of_loss_'][] = 'Nil';
|
|
$arrays['first_cause_of_loss'][] = 'Nil';
|
|
$arrays['first_claim_amount'][] = 'Nil';
|
|
$arrays['first_settled_amount'][] = 'Nil';
|
|
$arrays['first_claim_status'][] = 'Nil';
|
|
} else {
|
|
$arrays['first_policy_type_'][] = (string) ($row['policy_type'] ?? '');
|
|
$arrays['first_date_of_loss_'][] = (string) ($row['date_of_loss'] ?? '');
|
|
$arrays['first_cause_of_loss'][] = (string) ($row['cause_of_loss'] ?? '');
|
|
$arrays['first_claim_amount'][] = (string) ($row['claim_amount'] ?? '');
|
|
$arrays['first_settled_amount'][] = (string) ($row['settled_amount'] ?? '');
|
|
$arrays['first_claim_status'][] = (string) ($row['status'] ?? '');
|
|
}
|
|
}
|
|
|
|
return $arrays;
|
|
}
|
|
|
|
/**
|
|
* @return array<int, int> Row index => 1 when nil claims, else 0
|
|
*/
|
|
private function resolveNilClaimRowFlags(array $postData): array
|
|
{
|
|
$flags = [];
|
|
|
|
foreach ((array) ($postData['nil_claims'] ?? []) as $idx => $val) {
|
|
$flags[(int) $idx] = (int) $val;
|
|
}
|
|
|
|
foreach ($this->getFinyearRowsFromPost($postData) as $idx => $row) {
|
|
if (! is_array($row)) {
|
|
continue;
|
|
}
|
|
|
|
if (! empty($row['nil_claims'])) {
|
|
$flags[(int) $idx] = 1;
|
|
} elseif (! isset($flags[(int) $idx])) {
|
|
$flags[(int) $idx] = 0;
|
|
}
|
|
}
|
|
|
|
return $flags;
|
|
}
|
|
|
|
/**
|
|
* @param array<int, int> $nilClaimFlags
|
|
*/
|
|
private function getClaimHistoryRowCount(array $postData, array $nilClaimFlags): int
|
|
{
|
|
$counts = [
|
|
count((array) ($postData['first_year'] ?? [])),
|
|
count($nilClaimFlags),
|
|
];
|
|
|
|
$counts[] = count($this->getFinyearRowsFromPost($postData));
|
|
|
|
return max(0, ...$counts);
|
|
}
|
|
|
|
public function getLastFiveFinancialYears(): array
|
|
{
|
|
$year = (int) date('Y');
|
|
$month = (int) date('m');
|
|
// $month = (int) 5;
|
|
|
|
// Financial year starts in April
|
|
$currentFYStart = ($month >= 4) ? $year : $year - 1;
|
|
|
|
$financialYears = [];
|
|
|
|
for ($i = 0; $i < 6; $i++) {
|
|
$startYear = $currentFYStart - $i;
|
|
$endYear = $startYear + 1;
|
|
$financialYears[] = "{$startYear}-{$endYear}";
|
|
}
|
|
|
|
return $financialYears;
|
|
}
|
|
|
|
/**
|
|
* Fetch basic placement-related lead data for Non-EB placement modal (AJAX).
|
|
*
|
|
* Route: GET /rfq/placementData/{lead_id}
|
|
*/
|
|
public function getPlacementData($id)
|
|
{
|
|
try {
|
|
$leadId = (int) $id;
|
|
|
|
if ($leadId <= 0) {
|
|
return $this->respond(
|
|
['status' => 'error', 'code' => 400, 'message' => 'Invalid lead id'],
|
|
400
|
|
);
|
|
}
|
|
|
|
$lead = $this->leadsModel
|
|
->where('id', $leadId)
|
|
->where('is_active', 1)
|
|
->first();
|
|
|
|
if (! $lead) {
|
|
$this->myLogger->logme('error', "PLACEMENT DATA: lead not found | lead_id={$leadId}");
|
|
return $this->respond(
|
|
['status' => 'error', 'code' => 404, 'message' => 'Lead not found'],
|
|
404
|
|
);
|
|
}
|
|
|
|
$data = [
|
|
'id' => (int) $lead['id'],
|
|
'policy_start_date' => ! empty($lead['policy_start_date']) ? date('d-m-Y', strtotime($lead['policy_start_date'])) : null,
|
|
'policy_end_date' => ! empty($lead['policy_end_date']) ? date('d-m-Y', strtotime($lead['policy_end_date'])) : null,
|
|
'placement_date' => ! empty($lead['placement_date']) ? date('d-m-Y', strtotime($lead['placement_date'])) : null,
|
|
'payment_date' => ! empty($lead['payment_date']) ? date('d-m-Y', strtotime($lead['payment_date'])) : null,
|
|
'utr_no' => $lead['utr_no'] ?? null,
|
|
'premium_amount' => $lead['premium_amount'] ?? null,
|
|
'cd_amount' => $lead['cd_amount'] ?? null,
|
|
'total_amount' => $lead['total_amount'] ?? null,
|
|
'is_cd' => isset($lead['is_cd']) ? (int) $lead['is_cd'] : 1,
|
|
'is_installment' => isset($lead['is_installment']) ? (int) $lead['is_installment'] : 0,
|
|
'no_of_installment' => $lead['no_of_installment'] ?? 1,
|
|
'status' => $lead['status'] ?? null,
|
|
];
|
|
|
|
// Fetch insurer level contacts based on lead's insurer/branch
|
|
$insurerId = $lead['insurer_id'] ?? null;
|
|
$insurerBranchId = $lead['insurer_branch_id'] ?? null;
|
|
// echo $insurerId;die();
|
|
$insurerContacts = [];
|
|
if (! empty($insurerId)) {
|
|
// getContactForRFQ($insurerId, $branchId) returns insurer-level contacts
|
|
$contacts = $this->levelContactModel->getContactForRFQ($insurerId, $insurerBranchId);
|
|
// print_rr($contacts);die();
|
|
if (! empty($contacts) && is_array($contacts)) {
|
|
foreach ($contacts as $contact) {
|
|
$insurerContacts[] = [
|
|
'id' => (int) ($contact['id'] ?? 0),
|
|
'display' => trim(
|
|
($contact['insurer_name'] ?? '') . ' - ' .
|
|
($contact['branch_code'] ?? '') . ' - ' .
|
|
($contact['contact_person_name'] ?? '') . ' - ' .
|
|
($contact['contact_person_email'] ?? '')
|
|
),
|
|
'email' => $contact['contact_person_email'] ?? '',
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Client contact from lead data for placement TO
|
|
$clientContact = null;
|
|
if (! empty($lead['contact_person_email'])) {
|
|
$clientContact = [
|
|
'name' => $lead['contact_person_name'] ?? '',
|
|
'email' => $lead['contact_person_email'],
|
|
];
|
|
}
|
|
|
|
$data['insurer_contacts'] = $insurerContacts;
|
|
$data['client_contact'] = $clientContact;
|
|
|
|
return $this->respond(
|
|
[
|
|
'status' => 'success',
|
|
'code' => 200,
|
|
'data' => $data,
|
|
],
|
|
200
|
|
);
|
|
} catch (\Throwable $e) {
|
|
$errorDetails = [
|
|
'message' => $e->getMessage(),
|
|
'file' => $e->getFile(),
|
|
'line' => $e->getLine(),
|
|
];
|
|
|
|
$this->myLogger->logme(
|
|
'error',
|
|
'PLACEMENT DATA: exception occurred | ' . json_encode($errorDetails)
|
|
);
|
|
|
|
return $this->respond(
|
|
[
|
|
'status' => 'error',
|
|
'code' => 500,
|
|
'message' => 'Failed to fetch placement data',
|
|
],
|
|
500
|
|
);
|
|
}
|
|
}
|
|
|
|
// ------------ RFQ NON EB FUNCTIONS-----------------------------------------------------------------------------------------
|
|
|
|
public function rfqNonEB()
|
|
{
|
|
|
|
$this->loadLayout('view_rfq_non_eb');
|
|
}
|
|
|
|
/**
|
|
* Dedicated endpoint to view RFQ for Non-EB opportunities from the Opportunities List.
|
|
* Internally reuses the existing viewRFQ flow without modifying its logic.
|
|
*/
|
|
public function viewNonEbRFQFromList($id)
|
|
{
|
|
echo 'NONEB_RFQ';
|
|
}
|
|
|
|
/**
|
|
* Dedicated endpoint to view QCR for Non-EB opportunities from the Opportunities List.
|
|
* Internally reuses the existing viewRFQ flow without modifying its logic.
|
|
*/
|
|
public function viewNonEbQCRFromList($id)
|
|
{
|
|
echo 'NONEB_QCR';
|
|
}
|
|
|
|
// get lead data for edit both EB and NON-EB
|
|
public function getLeadNonEB($type, $actual_lead_id = null, $id = null)
|
|
{
|
|
// Convert '0' to null so it doesn't break your existing DB checks
|
|
$actual_lead_id = ($actual_lead_id == 0 || $actual_lead_id == '0') ? null : $actual_lead_id;
|
|
// Set basic data
|
|
$data = [
|
|
'issuer' => $this->issuer,
|
|
'client_type' => $this->clientType,
|
|
'lead_type' => $this->leadType,
|
|
'lead_status' => $this->leadsStatus,
|
|
'policy_type' => $this->policyTypeModel->where('is_active', 1)->findAll(),
|
|
'entity' => $this->kycEntityTypeModel->where('is_active', 1)->findAll(),
|
|
'insurer' => $this->insurerBranchModel->getInsurerBranchesWithInsurerNames(),
|
|
'tpa' => $this->tpaBranchModel->getTpaBranchesWithTpaNames(),
|
|
'lastFiveYears' => $this->getLastFiveFinancialYears(),
|
|
'gpaClaimType' => $this->claim_type_for_gpa,
|
|
'causeOfDeath' => $this->cause_of_death,
|
|
'selected_lead_type' => $type,
|
|
'actual_lead_id' => $actual_lead_id,
|
|
];
|
|
$data['tab_name'] = 'Opportunities';
|
|
$data['page_name'] = 'Opportunities';
|
|
|
|
if ($actual_lead_id > 0) {
|
|
|
|
// 🔹 Client Details (Single Row)
|
|
$data['actual_lead_client_details'] = $this->leadModel
|
|
->select("
|
|
sales_actual_leads.company_name,
|
|
clients.short_name,
|
|
clients.client_type,
|
|
sales_actual_leads.email,
|
|
sales_actual_leads.phone,
|
|
sales_actual_leads.address,
|
|
sales_actual_leads.website,
|
|
COALESCE(NULLIF(sales_actual_leads.gst_number, ''), clients.gst) AS gst_number,
|
|
sales_actual_leads.status,
|
|
sales_actual_leads.assigned_to
|
|
", false)
|
|
->join('clients', 'clients.id = sales_actual_leads.client_id', 'left')
|
|
->where('sales_actual_leads.lead_id', $actual_lead_id)
|
|
->first(); // first row only
|
|
|
|
|
|
// 🔹 Contact Person Details (First Row Only)
|
|
$data['actual_lead_contact_person_details'] = $this->contactModel
|
|
->select('contact_id, name, mobile, designation, email, is_primary')
|
|
->where('lead_id', $actual_lead_id)
|
|
->where('is_primary',1)
|
|
->orderBy('is_primary', 'DESC') // optional (primary first)
|
|
->first(); // only first row
|
|
}
|
|
else {
|
|
$data['actual_lead_client_details'] = null;
|
|
$data['actual_lead_contact_person_details'] = null;
|
|
}
|
|
|
|
// Fetch sales team members who are active in team 5
|
|
$data['salse_team'] = $this->userModel
|
|
->select('user_profiles.*')
|
|
->join('user_teams', 'user_profiles.id = user_teams.user_id')
|
|
->where('user_teams.team_id', 5)
|
|
->where('user_teams.is_active', 1)
|
|
->where('user_profiles.is_active', 1)
|
|
->findAll();
|
|
|
|
if (! empty($id)) {
|
|
|
|
$data['lead_edit_data'] = $this->leadsModel->where('id', $id)->first() ?? [];
|
|
|
|
$data['lead_edit_data']['multi_file_data'] = $this->leadFilesModel
|
|
->where('lead_id', $id)
|
|
->where('type !=', 2)
|
|
->where('is_active', 1)
|
|
->findAll() ?? null;
|
|
$data['lead_edit_data']['lead_file_count'] = count($data['lead_edit_data']['multi_file_data']);
|
|
|
|
// Decode and merge custom fields if present
|
|
$custom_fields_data = ! empty($data['lead_edit_data']['custom_fields'])
|
|
? json_decode($data['lead_edit_data']['custom_fields'], true)
|
|
: [];
|
|
|
|
if (! empty($custom_fields_data) && is_array($custom_fields_data)) {
|
|
$data['lead_edit_data'] = array_merge($data['lead_edit_data'], $custom_fields_data);
|
|
}
|
|
|
|
if (! empty($data['lead_edit_data'])) {
|
|
foreach (['policy_start_date', 'policy_end_date', 'source_policy_start_date', 'source_policy_end_date', 'incurred_claims_date', 'next_reminder_date'] as $dateField) {
|
|
$data['lead_edit_data'][$dateField] = ! empty($data['lead_edit_data'][$dateField])
|
|
? change_date_format($data['lead_edit_data'][$dateField], 'Y-m-d', 'd/m/Y')
|
|
: null;
|
|
}
|
|
|
|
$data['lead_edit_data']['fin_years_claims_array'] = ! empty($data['lead_edit_data']['fin_years_claims'])
|
|
? json_decode($data['lead_edit_data']['fin_years_claims'], true)['finyear'] ?? []
|
|
: [];
|
|
|
|
$data['lead_edit_data']['html'] = $this->generateViewPageHtml(
|
|
$data['lead_edit_data']['policy_type_id'] ?? null,
|
|
$data
|
|
) ?? "";
|
|
|
|
$html = view('rfq/multi_files', $data);
|
|
$data['lead_edit_data']['multi_file_html'] = trim($html) !== '' ? $html : null;
|
|
}
|
|
|
|
if (in_array((int) $data['lead_edit_data']['lead_type'], [1, 2, 3], true) && $data['lead_edit_data']['lead_form_type'] == 2) {
|
|
$data['lead_edit_data']['claims_details_html'] = view('rfq/claims_details_non_eb', [
|
|
'lead_edit_data' => $data['lead_edit_data'],
|
|
'lastFiveYears' => $data['lastFiveYears'] ?? $this->getLastFiveFinancialYears(),
|
|
]);
|
|
} else {
|
|
$data['lead_edit_data']['claims_details_html'] = "";
|
|
}
|
|
}
|
|
// dd($data);
|
|
|
|
return $this->loadLayout('leads_form_handler', $data);
|
|
}
|
|
|
|
public function getLeadEmailHistory($id)
|
|
{
|
|
if (! empty($id)) {
|
|
$result = $this->gmailSentHistoryModel
|
|
->where('pk', $id)
|
|
->where('module', "leads")
|
|
->orderBy('created_at', 'desc')
|
|
->findAll();
|
|
if (! empty($result)) {
|
|
$result = ! empty($result) ? $result : [];
|
|
return $this->response->setJSON((['status' => 'success', 'data' => $result]))->setStatusCode(200);
|
|
} else {
|
|
return $this->response->setJSON((['status' => 'error', 'message' => 'No History found']))->setStatusCode(400);
|
|
}
|
|
} else {
|
|
return $this->response->setJSON((['status' => 'error', 'message' => 'ID not found']))->setStatusCode(404);
|
|
}
|
|
|
|
// Select * from gmail_sent_history where pk != "" and module = "leads";
|
|
// echo $id;
|
|
}
|
|
|
|
public function getPolicyTypeFields()
|
|
{
|
|
|
|
$policy_type_id = $this->request->getGET('policy_type_id');
|
|
|
|
$html = $this->generateViewPageHtml($policy_type_id) ?? "";
|
|
|
|
if (! empty($html)) {
|
|
return $this->respond(['status' => true, 'code' => 200, 'message' => 'Policy Type FIELDS are found', 'data' => $html], 200);
|
|
} else {
|
|
return $this->respond(['status' => false, 'code' => 400, 'message' => 'Fields not found for this policy type'], 200);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* AJAX endpoint to create or fetch RFQ Google Sheet for a lead.
|
|
*
|
|
* Flow:
|
|
* - Get lead_id from query param.
|
|
* - Fetch lead joined with policy_type (to read both misc columns).
|
|
* - If leads.misc has non-empty rfq_sheet_id, return that.
|
|
* - Else, read policy_type.misc.rfq_template_sheet_id and copy that template.
|
|
* - Apply protections (using RfqConfig if available).
|
|
* - Store new rfq_sheet_id back into leads.misc.
|
|
*/
|
|
public function createRfqSheet()
|
|
{
|
|
try {
|
|
$leadId = (int) $this->request->getGet('lead_id');
|
|
|
|
if ($leadId <= 0) {
|
|
return $this->respond(
|
|
['status' => 'error', 'code' => 400, 'message' => 'Invalid lead id'],
|
|
400
|
|
);
|
|
}
|
|
|
|
$this->myLogger->logme('error', "RFQ Sheet: starting for lead_id={$leadId}");
|
|
|
|
// Fetch lead + policy type + client address (LEFT JOIN for communication address on EB leads)
|
|
$lead = $this->leadsModel
|
|
->select('
|
|
leads.*,
|
|
policy_type.policy_type,
|
|
policy_type.long_name,
|
|
policy_type.misc as policy_misc,
|
|
clients.address1 as client_address1,
|
|
clients.address2 as client_address2,
|
|
clients.city as client_city,
|
|
clients.state as client_state,
|
|
clients.pincode as client_pincode
|
|
')
|
|
->join('policy_type', 'leads.policy_type_id = policy_type.id', 'left')
|
|
->join('clients', 'leads.client_id = clients.id', 'left')
|
|
->where('leads.id', $leadId)
|
|
->where('leads.is_active', 1)
|
|
->first();
|
|
|
|
if (! $lead) {
|
|
$this->myLogger->logme('error', "RFQ Sheet: lead not found | lead_id={$leadId}");
|
|
return $this->respond(
|
|
['status' => 'error', 'code' => 404, 'message' => 'Lead not found'],
|
|
404
|
|
);
|
|
}
|
|
|
|
// Decode leads.misc
|
|
$leadMisc = [];
|
|
if (! empty($lead['misc'])) {
|
|
$decoded = json_decode($lead['misc'], true);
|
|
if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
|
|
$leadMisc = $decoded;
|
|
} else {
|
|
$this->myLogger->logme('error', "RFQ Sheet: invalid JSON in leads.misc | lead_id={$leadId}, misc={$lead['misc']}");
|
|
}
|
|
}
|
|
|
|
// If RFQ sheet already exists, just return it
|
|
if (! empty($leadMisc['rfq_sheet_id'])) {
|
|
$sheetId = (string) $leadMisc['rfq_sheet_id'];
|
|
$sheetLib = new GoogleSheetLib();
|
|
$sheetUrl = $sheetLib->sheetUrl($sheetId);
|
|
|
|
$this->myLogger->logme('error', "RFQ Sheet: existing sheet found | lead_id={$leadId}, sheet_id={$sheetId}");
|
|
|
|
return $this->respond(
|
|
[
|
|
'status' => 'success',
|
|
'code' => 200,
|
|
'sheet_id' => $sheetId,
|
|
'sheet_url' => $sheetUrl,
|
|
'message' => 'RFQ sheet already exists',
|
|
],
|
|
200
|
|
);
|
|
}
|
|
|
|
// Decode policy_type.misc and get template id
|
|
$policyMisc = [];
|
|
if (! empty($lead['policy_misc'])) {
|
|
$decodedPolicy = json_decode($lead['policy_misc'], true);
|
|
if (json_last_error() === JSON_ERROR_NONE && is_array($decodedPolicy)) {
|
|
$policyMisc = $decodedPolicy;
|
|
} else {
|
|
$this->myLogger->logme('error', "RFQ Sheet: invalid JSON in policy_type.misc | lead_id={$leadId}, policy_misc={$lead['policy_misc']}");
|
|
}
|
|
}
|
|
|
|
$templateId = $policyMisc['rfq_template_sheet_id'] ?? null;
|
|
if (empty($templateId)) {
|
|
$this->myLogger->logme(
|
|
'error',
|
|
"RFQ Sheet: rfq_template_sheet_id missing | lead_id={$leadId}, policy_misc=" . ($lead['policy_misc'] ?? 'NULL')
|
|
);
|
|
|
|
return $this->respond(
|
|
[
|
|
'status' => 'error',
|
|
'code' => 400,
|
|
'message' => 'RFQ template not found for this policy type',
|
|
],
|
|
400
|
|
);
|
|
}
|
|
|
|
// Prepare Google Sheet lib and config
|
|
$sheetLib = new GoogleSheetLib();
|
|
|
|
// Try to use RfqConfig if available for folder/protections
|
|
$parentFolderId = null;
|
|
$protections = [];
|
|
|
|
try {
|
|
/** @var \Config\RfqConfig $rfqConfig */
|
|
$rfqConfig = config('RfqConfig');
|
|
if ($rfqConfig) {
|
|
$parentFolderId = $rfqConfig->rfqParentFolderId ?? null;
|
|
$protections = $rfqConfig->protections ?? [];
|
|
}
|
|
} catch (\Throwable $e) {
|
|
// Config is optional; just log and continue with defaults
|
|
$this->myLogger->logme('error', 'RFQ Sheet: error loading RfqConfig | ' . $e->getMessage());
|
|
}
|
|
|
|
// Fallback to same parent folder as GoogleSheetController if config not set
|
|
if (! $parentFolderId) {
|
|
return $this->respond(
|
|
[
|
|
'status' => 'error',
|
|
'code' => 400,
|
|
'message' => 'Google config not correct, contact administrator',
|
|
],
|
|
400);
|
|
}
|
|
|
|
// Filename logic same as exportQCRandRFQ (lines 2660-2673)
|
|
$string = 'RFQ';
|
|
$current_year = date('Y');
|
|
$next_year = $current_year + 1;
|
|
$policy_year = "{$current_year}-{$next_year}";
|
|
|
|
$clientName = trim($lead['client_name'] ?? $lead['client_short_name'] ?? '');
|
|
$policyType = trim($lead['policy_type'] ?? '');
|
|
|
|
if (! empty($lead['policy_end_date'])) {
|
|
$policy_expiry = strtotime($lead['policy_end_date']);
|
|
$formatted_policy = date('d-m-Y', $policy_expiry);
|
|
$sheetName = "{$clientName}_{$policyType}_{$string}_{$policy_year}(Due On {$formatted_policy}).xlsx";
|
|
} else {
|
|
$sheetName = "{$clientName}_{$policyType}_{$string}_{$policy_year}_" . '.xlsx';
|
|
}
|
|
|
|
// Copy template in Drive
|
|
$newSheetId = $sheetLib->copyTemplate($templateId, $sheetName, $parentFolderId);
|
|
$this->myLogger->logme('error', "RFQ Sheet: template copied | lead_id={$leadId}, template_id={$templateId}, new_sheet_id={$newSheetId}");
|
|
|
|
// Fill placeholders across all sheets (see Config\RfqConfig::$rfqPlaceholders)
|
|
try {
|
|
/** @var \Config\RfqConfig $rfqCfg */
|
|
$rfqCfg = config('RfqConfig');
|
|
$placeholderData = $this->buildRfqPlaceholderData($lead);
|
|
$claimsPh = $rfqCfg->rfqClaimsPlaceholder ?? '{{CLAIMS_DETAILS}}';
|
|
$map = $rfqCfg->rfqPlaceholders ?? [];
|
|
$textReplacements = [];
|
|
|
|
foreach ($map as $placeholder => $key) {
|
|
if ($placeholder === $claimsPh) {
|
|
continue;
|
|
}
|
|
$textReplacements[$placeholder] = (string) ($placeholderData['values'][$key] ?? '');
|
|
}
|
|
|
|
$sheetLib->findAndReplaceAllSheets($newSheetId, $textReplacements);
|
|
|
|
if ($placeholderData['claims_table'] !== null) {
|
|
$written = $sheetLib->writeTableAtPlaceholder(
|
|
$newSheetId,
|
|
$claimsPh,
|
|
$placeholderData['claims_table']
|
|
);
|
|
|
|
if (! $written) {
|
|
$sheetLib->findAndReplaceAllSheets($newSheetId, [
|
|
$claimsPh => $placeholderData['claims_placeholder_fallback'],
|
|
]);
|
|
}
|
|
} else {
|
|
$sheetLib->findAndReplaceAllSheets($newSheetId, [
|
|
$claimsPh => $placeholderData['claims_placeholder_fallback'],
|
|
]);
|
|
}
|
|
|
|
$this->myLogger->logme('error', "RFQ Sheet: placeholders applied | lead_id={$leadId}, sheet_id={$newSheetId}");
|
|
} catch (\Throwable $e) {
|
|
$this->myLogger->logme(
|
|
'error',
|
|
"RFQ Sheet: placeholder fill failed | lead_id={$leadId}, error=" . $e->getMessage()
|
|
);
|
|
}
|
|
|
|
// Apply permissions: get sales users from DB (team_id 5) and add as editors
|
|
// $salesTeam = $this->userModel
|
|
// ->select('user_profiles.email')
|
|
// ->join('user_teams', 'user_profiles.id = user_teams.user_id')
|
|
// ->where('user_teams.team_id', 5)
|
|
// ->where('user_teams.is_active', 1)
|
|
// ->where('user_profiles.is_active', 1)
|
|
// ->findAll();
|
|
// $editorEmails = array_values(array_filter(array_unique(array_column($salesTeam, 'email'))));
|
|
|
|
// Decode rfq_qcr_viewers from lead and add as viewers
|
|
$editorEmails = [];
|
|
if (! empty($lead['rfq_qcr_viewers'])) {
|
|
$decoded = json_decode($lead['rfq_qcr_viewers'], true);
|
|
if (is_array($decoded)) {
|
|
$editorEmails = array_values(array_filter(array_unique($decoded)));
|
|
}
|
|
}
|
|
|
|
if ( ! empty($editorEmails)) {
|
|
try {
|
|
$sheetLib->applyPermissions($newSheetId, [
|
|
'editors' => $editorEmails,
|
|
// 'viewers' => $viewerEmails,
|
|
]);
|
|
$this->myLogger->logme('error', "RFQ Sheet: permissions applied | sheet_id={$newSheetId}, editors=" . count($editorEmails) );
|
|
} catch (\Throwable $e) {
|
|
$this->myLogger->logme(
|
|
'error',
|
|
"RFQ Sheet: failed to apply permissions | sheet_id={$newSheetId}, error=" . $e->getMessage()
|
|
);
|
|
}
|
|
}
|
|
|
|
// Apply protections if configured
|
|
if (! empty($protections)) {
|
|
try {
|
|
$sheetLib->applyProtections($newSheetId, $protections);
|
|
$this->myLogger->logme('error', "RFQ Sheet: protections applied | sheet_id={$newSheetId}");
|
|
} catch (\Throwable $e) {
|
|
$this->myLogger->logme(
|
|
'error',
|
|
"RFQ Sheet: failed to apply protections | sheet_id={$newSheetId}, error=" . $e->getMessage()
|
|
);
|
|
}
|
|
}
|
|
|
|
// Update leads.misc with new rfq_sheet_id
|
|
$leadMisc['rfq_sheet_id'] = $newSheetId;
|
|
$this->leadsModel->update($leadId, [
|
|
'misc' => json_encode($leadMisc),
|
|
'status' => 'rfq_created',
|
|
]);
|
|
|
|
$sheetUrl = $sheetLib->sheetUrl($newSheetId);
|
|
|
|
$this->myLogger->logme(
|
|
'error',
|
|
"RFQ Sheet: created and stored | lead_id={$leadId}, sheet_id={$newSheetId}"
|
|
);
|
|
|
|
return $this->respond(
|
|
[
|
|
'status' => 'success',
|
|
'code' => 200,
|
|
'sheet_id' => $newSheetId,
|
|
'sheet_url' => $sheetUrl,
|
|
'message' => 'RFQ sheet created successfully',
|
|
],
|
|
200
|
|
);
|
|
} catch (\Throwable $e) {
|
|
$errorDetails = [
|
|
'message' => $e->getMessage(),
|
|
'file' => $e->getFile(),
|
|
'line' => $e->getLine(),
|
|
];
|
|
|
|
$this->myLogger->logme(
|
|
'error',
|
|
'RFQ Sheet: exception occurred | ' . json_encode($errorDetails)
|
|
);
|
|
|
|
return $this->respond(
|
|
[
|
|
'status' => 'error',
|
|
'code' => 500,
|
|
'message' => 'Failed to create RFQ sheet',
|
|
],
|
|
500
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build values for RFQ Google Sheet placeholders (see RfqConfig::$rfqPlaceholders).
|
|
*
|
|
* @return array{values: array<string, string>, claims_table: ?list<list<string|int|float>>, claims_placeholder_fallback: string}
|
|
*/
|
|
private function buildRfqPlaceholderData(array $lead): array
|
|
{
|
|
helper('excel_util_helper');
|
|
|
|
$custom = [];
|
|
|
|
if (! empty($lead['custom_fields'])) {
|
|
$decoded = json_decode($lead['custom_fields'], true);
|
|
|
|
if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
|
|
$custom = $decoded;
|
|
}
|
|
}
|
|
|
|
$clientParts = array_filter([
|
|
trim((string) ($lead['client_address1'] ?? '')),
|
|
trim((string) ($lead['client_address2'] ?? '')),
|
|
trim((string) ($lead['client_city'] ?? '')),
|
|
trim((string) ($lead['client_state'] ?? '')),
|
|
trim((string) ($lead['client_pincode'] ?? '')),
|
|
], static function ($s) {
|
|
return $s !== '';
|
|
});
|
|
$clientAddr = implode(', ', $clientParts);
|
|
|
|
$cfParts = array_filter([
|
|
trim((string) ($custom['address'] ?? '')),
|
|
trim((string) ($custom['pincode'] ?? '')),
|
|
], static function ($s) {
|
|
return $s !== '';
|
|
});
|
|
$cfAddr = implode(', ', $cfParts);
|
|
|
|
$communicationAddress = $clientAddr !== '' ? $clientAddr : $cfAddr;
|
|
|
|
$policyPeriod = '';
|
|
|
|
if (! empty($lead['policy_start_date']) && ! empty($lead['policy_end_date'])) {
|
|
$policyPeriod = date('d-m-Y', strtotime((string) $lead['policy_start_date']))
|
|
. ' to '
|
|
. date('d-m-Y', strtotime((string) $lead['policy_end_date']));
|
|
}
|
|
|
|
$lt = (int) ($lead['lead_type'] ?? 0);
|
|
$opportunityType = $this->leadType[$lt] ?? '';
|
|
|
|
$riskRaw = (string) ($custom['risk_location'] ?? '');
|
|
$riskLocation = $riskRaw !== ''
|
|
? ucwords(str_replace('_', ' ', strtolower($riskRaw)))
|
|
: '';
|
|
|
|
$occupancyRaw = (string) ($custom['business_description'] ?? $custom['occupancy_risk'] ?? '');
|
|
$occupancy = $occupancyRaw !== ''
|
|
? ucwords(str_replace('_', ' ', strtolower($occupancyRaw)))
|
|
: '';
|
|
|
|
$claimsTable = null;
|
|
$claimsFallback = 'No claims data available';
|
|
|
|
if (! empty($lead['fin_years_claims'])) {
|
|
$claimJson = json_decode($lead['fin_years_claims'], true);
|
|
|
|
if (json_last_error() === JSON_ERROR_NONE && is_array($claimJson)) {
|
|
$finyear = $claimJson['finyear'] ?? null;
|
|
|
|
if (is_array($finyear) && $finyear !== []) {
|
|
$claimsTable = $this->buildRfqClaimsTableValues($finyear);
|
|
}
|
|
}
|
|
}
|
|
|
|
$values = [
|
|
'insured_name' => trim((string) ($lead['client_name'] ?? $lead['client_short_name'] ?? '')),
|
|
'communication_address' => $communicationAddress,
|
|
'gst' => trim((string) ($lead['gst'] ?? '')),
|
|
'pan' => trim((string) ($lead['pan'] ?? '')),
|
|
'policy_period' => $policyPeriod,
|
|
'opportunity_type' => $opportunityType,
|
|
'risk_location' => $riskLocation,
|
|
'occupancy' => $occupancy,
|
|
'claims_details' => '',
|
|
];
|
|
|
|
return [
|
|
'values' => $values,
|
|
'claims_table' => $claimsTable,
|
|
'claims_placeholder_fallback' => $claimsFallback,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @param list<array<string, mixed>> $finyear
|
|
*
|
|
* @return list<list<string|int|float>>
|
|
*/
|
|
private function buildRfqClaimsTableValues(array $finyear): array
|
|
{
|
|
helper('excel_util_helper');
|
|
|
|
$finyear = array_map(static function ($record) {
|
|
if (! is_array($record)) {
|
|
return $record;
|
|
}
|
|
|
|
unset($record['nil_claims']);
|
|
|
|
return $record;
|
|
}, $finyear);
|
|
|
|
$first = $finyear[0] ?? null;
|
|
|
|
if (! is_array($first) || $first === []) {
|
|
return [['No data available']];
|
|
}
|
|
|
|
$headers = [];
|
|
|
|
foreach (array_keys($first) as $key) {
|
|
$headers[] = ucwords(str_replace('_', ' ', (string) $key));
|
|
}
|
|
|
|
$rows = [];
|
|
$rows[] = $headers;
|
|
|
|
foreach ($finyear as $record) {
|
|
if (! is_array($record)) {
|
|
continue;
|
|
}
|
|
|
|
$line = [];
|
|
|
|
foreach ($record as $arrayKey => $value) {
|
|
if (in_array($arrayKey, ['sum_insured', 'claim_amount', 'settled'], true)) {
|
|
$line[] = function_exists('formatIndianCurrency')
|
|
? formatIndianCurrency((int) $value)
|
|
: (string) $value;
|
|
} else {
|
|
$line[] = $value === null || $value === '' ? '' : (string) $value;
|
|
}
|
|
}
|
|
|
|
$rows[] = $line;
|
|
}
|
|
|
|
return $rows;
|
|
}
|
|
|
|
public function createQcrSheet()
|
|
{
|
|
try {
|
|
$leadId = (int) $this->request->getGet('lead_id');
|
|
|
|
if ($leadId <= 0) {
|
|
return $this->respond(
|
|
['status' => 'error', 'code' => 400, 'message' => 'Invalid lead id'],
|
|
400
|
|
);
|
|
}
|
|
|
|
$this->myLogger->logme('error', "QCR Sheet: starting for lead_id={$leadId}");
|
|
|
|
$lead = $this->leadsModel
|
|
->select('
|
|
leads.*,
|
|
policy_type.policy_type,
|
|
policy_type.long_name,
|
|
policy_type.misc as policy_misc
|
|
')
|
|
->join('policy_type', 'leads.policy_type_id = policy_type.id', 'left')
|
|
->where('leads.id', $leadId)
|
|
->where('leads.is_active', 1)
|
|
->first();
|
|
|
|
if (! $lead) {
|
|
$this->myLogger->logme('error', "QCR Sheet: lead not found | lead_id={$leadId}");
|
|
return $this->respond(
|
|
['status' => 'error', 'code' => 404, 'message' => 'Lead not found'],
|
|
404
|
|
);
|
|
}
|
|
|
|
$leadMisc = [];
|
|
if (! empty($lead['misc'])) {
|
|
$decoded = json_decode($lead['misc'], true);
|
|
if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
|
|
$leadMisc = $decoded;
|
|
}
|
|
}
|
|
|
|
// If QCR sheet already exists, just return it
|
|
if (! empty($leadMisc['qcr_sheet_id'])) {
|
|
$sheetId = (string) $leadMisc['qcr_sheet_id'];
|
|
$sheetLib = new GoogleSheetLib();
|
|
$sheetUrl = $sheetLib->sheetUrl($sheetId);
|
|
|
|
$this->myLogger->logme('error', "QCR Sheet: existing sheet found | lead_id={$leadId}, sheet_id={$sheetId}");
|
|
|
|
return $this->respond(
|
|
[
|
|
'status' => 'success',
|
|
'code' => 200,
|
|
'sheet_id' => $sheetId,
|
|
'sheet_url' => $sheetUrl,
|
|
'message' => 'QCR sheet already exists',
|
|
],
|
|
200
|
|
);
|
|
}
|
|
|
|
// Source is the existing RFQ sheet for this lead
|
|
$rfqSheetId = $leadMisc['rfq_sheet_id'] ?? null;
|
|
if (empty($rfqSheetId)) {
|
|
$this->myLogger->logme('error', "QCR Sheet: rfq_sheet_id missing in leads.misc | lead_id={$leadId}");
|
|
return $this->respond(
|
|
['status' => 'error', 'code' => 400, 'message' => 'RFQ sheet not found. Please create the RFQ sheet first.'],
|
|
400
|
|
);
|
|
}
|
|
|
|
// Load config for folder id and permissions
|
|
$parentFolderId = null;
|
|
$permissions = [];
|
|
|
|
try {
|
|
/** @var \Config\RfqConfig $rfqConfig */
|
|
$rfqConfig = config('RfqConfig');
|
|
if ($rfqConfig) {
|
|
$parentFolderId = $rfqConfig->rfqParentFolderId ?? null;
|
|
$permissions = $rfqConfig->permissions ?? [];
|
|
}
|
|
} catch (\Throwable $e) {
|
|
$this->myLogger->logme('error', 'QCR Sheet: error loading RfqConfig | ' . $e->getMessage());
|
|
}
|
|
|
|
if (! $parentFolderId) {
|
|
return $this->respond(
|
|
['status' => 'error', 'code' => 400, 'message' => 'Google config not correct, contact administrator'],
|
|
400
|
|
);
|
|
}
|
|
|
|
// Build filename: same as RFQ naming but with QCR
|
|
$string = 'QCR';
|
|
$current_year = date('Y');
|
|
$next_year = $current_year + 1;
|
|
$policy_year = "{$current_year}-{$next_year}";
|
|
|
|
$clientName = trim($lead['client_name'] ?? $lead['client_short_name'] ?? '');
|
|
$policyType = trim($lead['policy_type'] ?? '');
|
|
|
|
if (! empty($lead['policy_end_date'])) {
|
|
$policy_expiry = strtotime($lead['policy_end_date']);
|
|
$formatted_policy = date('d-m-Y', $policy_expiry);
|
|
$sheetName = "{$clientName}_{$policyType}_{$string}_{$policy_year}(Due On {$formatted_policy}).xlsx";
|
|
} else {
|
|
$sheetName = "{$clientName}_{$policyType}_{$string}_{$policy_year}_.xlsx";
|
|
}
|
|
|
|
$sheetLib = new GoogleSheetLib();
|
|
$newSheetId = $sheetLib->copyTemplate($rfqSheetId, $sheetName, $parentFolderId);
|
|
$this->myLogger->logme('error', "QCR Sheet: copied from RFQ sheet | lead_id={$leadId}, rfq_sheet_id={$rfqSheetId}, new_sheet_id={$newSheetId}");
|
|
|
|
// Apply permissions: sales team as editors
|
|
// $salesTeam = $this->userModel
|
|
// ->select('user_profiles.email')
|
|
// ->join('user_teams', 'user_profiles.id = user_teams.user_id')
|
|
// ->where('user_teams.team_id', 5)
|
|
// ->where('user_teams.is_active', 1)
|
|
// ->where('user_profiles.is_active', 1)
|
|
// ->findAll();
|
|
// $editorEmails = array_values(array_filter(array_unique(array_column($salesTeam, 'email'))));
|
|
|
|
// Decode rfq_qcr_viewers from lead and add as viewers
|
|
$editorEmails = [];
|
|
if (! empty($lead['rfq_qcr_viewers'])) {
|
|
$decoded = json_decode($lead['rfq_qcr_viewers'], true);
|
|
if (is_array($decoded)) {
|
|
$editorEmails = array_values(array_filter(array_unique($decoded)));
|
|
}
|
|
}
|
|
|
|
// !dd($editorEmails);
|
|
if (! empty($editorEmails)) {
|
|
try {
|
|
$sheetLib->applyPermissions($newSheetId, [
|
|
'editors' => $editorEmails,
|
|
// 'viewers' => $viewerEmails,
|
|
]);
|
|
$this->myLogger->logme('error', "QCR Sheet: permissions applied | sheet_id={$newSheetId}, editors=" . count($editorEmails));
|
|
} catch (\Throwable $e) {
|
|
$this->myLogger->logme('error', "QCR Sheet: failed to apply permissions | sheet_id={$newSheetId}, error=" . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
// No protections applied for QCR as of now
|
|
|
|
// Save qcr_sheet_id to leads.misc and update status
|
|
$leadMisc['qcr_sheet_id'] = $newSheetId;
|
|
$this->leadsModel->update($leadId, [
|
|
'misc' => json_encode($leadMisc),
|
|
'status' => 'qcr_created',
|
|
]);
|
|
|
|
$sheetUrl = $sheetLib->sheetUrl($newSheetId);
|
|
|
|
$this->myLogger->logme('error', "QCR Sheet: created and stored | lead_id={$leadId}, sheet_id={$newSheetId}");
|
|
|
|
return $this->respond(
|
|
[
|
|
'status' => 'success',
|
|
'code' => 200,
|
|
'sheet_id' => $newSheetId,
|
|
'sheet_url' => $sheetUrl,
|
|
'message' => 'QCR sheet created successfully',
|
|
],
|
|
200
|
|
);
|
|
} catch (\Throwable $e) {
|
|
$errorDetails = [
|
|
'message' => $e->getMessage(),
|
|
'file' => $e->getFile(),
|
|
'line' => $e->getLine(),
|
|
];
|
|
|
|
$this->myLogger->logme('error', 'QCR Sheet: exception occurred | ' . json_encode($errorDetails));
|
|
|
|
return $this->respond(
|
|
['status' => 'error', 'code' => 500, 'message' => 'Failed to create QCR sheet'],
|
|
500
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Download RFQ/QCR Excel file from Google Sheet for Non-EB leads.
|
|
*
|
|
* Sheet selection based on recipient_type:
|
|
* - 'insurer' → rfq_sheet_id
|
|
* - 'client' → qcr_sheet_id
|
|
* - 'internal' → based on lead status: qcr_created/qcr_sent → qcr_sheet_id, else rfq_sheet_id
|
|
*
|
|
* @param string $recipientType insurer|client|internal
|
|
*/
|
|
protected function downloadFileFromGoogleSheet(array $lead_data, string $recipientType = 'insurer'): ?array
|
|
{
|
|
try {
|
|
$leadId = (int) ($lead_data['id'] ?? 0);
|
|
|
|
// Decode misc JSON
|
|
$misc = [];
|
|
if (! empty($lead_data['misc'])) {
|
|
$decoded = json_decode($lead_data['misc'], true);
|
|
if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
|
|
$misc = $decoded;
|
|
} else {
|
|
$this->myLogger->logme('error', "GSHEET DOWNLOAD: invalid JSON in leads.misc | lead_id={$leadId}, misc={$lead_data['misc']}");
|
|
}
|
|
}
|
|
|
|
// Pick sheet id based on recipient type
|
|
$sheetId = null;
|
|
$sheetType = '';
|
|
|
|
if ($recipientType === 'client') {
|
|
$sheetId = $misc['qcr_sheet_id'] ?? null;
|
|
$sheetType = 'qcr_sheet_id';
|
|
} elseif ($recipientType === 'internal') {
|
|
$leadStatus = $lead_data['status'] ?? '';
|
|
if (in_array($leadStatus, ['qcr_created', 'qcr_sent'])) {
|
|
$sheetId = $misc['qcr_sheet_id'] ?? null;
|
|
$sheetType = 'qcr_sheet_id';
|
|
} else {
|
|
$sheetId = $misc['rfq_sheet_id'] ?? null;
|
|
$sheetType = 'rfq_sheet_id';
|
|
}
|
|
} else {
|
|
// insurer or default
|
|
$sheetId = $misc['rfq_sheet_id'] ?? null;
|
|
$sheetType = 'rfq_sheet_id';
|
|
}
|
|
|
|
if (empty($sheetId)) {
|
|
$this->myLogger->logme('error', "GSHEET DOWNLOAD: {$sheetType} missing in leads.misc | lead_id={$leadId}, recipient_type={$recipientType}");
|
|
throw new \RuntimeException("{$sheetType} not found in leads. Please create the sheet first.");
|
|
}
|
|
|
|
$this->myLogger->logme('error', "GSHEET DOWNLOAD: starting download | lead_id={$leadId}, sheet_id={$sheetId}");
|
|
|
|
$sheetLib = new GoogleSheetLib();
|
|
$binary = $sheetLib->downloadExcel($sheetId);
|
|
|
|
if (! $binary) {
|
|
$this->myLogger->logme('error', "GSHEET DOWNLOAD: empty content from Google | lead_id={$leadId}, sheet_id={$sheetId}");
|
|
throw new \RuntimeException('Empty content from Google Sheet');
|
|
}
|
|
|
|
$filename = "lead_{$leadId}_" . date('Ymd_His') . '.xlsx';
|
|
$uploadDir = WRITEPATH . 'tmp/';
|
|
$uploadFilePath = $uploadDir . $filename;
|
|
|
|
if (! is_dir($uploadDir)) {
|
|
if (! mkdir($uploadDir, 0777, true) && ! is_dir($uploadDir)) {
|
|
$this->myLogger->logme('error', "GSHEET DOWNLOAD: failed to create tmp dir | path={$uploadDir}");
|
|
throw new \RuntimeException('Failed to create temporary directory for Excel download');
|
|
}
|
|
}
|
|
|
|
$bytes = file_put_contents($uploadFilePath, $binary);
|
|
if ($bytes === false) {
|
|
$this->myLogger->logme('error', "GSHEET DOWNLOAD: failed to write file | path={$uploadFilePath}");
|
|
throw new \RuntimeException('Failed to write downloaded Excel file');
|
|
}
|
|
|
|
$this->myLogger->logme('error', "GSHEET DOWNLOAD: saved file | lead_id={$leadId}, path={$uploadFilePath}");
|
|
|
|
return [
|
|
'filePath' => $uploadFilePath,
|
|
'fileName' => $filename,
|
|
];
|
|
} catch (\Throwable $e) {
|
|
$errorDetails = [
|
|
'message' => $e->getMessage(),
|
|
'file' => $e->getFile(),
|
|
'line' => $e->getLine(),
|
|
];
|
|
|
|
$this->myLogger->logme(
|
|
'error',
|
|
'GSHEET DOWNLOAD: exception occurred | ' . json_encode($errorDetails)
|
|
);
|
|
|
|
// Final fallback to existing Non-EB Excel generator to avoid breaking mail flow
|
|
// $leadId = (int) ($lead_data['id'] ?? 0);
|
|
// $file_info = $this->constructNonEbExcelToSaveTemp($leadId, 1, null);
|
|
|
|
// return [
|
|
// 'filePath' => $file_info['filePath'],
|
|
// 'fileName' => $file_info['fileName'],
|
|
// ];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a placement Google Sheet by copying the QCR sheet (Non-EB only).
|
|
*
|
|
* - Reads qcr_sheet_id from leads.misc
|
|
* - If placement_sheet_id already exists, reuses it
|
|
* - Copies the QCR sheet, replacing "QCR" with "Placement" in the filename
|
|
* - Applies same editor/viewer permissions as QCR
|
|
* - Saves placement_sheet_id to leads.misc
|
|
* - Downloads the placement sheet as Excel and returns file info
|
|
*/
|
|
protected function createAndDownloadPlacementSheet(array $lead_data): array
|
|
{
|
|
$leadId = (int) ($lead_data['id'] ?? 0);
|
|
$sheetLib = new GoogleSheetLib();
|
|
|
|
// Decode leads.misc
|
|
$leadMisc = [];
|
|
if (! empty($lead_data['misc'])) {
|
|
$decoded = json_decode($lead_data['misc'], true);
|
|
if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
|
|
$leadMisc = $decoded;
|
|
}
|
|
}
|
|
|
|
// If placement sheet already exists, download and return it
|
|
if (! empty($leadMisc['placement_sheet_id'])) {
|
|
$placementSheetId = (string) $leadMisc['placement_sheet_id'];
|
|
$this->myLogger->logme('error', "Placement Sheet: existing sheet found | lead_id={$leadId}, sheet_id={$placementSheetId}");
|
|
return $this->downloadPlacementExcel($sheetLib, $placementSheetId, $leadId);
|
|
}
|
|
|
|
// QCR sheet must exist to create placement
|
|
$qcrSheetId = $leadMisc['qcr_sheet_id'] ?? null;
|
|
if (empty($qcrSheetId)) {
|
|
$this->myLogger->logme('error', "Placement Sheet: qcr_sheet_id missing in leads.misc | lead_id={$leadId}");
|
|
throw new \RuntimeException('QCR sheet not found. Please create the QCR sheet first.');
|
|
}
|
|
|
|
// Get QCR filename and replace "QCR" with "Placement"
|
|
$qcrFileName = $sheetLib->getFileName($qcrSheetId);
|
|
$placementFileName = str_ireplace('QCR', 'Placement', $qcrFileName);
|
|
$this->myLogger->logme('error', "Placement Sheet: renaming | qcr_name={$qcrFileName}, placement_name={$placementFileName}");
|
|
|
|
// Load folder ID from config
|
|
$parentFolderId = null;
|
|
try {
|
|
$rfqConfig = config('RfqConfig');
|
|
if ($rfqConfig) {
|
|
$parentFolderId = $rfqConfig->rfqParentFolderId ?? null;
|
|
}
|
|
} catch (\Throwable $e) {
|
|
$this->myLogger->logme('error', 'Placement Sheet: error loading RfqConfig | ' . $e->getMessage());
|
|
}
|
|
|
|
if (! $parentFolderId) {
|
|
throw new \RuntimeException('Google config not correct, contact administrator');
|
|
}
|
|
|
|
// Copy QCR sheet as placement
|
|
$placementSheetId = $sheetLib->copyTemplate($qcrSheetId, $placementFileName, $parentFolderId);
|
|
$this->myLogger->logme('error', "Placement Sheet: copied from QCR | lead_id={$leadId}, qcr_sheet_id={$qcrSheetId}, placement_sheet_id={$placementSheetId}");
|
|
|
|
// Apply same permissions as QCR (editors: sales team, viewers: rfq_qcr_viewers)
|
|
// $salesTeam = $this->userModel
|
|
// ->select('user_profiles.email')
|
|
// ->join('user_teams', 'user_profiles.id = user_teams.user_id')
|
|
// ->where('user_teams.team_id', 5)
|
|
// ->where('user_teams.is_active', 1)
|
|
// ->where('user_profiles.is_active', 1)
|
|
// ->findAll();
|
|
// $editorEmails = array_values(array_filter(array_unique(array_column($salesTeam, 'email'))));
|
|
|
|
$editorEmails = [];
|
|
if (! empty($lead_data['rfq_qcr_viewers'])) {
|
|
$decoded = json_decode($lead_data['rfq_qcr_viewers'], true);
|
|
if (is_array($decoded)) {
|
|
$editorEmails = array_values(array_filter(array_unique($decoded)));
|
|
}
|
|
}
|
|
|
|
if (! empty($editorEmails) ) {
|
|
try {
|
|
$sheetLib->applyPermissions($placementSheetId, [
|
|
'editors' => $editorEmails,
|
|
// 'viewers' => $viewerEmails,
|
|
]);
|
|
$this->myLogger->logme('error', "Placement Sheet: permissions applied | sheet_id={$placementSheetId}, editors=" . count($editorEmails));
|
|
} catch (\Throwable $e) {
|
|
$this->myLogger->logme('error', "Placement Sheet: failed to apply permissions | sheet_id={$placementSheetId}, error=" . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
// Save placement_sheet_id to leads.misc
|
|
$leadMisc['placement_sheet_id'] = $placementSheetId;
|
|
$this->leadsModel->update($leadId, [
|
|
'misc' => json_encode($leadMisc),
|
|
]);
|
|
$this->myLogger->logme('error', "Placement Sheet: saved to leads.misc | lead_id={$leadId}, placement_sheet_id={$placementSheetId}");
|
|
|
|
return $this->downloadPlacementExcel($sheetLib, $placementSheetId, $leadId);
|
|
}
|
|
|
|
/**
|
|
* Download a placement Google Sheet as Excel to tmp directory.
|
|
*/
|
|
private function downloadPlacementExcel(GoogleSheetLib $sheetLib, string $sheetId, int $leadId): array
|
|
{
|
|
$binary = $sheetLib->downloadExcel($sheetId);
|
|
|
|
if (! $binary) {
|
|
$this->myLogger->logme('error', "Placement Sheet: empty content from Google | lead_id={$leadId}, sheet_id={$sheetId}");
|
|
throw new \RuntimeException('Empty content from Google Sheet for placement');
|
|
}
|
|
|
|
$filename = "lead_{$leadId}_placement_" . date('Ymd_His') . '.xlsx';
|
|
$uploadDir = WRITEPATH . 'tmp/';
|
|
$uploadFilePath = $uploadDir . $filename;
|
|
|
|
if (! is_dir($uploadDir)) {
|
|
if (! mkdir($uploadDir, 0777, true) && ! is_dir($uploadDir)) {
|
|
throw new \RuntimeException('Failed to create temporary directory');
|
|
}
|
|
}
|
|
|
|
$bytes = file_put_contents($uploadFilePath, $binary);
|
|
if ($bytes === false) {
|
|
throw new \RuntimeException('Failed to write placement Excel file');
|
|
}
|
|
|
|
$this->myLogger->logme('error', "Placement Sheet: downloaded | lead_id={$leadId}, path={$uploadFilePath}");
|
|
|
|
return [
|
|
'filePath' => $uploadFilePath,
|
|
'fileName' => $filename,
|
|
];
|
|
}
|
|
|
|
public function generateViewPageHtml($policy_type_id, $data = [])
|
|
{
|
|
$data['insurer'] = $this->insurerBranchModel->getInsurerBranchesWithInsurerNames();
|
|
$data['tpa'] = $this->tpaBranchModel->getTpaBranchesWithTpaNames();
|
|
$data['lastFiveYears'] = $data['lastFiveYears'] ?? $this->getLastFiveFinancialYears();
|
|
$data['gpaClaimType'] = $data['gpaClaimType'] ?? $this->claim_type_for_gpa;
|
|
$data['causeOfDeath'] = $data['causeOfDeath'] ?? $this->cause_of_death;
|
|
|
|
$viewMap = [
|
|
1 => 'rfq/gpa',
|
|
6 => 'rfq/gpa',
|
|
7 => 'rfq/gpa',
|
|
2 => 'rfq/gmc',
|
|
3 => 'rfq/gmc',
|
|
4 => 'rfq/gmc',
|
|
5 => 'rfq/gmc',
|
|
17 => 'rfq/burglary',
|
|
22 => 'rfq/car',
|
|
23 => 'rfq/cpm',
|
|
24 => 'rfq/cyber_crime',
|
|
25 => 'rfq/do',
|
|
27 => 'rfq/eo',
|
|
49 => 'rfq/money',
|
|
19 => 'rfq/cgl',
|
|
59 => 'rfq/sfsp',
|
|
63 => 'rfq/wc',
|
|
15 => 'rfq/blu',
|
|
16 => 'rfq/bsu',
|
|
44 => 'rfq/marine',
|
|
45 => 'rfq/marine',
|
|
46 => 'rfq/marine',
|
|
47 => 'rfq/marine',
|
|
50 => 'rfq/office',
|
|
];
|
|
|
|
return isset($viewMap[$policy_type_id]) ? view($viewMap[$policy_type_id], $data) : "";
|
|
}
|
|
|
|
// ------------------- RFQ NON EB EXCEL EXPORT FUNCTION ---------------------------------------------------------------------------------------
|
|
|
|
public function constructNonEbExcelToSaveTemp($lead_id, $type, $propsal_and_insurer = null)
|
|
{
|
|
$rfq_data = $this->RFQModel->getRFQTableDataWithLeadIDAndType($lead_id, $type);
|
|
$claim_history = $rfq_data['claim_history'];
|
|
// dd($claim_history);
|
|
$lead_data = json_decode($rfq_data['custom_fields'], true) ?? [];
|
|
$lead_data['claim_history'] = $claim_history;
|
|
// dd($lead_data);
|
|
if (! is_array($lead_data)) {
|
|
$lead_data = [];
|
|
}
|
|
|
|
if (isset($lead_data['pincode']) && isset($lead_data['address'])) {
|
|
// Reorder keys: address first, then pincode, then the rest
|
|
$reordered = ['address' => $lead_data['address'], 'pincode' => $lead_data['pincode']];
|
|
|
|
// Remove existing keys
|
|
unset($lead_data['address'], $lead_data['pincode']);
|
|
|
|
// Merge reordered with the rest
|
|
$lead_data = $reordered + $lead_data;
|
|
}
|
|
$lead_data = array_merge(['Insured' => $rfq_data['client_name']], $lead_data);
|
|
|
|
$policy_registration_data = [];
|
|
if (isset($rfq_data['registration_json']) && ! empty($rfq_data['registration_json'])) {
|
|
$policy_registration_data = json_decode($rfq_data['registration_json'], true);
|
|
}
|
|
|
|
$jsonData = json_decode($rfq_data['json'], true);
|
|
$proposalData = end($jsonData);
|
|
array_pop($jsonData);
|
|
$length = 0;
|
|
// dd($jsonData[0]['table_data']['headers']);
|
|
foreach ($jsonData as $key => $data) {
|
|
if ($type == 2) {
|
|
|
|
$data = $this->convertNonEbJsonForQCR($data, $type, $proposalData, $key);
|
|
|
|
// Kint::dump($data, 'Second');
|
|
|
|
if ($propsal_and_insurer !== null) {
|
|
list($proposal_key, $insurer_key) = explode('-', $propsal_and_insurer, 2);
|
|
$data = $this->transformNonEbProposelData($data, $proposal_key, $insurer_key, $key);
|
|
}
|
|
unset($data['proposalData']);
|
|
} else if ($type == 1) {
|
|
$data = $this->convertNonEbJsonForQCR($data, $type, $proposalData, $key);
|
|
unset($data['proposalData']);
|
|
}
|
|
}
|
|
// dd($data);
|
|
foreach ($data['table_data']['headers'] as $header) {
|
|
if ($header['parentHeader'] != "Action") {
|
|
foreach ($header['subHeaders'] as $subHeader) {
|
|
// Kint::dump($header['parentHeader']);
|
|
// Kint::dump($subHeader);
|
|
|
|
$length++;
|
|
}
|
|
}
|
|
}
|
|
// dd($length);
|
|
$columnLetterForTitle = Coordinate::stringFromColumnIndex($length - 1);
|
|
$columnLetterForImage = Coordinate::stringFromColumnIndex($length);
|
|
|
|
// dd($columnLetter);
|
|
$sheetName = 'Worksheet';
|
|
if ($type == 2) {
|
|
$sheetName = 'QCR';
|
|
if ($propsal_and_insurer !== null) {
|
|
$sheetName = 'Placement';
|
|
}
|
|
} else if ($type == 1) {
|
|
$sheetName = 'RFQ';
|
|
}
|
|
|
|
$spreadsheet = new Spreadsheet();
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
$sheet->setTitle($sheetName);
|
|
|
|
// Start with lead_data at the top
|
|
$rowNumber = 1;
|
|
|
|
$title = "Nhance India Insurance Broking Pvt Ltd";
|
|
$mergeRange1 = "A{$rowNumber}:{$columnLetterForTitle}{$rowNumber}";
|
|
$sheet->mergeCells($mergeRange1);
|
|
$sheet->setCellValue("A{$rowNumber}", $title);
|
|
$sheet->getStyle("A{$rowNumber}")->applyFromArray([
|
|
'font' => [
|
|
'bold' => true,
|
|
'size' => 20,
|
|
],
|
|
'alignment' => [
|
|
'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
|
|
'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
|
|
],
|
|
]);
|
|
|
|
// Calculate title width
|
|
$maxWidthA = mb_strlen($title);
|
|
|
|
// dd($columnLetterForImage);
|
|
// Set column width to fit the image properly
|
|
$sheet->getColumnDimension($columnLetterForImage)->setWidth(40); // Adjust as needed
|
|
$sheet->getRowDimension($rowNumber)->setRowHeight(40); // Adjust as needed
|
|
|
|
$drawing = new Drawing();
|
|
$path = ROOTPATH . "public/assets/images/Nhance-Logo-Final.png"; // Use FCPATH for server path
|
|
$drawing->setPath($path);
|
|
$drawing->setCoordinates("{$columnLetterForImage}{$rowNumber}"); // Set position in column C
|
|
$drawing->setHeight(35); // Adjust image height
|
|
|
|
// Apply center alignment to the cell
|
|
$sheet->getStyle("{$columnLetterForImage}{$rowNumber}")->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
|
$sheet->getStyle("{$columnLetterForImage}{$rowNumber}")->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER);
|
|
|
|
$rowNumber++;
|
|
|
|
// Initialize max width tracking variables
|
|
$maxWidthB = 0;
|
|
|
|
//Lead Data
|
|
foreach ($lead_data as $key => $value) {
|
|
|
|
// if ($key == 'risk_location') {
|
|
// $key == 'risk_details';
|
|
// }
|
|
// Kint::dump($key);
|
|
// Kint::dump($value);
|
|
$formattedKey = ucwords(str_replace('_', ' ', $key));
|
|
$formattedKey = $formattedKey == "Risk Location" ? "Risk Details" : $formattedKey;
|
|
$formattedKey = $formattedKey == "Address" ? "Communication Address" : $formattedKey;
|
|
$formattedValue = ucwords(str_replace("_", " ", $value));
|
|
|
|
if ($key == "claim_history") {
|
|
|
|
$formattedValue = $value == "1" ? "Yes" : "No";
|
|
$formattedKey = "Claim Experience";
|
|
|
|
}
|
|
// Kint::dump($formattedValue);
|
|
|
|
// Merge A:B for key
|
|
$mergeRangeKey = "A{$rowNumber}:{$columnLetterForTitle}{$rowNumber}";
|
|
$sheet->mergeCells($mergeRangeKey);
|
|
|
|
// Set values in merged cells
|
|
$sheet->setCellValue("A{$rowNumber}", $formattedKey);
|
|
$sheet->setCellValue("{$columnLetterForImage}{$rowNumber}", $formattedValue);
|
|
|
|
// Apply styles for alignment and bold text in A:B
|
|
$sheet->getStyle($mergeRangeKey)->applyFromArray([
|
|
'font' => ['bold' => true],
|
|
'alignment' => [
|
|
'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
|
|
'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
|
|
],
|
|
]);
|
|
|
|
// Apply bold style to C column if the key is "Insured"
|
|
// if ($key === "Insured") {
|
|
// $sheet->getStyle("C{$rowNumber}")->applyFromArray([
|
|
// 'font' => ['bold' => true],
|
|
// ]);
|
|
// }
|
|
|
|
// Track max width needed for columns
|
|
$maxWidthA = max($maxWidthA, mb_strlen($formattedKey)); // Consider title and keys
|
|
$maxWidthB = max($maxWidthB, mb_strlen((string) $value));
|
|
// if (!empty($policy_registration_data)) {
|
|
// dd($policy_registration_data);
|
|
|
|
// }
|
|
|
|
$rowNumber++;
|
|
}
|
|
// die();
|
|
|
|
// Set column width based on max content length (adjusted for padding)
|
|
$sheet->getColumnDimension('A')->setWidth($maxWidthA * 1.2);
|
|
// $sheet->getColumnDimension('B')->setWidth($maxWidthA * 1.2);
|
|
// $sheet->getColumnDimension('C')->setWidth($maxWidthB * 1.2);
|
|
|
|
// $rowNumber += 1;
|
|
//Policy Registration
|
|
if (! empty($policy_registration_data)) {
|
|
foreach ($policy_registration_data as $key => $value) {
|
|
// kint::dump($value);
|
|
$startRow = $rowNumber; // Track where the block starts
|
|
|
|
// Title Row
|
|
$titleMergeRangeKey = "A{$rowNumber}:{$columnLetterForImage}{$rowNumber}";
|
|
$sheet->mergeCells($titleMergeRangeKey);
|
|
$sheet->setCellValue("A{$rowNumber}", ucfirst($key) . " Policy Details");
|
|
|
|
// Title Style
|
|
$sheet->getStyle($titleMergeRangeKey)->applyFromArray([
|
|
'font' => ['bold' => true],
|
|
'alignment' => [
|
|
'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
|
|
'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
|
|
],
|
|
'fill' => [
|
|
'fillType' => Fill::FILL_SOLID,
|
|
'startColor' => ['rgb' => 'ADD8E6'],
|
|
],
|
|
]);
|
|
|
|
$rowNumber++; // Move to next row
|
|
|
|
// Policy Type
|
|
if (isset($value['policyType'])) {
|
|
$sheet->mergeCells("A{$rowNumber}:{$columnLetterForTitle}{$rowNumber}");
|
|
$sheet->setCellValue("A{$rowNumber}", "Policy Type");
|
|
$sheet->setCellValue("{$columnLetterForImage}{$rowNumber}", $value['policyType']);
|
|
|
|
$sheet->getStyle("A{$rowNumber}:C{$rowNumber}")->applyFromArray([
|
|
'font' => ['bold' => true],
|
|
'alignment' => [
|
|
'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
|
|
'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
|
|
],
|
|
]);
|
|
|
|
$rowNumber++;
|
|
} else {
|
|
$sheet->mergeCells("A{$rowNumber}:{$columnLetterForTitle}{$rowNumber}");
|
|
$sheet->setCellValue("A{$rowNumber}", "Policy Type");
|
|
$sheet->setCellValue("{$columnLetterForImage}{$rowNumber}", ucfirst($key) . " Policy");
|
|
|
|
$sheet->getStyle("A{$rowNumber}:C{$rowNumber}")->applyFromArray([
|
|
'font' => ['bold' => true],
|
|
'alignment' => [
|
|
'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
|
|
'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
|
|
],
|
|
]);
|
|
|
|
$rowNumber++;
|
|
}
|
|
|
|
// Type of Business & Nature of Business
|
|
if (isset($value['productSelection']) && ! empty($value['productSelection'])) {
|
|
// Type of Business
|
|
$sheet->mergeCells("A{$rowNumber}:{$columnLetterForTitle}{$rowNumber}");
|
|
$sheet->setCellValue("A{$rowNumber}", "Type of Business");
|
|
$sheet->setCellValue("{$columnLetterForImage}{$rowNumber}", $this->buisnessType[$value['productSelection']['type_of_buisness']] ?? '');
|
|
|
|
$sheet->getStyle("A{$rowNumber}")->applyFromArray([
|
|
'font' => ['bold' => true],
|
|
'alignment' => [
|
|
'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
|
|
'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
|
|
],
|
|
]);
|
|
|
|
$rowNumber++;
|
|
|
|
// Nature of Business
|
|
$sheet->mergeCells("A{$rowNumber}:{$columnLetterForTitle}{$rowNumber}");
|
|
$sheet->setCellValue("A{$rowNumber}", "Nature of Business");
|
|
$sheet->setCellValue("{$columnLetterForImage}{$rowNumber}", $value['productSelection']['buisness_nature'] ?? '');
|
|
|
|
$sheet->getStyle("A{$rowNumber}")->applyFromArray([
|
|
'font' => ['bold' => true],
|
|
'alignment' => [
|
|
'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
|
|
'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
|
|
],
|
|
]);
|
|
|
|
$rowNumber++;
|
|
}
|
|
|
|
if (isset($value['policyDetails']) && ! empty($value['policyDetails'])) {
|
|
// Type of Business
|
|
$sheet->mergeCells("A{$rowNumber}:{$columnLetterForTitle}{$rowNumber}");
|
|
$sheet->setCellValue("A{$rowNumber}", "Terrorism");
|
|
$sheet->setCellValue("{$columnLetterForImage}{$rowNumber}", ucfirst($value['policyDetails']['terrorism'] ?? 'No'));
|
|
|
|
$sheet->getStyle("A{$rowNumber}")->applyFromArray([
|
|
'font' => ['bold' => true],
|
|
'alignment' => [
|
|
'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
|
|
'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
|
|
],
|
|
]);
|
|
|
|
$rowNumber++;
|
|
}
|
|
if (! empty($value['locations'])) {
|
|
|
|
foreach ($value['locations'] as $index => $location) {
|
|
// Merge title cell
|
|
$sheet->mergeCells("A{$rowNumber}:{$columnLetterForTitle}{$rowNumber}");
|
|
$sheet->setCellValue("A{$rowNumber}", "Risk " . ($location['select_location'] ?? 'Unknown'));
|
|
|
|
// Clean and safe address string
|
|
$address1 = ucfirst($location['policyRisk']['address1'] ?? '');
|
|
$address2 = ucfirst($location['policyRisk']['address2'] ?? '');
|
|
$pinCode = $location['policyRisk']['pin_code'] ?? 'No';
|
|
|
|
$fullAddress = "{$address1}, {$address2}, {$pinCode}";
|
|
$sheet->setCellValue("{$columnLetterForImage}{$rowNumber}", $fullAddress);
|
|
|
|
// Style the title cell
|
|
$sheet->getStyle("A{$rowNumber}")->applyFromArray([
|
|
'font' => ['bold' => true],
|
|
'alignment' => [
|
|
'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
|
|
'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
|
|
],
|
|
]);
|
|
|
|
$rowNumber++;
|
|
}
|
|
}
|
|
|
|
$endRow = $rowNumber; // Block ends at previous row
|
|
|
|
// Apply border to the whole block
|
|
$sheet->getStyle("A{$startRow}:{$columnLetterForImage}{$endRow}")->applyFromArray([
|
|
'borders' => [
|
|
'allBorders' => [
|
|
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
|
|
'color' => ['argb' => '000000'],
|
|
],
|
|
],
|
|
]);
|
|
|
|
// $rowNumber += 1; // Add space before the next block
|
|
}
|
|
$rowNumber--;
|
|
// die();
|
|
}
|
|
|
|
//Table Data
|
|
foreach ($jsonData as $key => $data) {
|
|
|
|
// Kint::dump($data, 'First');
|
|
|
|
if ($type == 2) {
|
|
|
|
$data = $this->convertNonEbJsonForQCR($data, $type, $proposalData, $key);
|
|
|
|
// Kint::dump($data, 'Second');
|
|
|
|
if ($propsal_and_insurer !== null) {
|
|
list($proposal_key, $insurer_key) = explode('-', $propsal_and_insurer, 2);
|
|
$data = $this->transformNonEbProposelData($data, $proposal_key, $insurer_key, $key);
|
|
}
|
|
unset($data['proposalData']);
|
|
} else if ($type == 1) {
|
|
$data = $this->convertNonEbJsonForQCR($data, $type, $proposalData, $key);
|
|
unset($data['proposalData']);
|
|
}
|
|
|
|
// dd($data);
|
|
// Add headers and subheaders
|
|
$headers = $data['table_data']['headers'];
|
|
// dd($headers);
|
|
|
|
$rowNumber = $rowNumber + 1;
|
|
|
|
$subHeaderRow = $rowNumber + 1;
|
|
$columnLetter = 'A';
|
|
|
|
foreach ($headers as $header) {
|
|
|
|
if (in_array($header['parentHeader'], ['Action'])) {
|
|
continue;
|
|
}
|
|
|
|
$sheet->getColumnDimension($columnLetter)->setWidth(60);
|
|
$sheet->getColumnDimension('C')->setWidth(35);
|
|
|
|
if ($header['parentHeader'] == 'Policy') {
|
|
// $header['parentHeader'] = 'S.No.';
|
|
$sheet->getColumnDimension('A')->setWidth(10);
|
|
}
|
|
|
|
if ($header['parentHeader'] === 'Particulars') {
|
|
$sheet->getColumnDimension('B')->setWidth(60);
|
|
}
|
|
|
|
if (strpos($header['parentHeader'], 'Proposal') === 0) {
|
|
$sheet->getColumnDimension('C')->setWidth(60);
|
|
$sheet->getColumnDimension('D')->setWidth(35);
|
|
}
|
|
|
|
$startColumn = $columnLetter; // Start of the current header range
|
|
$subHeaderCount = count($header['subHeaders']); // Number of subheaders for this parent header
|
|
// Kint::dump($subHeaderCount);
|
|
// Set parent header value
|
|
$sheet->setCellValue("{$startColumn}{$rowNumber}", $header['parentHeader']);
|
|
$sheet->getStyle("{$startColumn}{$rowNumber}")->applyFromArray([
|
|
'font' => ['bold' => true],
|
|
'alignment' => [
|
|
'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
|
|
'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
|
|
],
|
|
'fill' => [
|
|
'fillType' => Fill::FILL_SOLID,
|
|
'startColor' => ['rgb' => 'ADD8E6'],
|
|
],
|
|
]);
|
|
|
|
// Merge header cells if it spans multiple subheaders
|
|
if ($subHeaderCount > 1) {
|
|
$endColumn = Coordinate::stringFromColumnIndex(Coordinate::columnIndexFromString($startColumn) + $subHeaderCount - 1);
|
|
$sheet->mergeCells("{$startColumn}{$rowNumber}:{$endColumn}{$rowNumber}");
|
|
} else {
|
|
$endColumn = $startColumn; // No merge needed if only one subheader
|
|
}
|
|
|
|
// Kint::dump($header);
|
|
// Add subheaders
|
|
foreach ($header['subHeaders'] as $subHeader) {
|
|
$sheet->setCellValue("{$columnLetter}{$subHeaderRow}", $subHeader);
|
|
|
|
if ($columnLetter != "A" && $columnLetter != "B" && $columnLetter != "C" && $columnLetter != "D") {
|
|
$sheet->getColumnDimension($columnLetter)->setWidth(35);
|
|
} else {
|
|
$sheet->getColumnDimension('A')->setWidth(10);
|
|
}
|
|
|
|
$sheet->getStyle("{$columnLetter}{$subHeaderRow}")->applyFromArray([
|
|
'font' => ['bold' => true],
|
|
'alignment' => [
|
|
'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
|
|
'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
|
|
],
|
|
]);
|
|
$columnLetter++; // Move to the next column for subheaders
|
|
}
|
|
}
|
|
|
|
// For the subheader row, merge B and C and set the value
|
|
$sheet->setCellValue("B{$subHeaderRow}", "Sum Insured");
|
|
$sheet->mergeCells("B{$subHeaderRow}:C{$subHeaderRow}");
|
|
$sheet->getStyle("B{$subHeaderRow}:C{$subHeaderRow}")->applyFromArray([
|
|
'font' => ['bold' => true],
|
|
'alignment' => [
|
|
'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
|
|
'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
|
|
],
|
|
]);
|
|
|
|
// Apply border to the header range
|
|
$prevColumn4 = $this->getPreviousColumn($columnLetter);
|
|
$headerRange = "A{$rowNumber}:" . "{$prevColumn4}" . "{$subHeaderRow}";
|
|
$sheet->getStyle($headerRange)->applyFromArray([
|
|
'borders' => [
|
|
'allBorders' => [
|
|
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
|
|
'color' => ['argb' => 'FF000000'], // Black color
|
|
],
|
|
],
|
|
]);
|
|
|
|
// Increase row height for headers and subheaders
|
|
$sheet->getRowDimension($rowNumber)->setRowHeight(25); // Header row height
|
|
$sheet->getRowDimension($subHeaderRow)->setRowHeight(20); // Subheader row height
|
|
|
|
// $rowNumber = $subHeaderRow + 2;
|
|
$rowNumber = $subHeaderRow + 1;
|
|
|
|
$column_data = $data['table_data']['data'];
|
|
// dd($column_data);
|
|
$serial_no = 1;
|
|
$maxColumnWidths = [];
|
|
$RowSpanEnable = false;
|
|
|
|
// Add table data rows
|
|
foreach ($column_data as $dataRow) {
|
|
|
|
$columnLetter = 'A';
|
|
$hasPolicy = in_array('Policy', array_column($dataRow['data'], 'parentth'));
|
|
// Kint::dump($hasPolicy);
|
|
|
|
foreach ($dataRow['data'] as $cellData) {
|
|
|
|
if (in_array($cellData['parentth'], ['Action'])) {
|
|
continue;
|
|
}
|
|
|
|
if ($cellData['parentth'] == 'SNO') {
|
|
$sheet->setCellValue("{$columnLetter}{$rowNumber}", $serial_no);
|
|
} else if ($cellData['parentth'] == 'Policy') {
|
|
$mergeStart = $rowNumber; // Start row for merging
|
|
$mergeEnd = $rowNumber + ($cellData['rowspan'] - 1); // End row for merging
|
|
|
|
$sheet->setCellValue("{$columnLetter}{$mergeStart}", $dataRow['SNO']);
|
|
$sheet->mergeCells("{$columnLetter}{$mergeStart}:{$columnLetter}{$mergeEnd}");
|
|
$sheet->getStyle("{$columnLetter}{$mergeStart}:{$columnLetter}{$mergeEnd}")
|
|
->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER);
|
|
} else {
|
|
if (! $hasPolicy && $key == 0) {
|
|
$RowSpanEnable = true;
|
|
$columnLetter++;
|
|
$sheet->setCellValue("{$columnLetter}{$rowNumber}", $cellData['display_content']);
|
|
} else {
|
|
$sheet->setCellValue("{$columnLetter}{$rowNumber}", $cellData['display_content']);
|
|
}
|
|
}
|
|
|
|
if (! ($key === 0 && ! $hasPolicy)) {
|
|
$columnLetter++;
|
|
}
|
|
}
|
|
$rowNumber++;
|
|
$serial_no++;
|
|
}
|
|
|
|
if ($key == 0 && $RowSpanEnable == true) {
|
|
$columnLetter++;
|
|
}
|
|
|
|
// dd($columnLetter);
|
|
$prevColumn5 = $this->getPreviousColumn($columnLetter);
|
|
$dataRange = "A" . ($subHeaderRow + 1) . ":" . "{$prevColumn5}" . ($rowNumber - 1);
|
|
$sheet->getStyle($dataRange)->applyFromArray([
|
|
'borders' => [
|
|
'allBorders' => [
|
|
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
|
|
'color' => ['argb' => 'FF000000'], // Black color
|
|
],
|
|
],
|
|
]);
|
|
|
|
// Auto-size columns
|
|
// foreach ($sheet->getColumnIterator() as $column) {
|
|
// $sheet->getColumnDimension($column->getColumnIndex())->setAutoSize(true);
|
|
// }
|
|
|
|
$dataRange = $sheet->calculateWorksheetDimension();
|
|
|
|
$sheet->getStyle($dataRange)->getAlignment()
|
|
->setHorizontal(Alignment::HORIZONTAL_CENTER)
|
|
->setVertical(Alignment::VERTICAL_CENTER)
|
|
->setWrapText(true);
|
|
|
|
$sheet->getStyle('A1')->applyFromArray([
|
|
'alignment' => [
|
|
'wrapText' => false, // Disables text wrapping for A1
|
|
],
|
|
]);
|
|
|
|
// Apply border to the entire sheet
|
|
preg_match('/([A-Z]+)(\d+):([A-Z]+)(\d+)/', $dataRange, $matches);
|
|
|
|
if ($matches) {
|
|
$startColumn = $matches[1]; // A
|
|
$startRow = $matches[2]; // 1
|
|
$endColumn = $matches[3]; // G
|
|
$endRow = $matches[4]; // 75
|
|
|
|
// Convert column letter to index, reduce by 1, and convert back
|
|
$endColumnIndex = Coordinate::columnIndexFromString($endColumn) - 1;
|
|
$newEndColumn = Coordinate::stringFromColumnIndex($endColumnIndex);
|
|
|
|
// Generate the new range (e.g., "A1:F75" instead of "A1:G75")
|
|
$newDataRange = "{$startColumn}{$startRow}:{$newEndColumn}{$endRow}";
|
|
// $sheet->getStyle($newDataRange)->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);
|
|
}
|
|
|
|
$lastRow = count($lead_data) + 1;
|
|
$leadRange = "A1:{$columnLetterForImage}{$lastRow}";
|
|
|
|
$sheet->getStyle($leadRange)->applyFromArray([
|
|
'borders' => [
|
|
'allBorders' => [
|
|
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
|
|
'color' => ['argb' => 'FF000000'], // Black color
|
|
],
|
|
],
|
|
]);
|
|
}
|
|
|
|
$columnWidth = $sheet->getColumnDimension("C")->getWidth(); // e.g., 20
|
|
$cellPixelWidth = $columnWidth * 7; // Approximate conversion (1 unit ≈ 7 pixels)
|
|
$imagePixelWidth = 250; // Approximate width of your image (in pixels)
|
|
|
|
$offsetX = max(0, ($cellPixelWidth - $imagePixelWidth) / 2);
|
|
$offsetX = $offsetX + 97;
|
|
if ($length >= 4) {
|
|
$offsetX = 35;
|
|
} else if ($length == 3) {
|
|
$offsetX = 140;
|
|
}
|
|
|
|
// dd($offsetX, $cellPixelWidth, $imagePixelWidth);
|
|
$drawing->setOffsetX($offsetX); // Dynamically center
|
|
$drawing->setOffsetY(10); // Dynamically center
|
|
|
|
$drawing->setWorksheet($sheet);
|
|
|
|
$sheet->getStyle('C1')->getAlignment()
|
|
->setHorizontal(Alignment::HORIZONTAL_CENTER)
|
|
->setVertical(Alignment::VERTICAL_CENTER);
|
|
|
|
if (! empty($rfq_data['fin_years_claims']) && $claim_history == 1) {
|
|
|
|
$claim_details = $this->sanitizeClaimDetailsForExport(
|
|
json_decode($rfq_data['fin_years_claims'], true) ?? []
|
|
);
|
|
|
|
if (! empty($claim_details['finyear'])) {
|
|
|
|
// Get headers dynamically
|
|
$headers = array_map(function ($key) {
|
|
return ucwords(str_replace('_', ' ', $key));
|
|
}, array_keys($claim_details['finyear'][0]));
|
|
|
|
$newSheet = new Worksheet($spreadsheet, 'Claims Experience');
|
|
$spreadsheet->addSheet($newSheet);
|
|
$spreadsheet->setActiveSheetIndexByName('Claims Experience');
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
|
|
// Set headers
|
|
$sheet->fromArray($headers, null, 'A1');
|
|
|
|
// Apply background color and bold style to headers
|
|
$headerCellRange = 'A1:' . chr(64 + count($headers)) . '1'; // e.g., A1:G1
|
|
|
|
$sheet->getStyle($headerCellRange)->getFont()->setBold(true);
|
|
$sheet->getStyle($headerCellRange)->getFill()->setFillType(Fill::FILL_SOLID)->getStartColor()->setRGB('ADD8E6');
|
|
|
|
// Add border to header
|
|
$sheet->getStyle($headerCellRange)->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);
|
|
|
|
// Fill data and apply borders
|
|
$row = 2;
|
|
foreach ($claim_details['finyear'] as $record) {
|
|
$col = 'A';
|
|
foreach ($record as $value) {
|
|
$sheet->setCellValue($col . $row, $value);
|
|
$col++;
|
|
}
|
|
|
|
// Apply border to each data row
|
|
$sheet->getStyle('A' . $row . ':' . chr(64 + count($headers)) . $row)
|
|
->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);
|
|
|
|
$row++;
|
|
}
|
|
// Auto-size all columns based on header count
|
|
for ($i = 0; $i < count($headers); $i++) {
|
|
$colLetter = chr(65 + $i); // 'A', 'B', etc.
|
|
$sheet->getColumnDimension($colLetter)->setAutoSize(true);
|
|
}
|
|
|
|
// Enable wrap text for all cells
|
|
$maxColLetter = chr(64 + count($headers)); // Last column letter
|
|
$sheet->getStyle("A2:{$maxColLetter}{$row}")->getAlignment()->setWrapText(true);
|
|
|
|
// Optional: center vertically for neatness
|
|
$sheet->getStyle("A2:{$maxColLetter}{$row}")->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER);
|
|
|
|
// Optional: Make row height auto (helps when wrap text is on)
|
|
for ($i = 2; $i < $row; $i++) {
|
|
$sheet->getRowDimension($i)->setRowHeight(-1);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// dd($rowNumber);
|
|
// Set filename
|
|
$string = ($type == 2) ? 'QCR' : 'RFQ';
|
|
$filename = "{$string}_{$rfq_data['client_short_name']}_{$rfq_data['policy_type']}_" . date('YmdHis') . '.xlsx';
|
|
|
|
// Save to temporary location
|
|
$uploadFilePath = WRITEPATH . 'tmp/' . $filename;
|
|
$writer = new Xlsx($spreadsheet);
|
|
$writer->save($uploadFilePath);
|
|
|
|
return [
|
|
'filePath' => $uploadFilePath,
|
|
'fileName' => $filename,
|
|
];
|
|
}
|
|
|
|
public function convertNonEbJsonForQCR($jsonArr, $type, $proposeldata, $indexOfTheTable)
|
|
{
|
|
|
|
$first_json = $jsonArr;
|
|
$first_json = array_merge($first_json, $proposeldata);
|
|
|
|
if ($type == 2) {
|
|
|
|
// Column-wise Check: Remove headers and relevant data if qcr == 0
|
|
foreach ($first_json['proposal_data']['over_all_column_data'] as $proposalKey => $proposalData) {
|
|
|
|
if ((isset($proposalData['qcr']) && isset($proposalData['stc'])) && ($proposalData['qcr'] == 0 || $proposalData['qcr'] === false) || ($proposalData['stc'] == 0 || $proposalData['stc'] === false)) {
|
|
|
|
// Remove matching parentHeader in headers
|
|
foreach ($first_json['table_data']['headers'] as $index => $header) {
|
|
if ($header['parentHeader'] === $proposalKey) {
|
|
unset($first_json['table_data']['headers'][$index]);
|
|
}
|
|
}
|
|
|
|
// Remove data entries with matching parentth
|
|
foreach ($first_json['table_data']['data'] as &$item) {
|
|
$item['data'] = array_values(array_filter($item['data'], function ($entry) use ($proposalKey) {
|
|
return $entry['parentth'] !== $proposalKey;
|
|
}));
|
|
}
|
|
|
|
// Remove proposalKey from over_all_column_data
|
|
unset($first_json['proposal_data']['over_all_column_data'][$proposalKey]);
|
|
|
|
if ($type == 2) {
|
|
// Remove proposalKey from premium_data
|
|
unset($first_json['premium_data']['data'][$proposalKey]);
|
|
}
|
|
}
|
|
|
|
// Insurer Check: Remove subHeaders and relevant data for insurers with qcr == 0
|
|
foreach ($proposalData['insurers'] as $insurerIndex => $insurer) {
|
|
|
|
$qcr = $insurer['qcr'] ?? null;
|
|
$stc = $insurer['stc'] ?? null;
|
|
|
|
if (($qcr === 0 || $qcr === false) || ($stc === 0 || $stc === false)) {
|
|
|
|
foreach ($first_json['table_data']['headers'] as &$header) {
|
|
if (isset($header['subHeaders'])) {
|
|
$header['subHeaders'] = array_values(array_filter($header['subHeaders'], function ($sub) use ($insurer) {
|
|
return $sub !== $insurer['display_name'];
|
|
}));
|
|
}
|
|
}
|
|
|
|
foreach ($first_json['table_data']['data'] as &$item) {
|
|
$item['data'] = array_values(array_filter($item['data'], function ($entry) use ($insurer) {
|
|
return $entry['subth'] !== $insurer['display_name'];
|
|
}));
|
|
}
|
|
|
|
// Remove insurer from proposal's insurers array
|
|
unset($first_json['proposal_data']['over_all_column_data'][$proposalKey]['insurers'][$insurerIndex]);
|
|
|
|
if ($type == 2) {
|
|
unset($first_json['premium_data']['data'][$proposalKey][$insurer['display_name']]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Row-wise Check: Remove rows if qcr == 0 for actions
|
|
$groupedRows = [];
|
|
foreach ($first_json['table_data']['data'] as $rowKey => $rowData) {
|
|
|
|
$groupedRows[$rowData['row_id']][] = $rowData;
|
|
|
|
foreach ($rowData['data'] as $keyIndex => $data) {
|
|
|
|
if ($indexOfTheTable == 0) {
|
|
|
|
if ($data['parentth'] == "Policy" && $data['input_value'] != "Checked") {
|
|
unset($first_json['table_data']['data'][$rowKey]);
|
|
break;
|
|
}
|
|
} else {
|
|
if (
|
|
isset($data['parentth'], $data['input_value']['qcr'], $data['input_value']['stc']) &&
|
|
$data['parentth'] === "Action" &&
|
|
($data['input_value']['qcr'] == 0 || $data['input_value']['stc'] == 0)
|
|
) {
|
|
unset($first_json['table_data']['data'][$rowKey]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$finalRows = [];
|
|
|
|
if (! empty($groupedRows)) {
|
|
|
|
// Loop through each row_id group and check for Policy status
|
|
foreach ($groupedRows as $rowId => $rows) {
|
|
$hasPolicy = false;
|
|
$isChecked = false;
|
|
|
|
foreach ($rows as $row) {
|
|
foreach ($row['data'] as $cell) {
|
|
if ($cell['parentth'] === 'Policy') {
|
|
$hasPolicy = true;
|
|
if (trim(strtolower($cell['input_value'])) === 'checked') {
|
|
$isChecked = true;
|
|
}
|
|
break 2; // Found Policy, no need to continue further
|
|
}
|
|
}
|
|
}
|
|
|
|
// Step 3: If parent Policy is "Checked", retain the entire group
|
|
if (! $hasPolicy || $isChecked) {
|
|
foreach ($rows as $r) {
|
|
$finalRows[] = $r;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (! empty($finalRows)) {
|
|
// Update the original data
|
|
$first_json['table_data']['data'] = array_values($finalRows);
|
|
}
|
|
}
|
|
|
|
// Reindex arrays to maintain proper structure
|
|
$first_json['table_data']['headers'] = array_values($first_json['table_data']['headers']);
|
|
$first_json['table_data']['data'] = array_values($first_json['table_data']['data']);
|
|
$first_json['proposal_data']['over_all_column_data'] = array_map(function ($proposal) {
|
|
$proposal['insurers'] = array_values($proposal['insurers']);
|
|
return $proposal;
|
|
}, $first_json['proposal_data']['over_all_column_data']);
|
|
} else {
|
|
|
|
//remove insurer as Subheaders for RFQ
|
|
foreach ($first_json['table_data']['headers'] as &$header) {
|
|
// Ensure 'subHeaders' exists and is an array before filtering
|
|
if (isset($header['subHeaders']) && is_array($header['subHeaders'])) {
|
|
$header['subHeaders'] = array_filter($header['subHeaders'], function ($subHeader) {
|
|
return in_array($subHeader, ['Sum Insured', '-'], true);
|
|
});
|
|
}
|
|
}
|
|
// Kint::dump($header);
|
|
//Remove insurer Row wise data for RFQ
|
|
$groupedRows = [];
|
|
foreach ($first_json['table_data']['data'] as &$row) {
|
|
|
|
// Filter the inner data array
|
|
$row['data'] = array_filter(
|
|
$row['data'],
|
|
function ($item) {
|
|
return in_array($item['subth'], ['Sum Insured', '-', "Liability Limit"]);
|
|
}
|
|
);
|
|
|
|
$row['data'] = array_values($row['data']);
|
|
|
|
$groupedRows[$row['row_id']][] = $row;
|
|
}
|
|
// Ensure to unset the reference after the loop
|
|
unset($row);
|
|
|
|
$finalRows = [];
|
|
|
|
if (! empty($groupedRows)) {
|
|
|
|
// Loop through each row_id group and check for Policy status
|
|
foreach ($groupedRows as $rowId => $rows) {
|
|
$hasPolicy = false;
|
|
$isChecked = false;
|
|
|
|
foreach ($rows as $row) {
|
|
foreach ($row['data'] as $cell) {
|
|
if ($cell['parentth'] === 'Policy') {
|
|
$hasPolicy = true;
|
|
if (trim(strtolower($cell['input_value'])) === 'checked') {
|
|
$isChecked = true;
|
|
}
|
|
break 2; // Found Policy, no need to continue further
|
|
}
|
|
}
|
|
}
|
|
|
|
// Step 3: If parent Policy is "Checked", retain the entire group
|
|
if (! $hasPolicy || $isChecked) {
|
|
foreach ($rows as $r) {
|
|
$finalRows[] = $r;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (! empty($finalRows)) {
|
|
// Update the original data
|
|
$first_json['table_data']['data'] = array_values($finalRows);
|
|
}
|
|
}
|
|
|
|
// Remove insurers from Proposal Data key for RFQ
|
|
foreach ($proposeldata['proposal_data']['over_all_column_data'] as $key => &$proposal) {
|
|
if (isset($proposal['insurers'])) {
|
|
// Set the insurers array to empty
|
|
$proposal['insurers'] = [];
|
|
}
|
|
}
|
|
|
|
// Ensure to reset the reference
|
|
unset($proposal);
|
|
}
|
|
|
|
return $first_json;
|
|
return null;
|
|
}
|
|
|
|
public function transformNonEbProposelData(&$data, $proposal, $insurer, $tableCount = null, $actionColumn = null)
|
|
{
|
|
// Kint::dump($data, $proposal, $insurer, $tableCount);
|
|
|
|
// Initialize headers with defaults
|
|
$headerData = [];
|
|
|
|
// Add the first two default headers only once
|
|
$headerData[] = [
|
|
'parentHeader' => $data['table_data']['headers'][0]['parentHeader'],
|
|
'subHeaders' => ['-'],
|
|
];
|
|
$headerData[] = [
|
|
'parentHeader' => $data['table_data']['headers'][1]['parentHeader'],
|
|
'subHeaders' => ['-'],
|
|
];
|
|
|
|
$second_table_name = $data['table_data']['headers'][1]['parentHeader'] ?? "";
|
|
|
|
// Loop through the headers to find matching proposal and insurer
|
|
foreach ($data['table_data']['headers'] as $header) {
|
|
if ($header['parentHeader'] === $proposal) {
|
|
foreach ($header['subHeaders'] as $subHeader) {
|
|
if ($subHeader === $insurer) {
|
|
$headerData[] = [
|
|
'parentHeader' => $header['parentHeader'],
|
|
'subHeaders' => ['Sum Insured', $subHeader],
|
|
];
|
|
break 2; // Exit both loops after match is found
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update the original data's headers
|
|
$data['table_data']['headers'] = $headerData;
|
|
|
|
if (! empty($actionColumn)) {
|
|
$data['table_data']['headers'][] = [
|
|
'parentHeader' => "Action",
|
|
'subHeaders' => ['-'],
|
|
];
|
|
}
|
|
|
|
foreach ($data['table_data']['data'] as &$entry) {
|
|
|
|
$sno = $entry['SNO'];
|
|
$items = $entry['items'];
|
|
$row_id = $entry['row_id'];
|
|
|
|
$filteredData = [];
|
|
|
|
foreach ($entry['data'] as $item) {
|
|
|
|
// Always include SNO and Particulars
|
|
if (in_array($item['parentth'], ['S.NO', "Policy", "", 'Particulars', $second_table_name])) {
|
|
$filteredData[] = $item;
|
|
}
|
|
|
|
// Include Proposal with Sum Insured
|
|
if ($item['parentth'] === $proposal && ($item['subth'] === "Sum Insured" || $item['subth'] === "Liability Limit")) {
|
|
$filteredData[] = $item;
|
|
}
|
|
|
|
// Include specific proposal and insurer
|
|
if ($item['parentth'] === $proposal && $item['subth'] === $insurer) {
|
|
$filteredData[] = $item;
|
|
}
|
|
|
|
if (! empty($actionColumn)) {
|
|
if ($item['parentth'] === "Action") {
|
|
$filteredData[] = $item;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update the entry with filtered data
|
|
$entry['SNO'] = $sno;
|
|
$entry['items'] = $items;
|
|
$entry['row_id'] = $row_id;
|
|
$entry['data'] = $filteredData;
|
|
}
|
|
unset($entry);
|
|
|
|
// kint::dump($data);
|
|
return $data;
|
|
}
|
|
|
|
public function getPreviousColumn($columnLetter, $decrement = 1)
|
|
{
|
|
$colIndex = Coordinate::columnIndexFromString($columnLetter);
|
|
$colIndex = max(1, $colIndex - $decrement); // ensure column index doesn't go below 1
|
|
return Coordinate::stringFromColumnIndex($colIndex);
|
|
}
|
|
|
|
public function handleMultiFileAttachments($json_string, $lead_id)
|
|
{
|
|
log_message('error', 'handleMultiFileAttachments called with lead_id: ' . $lead_id);
|
|
|
|
$attachments = [];
|
|
|
|
if (! empty($json_string)) {
|
|
log_message('error', 'json_string is not empty');
|
|
|
|
$fileIds = json_decode($json_string, true);
|
|
log_message('error', 'Decoded fileIds: ' . print_r($fileIds, true));
|
|
|
|
$lead_file_path = WRITEPATH . 'uploads/lead_files';
|
|
log_message('error', 'Lead file path: ' . $lead_file_path);
|
|
|
|
foreach ($fileIds as $id) {
|
|
log_message('error', 'Processing file ID: ' . $id);
|
|
|
|
$lead_file = $this->leadFilesModel
|
|
->where('lead_id', $lead_id)
|
|
->where('id', $id)
|
|
->where('type !=', 2)
|
|
->where('is_active', 1)
|
|
->first();
|
|
|
|
if ($lead_file) {
|
|
log_message('error', 'Found lead file: ' . print_r($lead_file, true));
|
|
|
|
if (empty($lead_file['file_name'])) {
|
|
log_message('error', 'File name is empty for ID: ' . $id);
|
|
continue;
|
|
}
|
|
|
|
$fullPath = storage_ensure_local_file($lead_file_path, $lead_file['file_name']);
|
|
log_message('error', 'Full file path: ' . ($fullPath ?? ''));
|
|
|
|
if (! empty($fullPath) && file_exists($fullPath)) {
|
|
log_message('error', 'File exists at path: ' . $fullPath);
|
|
log_message('error', 'File name is not empty: ' . $lead_file['file_name']);
|
|
|
|
$attachments[] = [
|
|
'fileName' => $lead_file['file_name'],
|
|
'filePath' => $fullPath,
|
|
];
|
|
} else {
|
|
log_message('error', 'File does not exist at path for: ' . $lead_file['file_name']);
|
|
}
|
|
} else {
|
|
log_message('warning', 'No active lead file found for ID: ' . $id . ' and lead_id: ' . $lead_id);
|
|
}
|
|
}
|
|
} else {
|
|
log_message('error', 'json_string is empty');
|
|
}
|
|
|
|
log_message('error', 'Attachments prepared: ' . print_r($attachments, true));
|
|
return $attachments;
|
|
}
|
|
|
|
public function handleMemberDataGPATotalSumInsurerFromExcel($params)
|
|
{
|
|
try {
|
|
$lead_id = $params['lead_id'];
|
|
$lead_data = $this->leadsModel->find((int) $lead_id);
|
|
|
|
if (! $lead_data) {
|
|
return ['status' => 'failed', 'message' => 'Opportunity data not found'];
|
|
}
|
|
|
|
$file_name_with_path = ! empty($lead_data['file_name'])
|
|
? storage_ensure_local_file(WRITEPATH . 'uploads/lead_files', $lead_data['file_name'])
|
|
: null;
|
|
|
|
if ($lead_data['file_name']) {
|
|
|
|
//check physical file
|
|
if (empty($file_name_with_path) || ! file_exists($file_name_with_path)) {
|
|
|
|
$message = "Lead Physcial file not found";
|
|
$this->myLogger->logme('error', ($message . ' for file ' . ($lead_data['file_name'] ?? '')));
|
|
return ['status' => 'failed', 'message' => 'no physical file'];
|
|
}
|
|
|
|
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file_name_with_path);
|
|
|
|
//get members data
|
|
$members_sheet = $spreadsheet->getSheet(0);
|
|
$highestRowAndColumn = $members_sheet->getHighestRowAndColumn();
|
|
|
|
// Read raw values and skip formula evaluation to avoid Calculation exceptions from malformed formulas.
|
|
$uncleaned_members = $members_sheet->rangeToArray(
|
|
'A1:' . $highestRowAndColumn['column'] . $highestRowAndColumn['row'],
|
|
null,
|
|
false,
|
|
true,
|
|
false
|
|
);
|
|
|
|
$members = ExcelSanitizeHelper::sanitizeArrayData($uncleaned_members);
|
|
|
|
// Check column headings
|
|
$members_heading = $members[0];
|
|
$available_col = [];
|
|
|
|
$lower_headers = array_map('strtolower', $members_heading);
|
|
foreach ($lower_headers as $index => $header) {
|
|
if (preg_match('/^(sa\s*-\s*option|proposed\s+sum\s+insured)\s+\d+$/i', $header)) {
|
|
$sum = 0;
|
|
|
|
for ($i = 1; $i < count($members); $i++) {
|
|
$cell_raw = $members[$i][$index] ?? '';
|
|
$cell_clean = preg_replace('/[^0-9.\-]/', '', $cell_raw); // remove non-numeric chars
|
|
|
|
if ($cell_clean !== '' && is_numeric($cell_clean)) {
|
|
$sum += (float) $cell_clean;
|
|
}
|
|
}
|
|
|
|
$available_col[] = $sum;
|
|
}
|
|
}
|
|
|
|
return $available_col;
|
|
}
|
|
|
|
return [];
|
|
} catch (\Throwable $e) {
|
|
log_message('error', 'Exception in handleMemberDataGPATotalSumInsurerFromExcel: {message}', [
|
|
'message' => $e->getMessage(),
|
|
]);
|
|
log_message('error', 'Trace: {trace}', [
|
|
'trace' => $e->getTraceAsString(),
|
|
]);
|
|
|
|
return [];
|
|
}
|
|
}
|
|
|
|
public function generateDemographyDataTable($param = [])
|
|
{
|
|
|
|
if ($this->request !== null) {
|
|
$param['lead_id'] = $this->request->getGet('lead_id');
|
|
}
|
|
|
|
$returnData = $this->calculateMembersDemography($param, "internal");
|
|
|
|
$html = "";
|
|
|
|
if (isset($returnData['data'])) {
|
|
|
|
$data = $returnData['data'];
|
|
foreach ($data as $category => $records) {
|
|
// Extract all column headers (age groups) dynamically
|
|
$allColumns = [];
|
|
foreach ($records as $person => $ages) {
|
|
$allColumns = array_merge($allColumns, array_keys($ages));
|
|
}
|
|
$allColumns = array_unique($allColumns);
|
|
$allColumns = array_values($allColumns); // reset index
|
|
|
|
$category = ucfirst($category);
|
|
|
|
// Start table with clean styling
|
|
$html .= "<h3 style='color: #333; font-weight: 500; margin-bottom: 15px;'>{$category}</h3>";
|
|
$html .= "<table data-custom-table-css='table' style='width: 100%; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 14px;'>";
|
|
|
|
// Table header with light background
|
|
$html .= "<tr>";
|
|
$html .= "<th style='background-color: #f8f9fa; color: #495057; padding: 6px 8px; text-align: left; border: 1px solid #dee2e6; font-weight: 500;'>Relation</th>";
|
|
foreach ($allColumns as $col) {
|
|
$html .= "<th style='background-color: #f8f9fa; color: #495057; padding: 6px 8px; text-align: center; border: 1px solid #dee2e6; font-weight: 500;'>{$col}</th>";
|
|
}
|
|
$html .= "</tr>";
|
|
|
|
// Table rows with clean styling
|
|
foreach ($records as $relation => $ages) {
|
|
$html .= "<tr>";
|
|
$html .= "<td style='padding: 5px 8px; border: 1px solid #dee2e6; background-color: #fff;'>{$relation}</td>";
|
|
foreach ($allColumns as $col) {
|
|
$value = isset($ages[$col]) ? $ages[$col] : "-";
|
|
$html .= "<td style='padding: 5px 8px; border: 1px solid #dee2e6; text-align: center; background-color: #fff;'>{$value}</td>";
|
|
}
|
|
$html .= "</tr>";
|
|
}
|
|
|
|
$html .= "</table>";
|
|
}
|
|
}
|
|
|
|
if ($this->request !== null) {
|
|
if (! empty($html)) {
|
|
return $this->respond(['status' => true, 'data' => $html], 200);
|
|
} else {
|
|
return $this->respond(['status' => false, 'data' => $html], 200);
|
|
}
|
|
}
|
|
|
|
return $html;
|
|
}
|
|
|
|
// function for insurer remainder mail cron job
|
|
public function remainderForQcr()
|
|
{
|
|
$lead_data = $this->leadsModel
|
|
->select(
|
|
'leads.*,
|
|
user_profiles.email as created_person_email,
|
|
policy_type.policy_type,
|
|
policy_type.long_name
|
|
')
|
|
->join('policy_type', 'leads.policy_type_id = policy_type.id')
|
|
->join('user_profiles', 'leads.created_by = user_profiles.id', 'left')
|
|
->where('leads.is_active', 1)
|
|
->where('user_profiles.is_active', 1)
|
|
->whereIn('leads.status', ['rfq_sent', 'qcr_created'])
|
|
->where('leads.next_reminder_date', date('Y-m-d'))
|
|
->findAll();
|
|
|
|
// dd($lead_data);
|
|
|
|
if (count($lead_data) == 0) {
|
|
$this->myLogger->logme("info", "No leads found for reminder mail at " . date('Y-m-d H:i:s'));
|
|
print_r(["status" => true, "message" => "There is no data to send reminder mail"]);
|
|
return ["status" => true, "message" => "There is no data to send reminder mail"];
|
|
|
|
}
|
|
|
|
$from_mail = getenv(LEAD_INSURER_FROM_MAIL_ID);
|
|
$subject = "Reminder for RFQ";
|
|
$content_string = '
|
|
<p>Dear Sir,</p>
|
|
<p>Greetings from Nhance India!</p>
|
|
<p>This is a gentle reminder regarding our earlier mail about the RFQ for the <strong>{{POLICY_TYPE}}</strong> policy pertaining to <strong>{{CLIENT_NAME}}</strong>.</p>
|
|
<p>We kindly request you to share the competitive quotes at the earliest possible convenience.</p>
|
|
<p>In case of any clarification, please feel free to contact us.</p>
|
|
<p>Thank you for your prompt attention to this matter.</p><br>
|
|
<p>Best regards,</p>
|
|
<p><strong>Nhance India</strong></p>
|
|
';
|
|
|
|
$reminder_sended_lead = [];
|
|
|
|
foreach ($lead_data as $lead) {
|
|
|
|
$leadId = $lead['id'];
|
|
$reply_to = $lead['created_person_email'] ?? "";
|
|
|
|
if (isset($lead['policy_end_date']) && $lead['policy_end_date'] != null) {
|
|
$subject = "{{CLIENT_NAME}} _ {{POLICY_TYPE}} _ {{RFQ_OR_QCR}} _ {{POLICY_YEAR}} {{POLICY_END_DATE}}";
|
|
} else {
|
|
$subject = "{{CLIENT_NAME}} _ {{POLICY_TYPE}} _ {{RFQ_OR_QCR}} _ {{POLICY_YEAR}}";
|
|
}
|
|
|
|
$mail_content = $this->transformMailContent($lead, $content_string, "RFQ");
|
|
$mail_subject = $this->transformMailContent($lead, $subject, "RFQ");
|
|
|
|
$this->myLogger->logme("info", "Processing lead_id={$leadId} for reminder mails");
|
|
|
|
// get sales person + created_by emails
|
|
$sales_person_emails = $this->userModel
|
|
->select('email')
|
|
->where('is_active', 1)
|
|
->whereIn('id', json_decode($lead['salse_person_id'] ?? "[]", true))
|
|
->findAll();
|
|
|
|
$email_list = array_column($sales_person_emails, 'email');
|
|
if (! empty($reply_to)) {
|
|
$email_list[] = $reply_to;
|
|
}
|
|
$email_list = array_filter(array_unique($email_list));
|
|
$email_string = implode(',', $email_list);
|
|
|
|
// Get latest sent mail timestamp
|
|
$createdAtRow = $this->gmailSentHistoryModel
|
|
->select("DATE_FORMAT(created_at, '%Y-%m-%d %H:%i') as created_at", false)
|
|
->where('isactive', 1)
|
|
->where('mail_type', 'insurer')
|
|
->where('pk', $leadId)
|
|
->orderBy('id', 'desc')
|
|
->first();
|
|
// dd(db_connect()->getLastQuery(), $createdAtRow);
|
|
|
|
if (! $createdAtRow) {
|
|
$this->myLogger->logme("warning", "No sent history found for lead_id={$leadId}, skipping...");
|
|
continue;
|
|
}
|
|
|
|
$createdAt = $createdAtRow['created_at'];
|
|
|
|
// Fetch mail data for that timestamp
|
|
$mail_datas = $this->gmailSentHistoryModel
|
|
->where('isactive', 1)
|
|
->where('mail_type', "insurer")
|
|
->where('pk', $leadId)
|
|
->where("DATE_FORMAT(created_at, '%Y-%m-%d %H:%i')", $createdAt)
|
|
->findAll();
|
|
|
|
if (empty($mail_datas)) {
|
|
$this->myLogger->logme("warning", "No mail data found for lead_id={$leadId} at created_at={$createdAt}");
|
|
continue;
|
|
}
|
|
|
|
// Filter only pending insurers
|
|
$quote_received_insurer = json_decode($lead['quote_received_insurer'] ?? "[]", true);
|
|
$reminder_mail_data = [];
|
|
|
|
if (empty($quote_received_insurer)) {
|
|
$reminder_mail_data = $mail_datas;
|
|
} else {
|
|
foreach ($mail_datas as $mail_value) {
|
|
$insurer_id = $mail_value['common'] ?? "";
|
|
if (! in_array($insurer_id, $quote_received_insurer)) {
|
|
$reminder_mail_data[] = $mail_value;
|
|
}
|
|
}
|
|
}
|
|
|
|
// dd($reminder_mail_data);
|
|
if (empty($reminder_mail_data)) {
|
|
$this->myLogger->logme("info", "All insurers already responded for lead_id={$leadId}, no reminder needed");
|
|
continue;
|
|
}
|
|
|
|
$this->myLogger->logme("info", "Sending " . count($reminder_mail_data) . " reminder mail(s) for lead_id={$leadId}");
|
|
|
|
$common = ['module' => "leads", 'pk' => $leadId, 'mail_type' => "remainder", 'common' => null];
|
|
|
|
foreach ($reminder_mail_data as $content) {
|
|
$insurerId = $content['common'] ?? null;
|
|
$common['common'] = $insurerId;
|
|
|
|
try {
|
|
|
|
if ($lead['is_insurer_auto_mail'] == 1) {
|
|
// send reminder to insurer
|
|
$res = MailHelper::send_email([
|
|
'from_mail' => $from_mail,
|
|
'mail' => $content['mail'] ?? "",
|
|
'cc' => json_decode($content['cc'] ?? "", true) ?? "",
|
|
'subject' => $mail_subject ?? "",
|
|
'message' => $mail_content ?? "",
|
|
'reply_to' => $reply_to,
|
|
'bcc' => json_decode($content["bcc"] ?? "", true) ?? "",
|
|
'common' => $common,
|
|
]);
|
|
$this->myLogger->logme("info", "Reminder mail sent to the insurer | lead_id={$leadId}, insurer_id={$insurerId}, response=" . json_encode($res));
|
|
|
|
$reminder_sended_lead[] = [
|
|
'lead_id' => $leadId,
|
|
'insurer_id' => $insurerId,
|
|
'response' => $res,
|
|
];
|
|
} else {
|
|
$this->myLogger->logme("info", "Reminder mail disable for this lead_id={$leadId}");
|
|
}
|
|
|
|
} catch (\Throwable $e) {
|
|
$errorDetails = [
|
|
'error_message' => $e->getMessage(),
|
|
'file' => $e->getFile(),
|
|
'line' => $e->getLine(),
|
|
'stack_trace' => $e->getTraceAsString(),
|
|
];
|
|
$this->myLogger->logme("error", "Exception while sending reminder | lead_id={$leadId}, insurer_id={$insurerId}, error=" . json_encode($errorDetails));
|
|
$reminder_sended_lead[] = [
|
|
'lead_id' => $leadId,
|
|
'insurer_id' => $insurerId,
|
|
'response' => ['status' => false, 'error' => $errorDetails],
|
|
];
|
|
}
|
|
|
|
// send reminder to sales person / creator only
|
|
$internal_mail_response = MailHelper::send_email([
|
|
'mail' => $from_mail,
|
|
'cc' => $email_string,
|
|
'subject' => $mail_subject ?? "",
|
|
'message' => $mail_content ?? "",
|
|
'common' => $common,
|
|
]);
|
|
|
|
$this->myLogger->logme("info", "Reminder mail sent to sales persons | lead_id={$leadId}, recipients={$email_string}, response=" . json_encode($internal_mail_response));
|
|
|
|
}
|
|
}
|
|
|
|
return ['status' => true, "data" => $reminder_sended_lead];
|
|
}
|
|
|
|
public function uploadMultiFileFromRfq()
|
|
{
|
|
try {
|
|
|
|
$this->myLogger->logme('error', "uploadMultiFileFromRfq START");
|
|
$this->myLogger->logme('error', "Files received: " . json_encode($this->request->getPost() ?? []));
|
|
|
|
$lead_id = $this->request->getPost('lead_id');
|
|
$lead_form_type = $this->request->getPost('lead_form_type');
|
|
$leads_file_primary_key = $this->request->getPost('leads_file_id') ?? [];
|
|
$docs_name = $this->request->getPost('docs_name') ?? [];
|
|
$files = $this->request->getFileMultiple('file_name');
|
|
|
|
if (empty($files) || empty($docs_name)) {
|
|
$this->myLogger->logme('error', "No files or document names provided");
|
|
return $this->respond([
|
|
'status' => false,
|
|
'code' => 400,
|
|
'message' => 'No files or document names provided',
|
|
], 400);
|
|
}
|
|
|
|
// Upload process
|
|
$multi_file_data = $this->uploadMultiFiles($files, $docs_name, $leads_file_primary_key) ?? [];
|
|
|
|
$this->myLogger->logme('error', "uploadMultiFiles result: " . json_encode($multi_file_data ?? []));
|
|
|
|
if (! empty($multi_file_data)) {
|
|
$this->insertMultiFilesData($multi_file_data, $lead_id, $lead_form_type);
|
|
$this->myLogger->logme('error', "Files inserted successfully into DB");
|
|
|
|
// update lead file name if change
|
|
if (isset($multi_file_data[0]['file_name']) && ! empty($multi_file_data[0]['file_name'])) {
|
|
$this->leadsModel->where('id', $lead_id)->set('file_name', $multi_file_data[0]['file_name'])->update();
|
|
}
|
|
|
|
} else {
|
|
$this->myLogger->logme('error', "uploadMultiFiles returned empty");
|
|
}
|
|
|
|
// Get the updated lead file data
|
|
$lead_file_data = $this->leadFilesModel
|
|
->where('is_active', 1)
|
|
->where('type !=', 2)
|
|
->where('lead_id', $lead_id)
|
|
->findAll();
|
|
|
|
$this->myLogger->logme('error', "Fetched " . count($lead_file_data) . " lead file records");
|
|
|
|
$document_data = $this->renderFileFields($lead_file_data);
|
|
$attch_data['multi_file_data'] = $lead_file_data;
|
|
$attachment_html = view('rfq/attachment_files', $attch_data) ?? "";
|
|
|
|
$this->myLogger->logme('error', "uploadMultiFileFromRfq END");
|
|
|
|
return $this->respond([
|
|
'status' => true,
|
|
'code' => 200,
|
|
'message' => "File uploaded Successfully",
|
|
'document_data' => $document_data,
|
|
'attachment_html' => $attachment_html,
|
|
], 200);
|
|
|
|
} catch (\Throwable $e) {
|
|
|
|
$errorDetails = [
|
|
'error_message' => $e->getMessage(),
|
|
'file' => $e->getFile(),
|
|
'line' => $e->getLine(),
|
|
'stack_trace' => $e->getTraceAsString(),
|
|
];
|
|
|
|
// Catch any error/exception and log with trace
|
|
$this->myLogger->logme('error', "Exception in uploadMultiFileFromRfq: " . json_encode($errorDetails));
|
|
|
|
return $this->respond([
|
|
'status' => false,
|
|
'code' => 500,
|
|
'message' => "File upload failed: " . $e->getMessage(),
|
|
'errorDetails' => $errorDetails,
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
public function renderFileFields($multi_file_data = [])
|
|
{
|
|
$uploadFilePath = WRITEPATH . 'uploads/lead_files/';
|
|
$html = '';
|
|
|
|
// If data exists (edit mode)
|
|
if (! empty($multi_file_data)) {
|
|
|
|
foreach ($multi_file_data as $index => $value) {
|
|
|
|
$sample_dwn_link = ' [ <a href="' . base_url("util/downloadMemberFile/") . $value['file_name'] . '" data-toggle="tooltip" data-placement="top" title="Download Member List" target="_blank">Download</a> ]';
|
|
$isFirstField = ($index === 0);
|
|
$placeholder = $isFirstField ? 'First file must be Demography.' : '';
|
|
$first_file_name = $isFirstField ? 'Member List' : '';
|
|
$member_data_link = $isFirstField ? $sample_dwn_link : '';
|
|
$read_only = $isFirstField ? 'readonly' : '';
|
|
$accept = $isFirstField ? '.xls,.xlsx' : '.xls,.xlsx,.pdf,.jpg,.jpeg,.png';
|
|
$displayIndex = $index + 1;
|
|
|
|
$html .= '
|
|
<div class="form-row d-flex align-items-end" id="fileField_' . $displayIndex . '">
|
|
<input type="hidden" name="leads_file_id[]" value="' . htmlspecialchars($value['id']) . '" id="file_id_' . $displayIndex . '">
|
|
|
|
<div class="form-group col-md-5">
|
|
<label>Document Name</label>
|
|
<input type="text" class="form-control" name="docs_name[]"
|
|
placeholder="' . $placeholder . '"
|
|
value="' . htmlspecialchars(! empty($first_file_name) ? $first_file_name : $value['docs_name']) . '" id="docs_name_' . $displayIndex . '" ' . $read_only . '>
|
|
</div>
|
|
|
|
<div class="form-group col-md-5">
|
|
<label>
|
|
File Upload<br>
|
|
<small id="file_name_display_' . $displayIndex . '" class="text-muted">' .
|
|
(! empty($value['file_name']) ? htmlspecialchars($value['file_name']) : 'No file chosen') .
|
|
'</small> ' . $member_data_link . '
|
|
</label>
|
|
<input type="file" class="form-control" id="file_name_' . $displayIndex . '"
|
|
name="file_name[]" accept="' . $accept . '"
|
|
onchange="showFileName(this, ' . $displayIndex . ')">
|
|
</div>
|
|
|
|
<div class="col-md-2" style="position: relative; bottom: 16px;">
|
|
<button type="button" class="btn btn-danger" onclick="removeFileField(' . $displayIndex . ', ' . htmlspecialchars($value['id']) . ')">x</button>
|
|
<button type="button" class="btn btn-primary" onclick="addFileField()">+</button>
|
|
</div>
|
|
</div>';
|
|
}
|
|
} else {
|
|
// Default (add mode)
|
|
$html .= '
|
|
<div class="form-row d-flex align-items-end" id="fileField_1">
|
|
<input type="hidden" name="leads_file_id[]" value="">
|
|
|
|
<div class="form-group col-md-5">
|
|
<label>Document Name</label>
|
|
<input type="text" class="form-control" name="docs_name[]"
|
|
placeholder="First file must be Demography." id="docs_name_1">
|
|
</div>
|
|
|
|
<div class="form-group col-md-5">
|
|
<label>
|
|
File Upload<br>
|
|
<small id="file_name_display_1" class="text-muted">No file chosen</small>
|
|
</label>
|
|
<input type="file" class="form-control" id="file_name_1"
|
|
name="file_name[]" accept=".xls,.xlsx" onchange="showFileName(this, 1)">
|
|
</div>
|
|
|
|
<div class="col-md-2" style="position: relative; bottom: 16px;">
|
|
<button type="button" class="btn btn-danger" onclick="removeFileField(1, \'\')">x</button>
|
|
<button type="button" class="btn btn-primary" onclick="addFileField()">+</button>
|
|
</div>
|
|
</div>';
|
|
}
|
|
|
|
return $html;
|
|
}
|
|
|
|
public function downloadMemberFile($fileName)
|
|
{
|
|
$fileName = basename((string) $fileName);
|
|
$uploadFilePath = WRITEPATH . 'uploads/lead_files';
|
|
$storage = \Config\Services::getFileStorageService();
|
|
$result = $storage->download($uploadFilePath, $fileName);
|
|
|
|
if (! ($result['success'] ?? false)) {
|
|
$data['message'] = 'The Physical File Not Found';
|
|
return view('errors/404', $data);
|
|
}
|
|
|
|
$downloadAs = storage_upload_display_name($fileName);
|
|
|
|
if (! empty($result['path']) && is_file($result['path'])) {
|
|
return $this->response->download($result['path'], null)->setFileName($downloadAs);
|
|
}
|
|
|
|
if (! empty($result['content'])) {
|
|
return $this->response->download($downloadAs, $result['content'])->setFileName($downloadAs);
|
|
}
|
|
|
|
$data['message'] = 'The Physical File Not Found';
|
|
return view('errors/404', $data);
|
|
}
|
|
|
|
// ----------- MEMBER DATA VALIDAATION ------------------------------------------------------------------------------------------------------
|
|
|
|
public function memberDataListValidation()
|
|
{
|
|
$lead_id = $this->request->getPost('lead_id');
|
|
$this->memberDataListExcelFileFormatValidation(['lead_id' => $lead_id]);
|
|
}
|
|
|
|
public function memberDataListExcelFileFormatValidation($params)
|
|
{
|
|
helper('excel_util_helper');
|
|
|
|
$this->myLogger->logme('error', 'Start memberDataListExcelFileFormatValidation');
|
|
$this->myLogger->logme('error', "Received params: " . json_encode($params));
|
|
|
|
$lead_id = $params['lead_id'];
|
|
$age_validation_check = $params['age_validation'] ?? null;
|
|
$lead_data = $this->leadsModel->where('id', $lead_id)->first();
|
|
// dd($lead_data);
|
|
|
|
$return = [];
|
|
if (! isset($lead_data)) {
|
|
$this->myLogger->logme('error', "Lead not found for lead_id: {$lead_id}");
|
|
$this->leadFilesModel->where('lead_id', $lead_id)->where('type', 2)->set(['status' => 'failed', 'error_data' => json_encode(['error_summary' => array_count_values([12]), 'error_data' => 'file not found in DB'])])->update();
|
|
return ['status' => false, 'msg' => 'file not found in DB'];
|
|
}
|
|
|
|
//get the lead files data
|
|
$lead_file_data = $this->leadFilesModel->where('is_active', 1)->where('type', 2)->first();
|
|
|
|
//check the lead file table has the error data entry if not than create new entry
|
|
if (empty($lead_file_data)) {
|
|
$data['type'] = 2;
|
|
$data['file_name'] = $lead_data['file_name'];
|
|
$data['docs_name'] = "Member List";
|
|
$data['lead_id'] = $lead_id;
|
|
$lead_file_last_insert_id = $this->leadFilesModel->insert($data);
|
|
$this->myLogger->logme('error', "New lead file entry created for store the error data, insert_id : '{$lead_file_last_insert_id}'");
|
|
}
|
|
|
|
$family_composition = [];
|
|
if ($age_validation_check && ! empty($lead_data['proposel_data'])) {
|
|
$family_composition = $this->getAgeRatioFromRfqJson($lead_id, $lead_data['proposel_data']);
|
|
$this->myLogger->logme('info', 'Family composition :', json_encode($family_composition));
|
|
}
|
|
// dd($family_composition);
|
|
|
|
// get the file path
|
|
$file_name_with_path = ! empty($lead_data['file_name'])
|
|
? storage_ensure_local_file(WRITEPATH . 'uploads/lead_files', $lead_data['file_name'])
|
|
: null;
|
|
$this->myLogger->logme('error', "File path: " . ($file_name_with_path ?? ''));
|
|
|
|
//check physical file
|
|
if (empty($file_name_with_path) || ! file_exists($file_name_with_path)) {
|
|
//file not found update status and reason
|
|
$message = "Physcial file not found";
|
|
$this->myLogger->logme('error', ($message . ' for lead id ' . $lead_id));
|
|
$this->leadFilesModel
|
|
->where('lead_id', $lead_id)
|
|
->where('type', 2)
|
|
->set(['status' => 'failed', 'error_data' => json_encode(['error_summary' => array_count_values([5]), 'error_data' => $message])])
|
|
->update();
|
|
return ['error_summary' => [5], 'error_data' => $message];
|
|
}
|
|
|
|
$this->myLogger->logme('info', 'File exists, starting validation process');
|
|
|
|
//start validation process
|
|
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file_name_with_path);
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
|
|
$highestRowAndColumn = $sheet->getHighestRowAndColumn();
|
|
// dd($highestRowAndColumn);
|
|
|
|
$columns_to_check = $this->member_data_excel_columns;
|
|
|
|
$result = ['error_type' => 1, 'error_summary' => [], 'error_data' => []];
|
|
$keys = array_keys($columns_to_check);
|
|
$allowedHighestColumn = end($columns_to_check);
|
|
$excel_data = $sheet->rangeToArray('A1:' . $allowedHighestColumn['col_cell_name'] . $highestRowAndColumn['row']);
|
|
$excel_data = ExcelSanitizeHelper::sanitizeArrayData($excel_data);
|
|
$this->myLogger->logme('error', 'Excel data sanitized count : {row_count}', ['row_count' => count($excel_data)]);
|
|
// dd($excel_data);
|
|
|
|
//check number of columns in excel
|
|
$excel_columns = ($excel_data[0]);
|
|
|
|
//check columns order in excel
|
|
$column_count_res = check_columns_name_exist($columns_to_check, $excel_columns);
|
|
// dd($column_count_res);
|
|
|
|
if (isset($column_count_res) && count($column_count_res)) {
|
|
//columns count mismatch
|
|
$message = implode("\n", $column_count_res);
|
|
// echo $message;
|
|
$this->myLogger->logme('error', ($message . ' for lead id ' . $lead_id));
|
|
$this->leadFilesModel
|
|
->where('lead_id', $lead_id)
|
|
->where('type', 2)
|
|
->set(['status' => 'failed', 'error_data' => json_encode(['error_summary' => array_count_values([6]), 'error_data' => $message])])
|
|
->update();
|
|
return ['error_summary' => [6], 'error_data' => $message];
|
|
}
|
|
|
|
$relationship = $this->general_relationships;
|
|
|
|
$column_count_res = update_excel_column_indexes($columns_to_check, $excel_columns);
|
|
// dd($column_count_res);
|
|
|
|
//remove header
|
|
unset($excel_data[0]);
|
|
$member_family_data = [];
|
|
foreach ($excel_data as $row_key => $row) {
|
|
|
|
//1. avoid empty rows
|
|
if (check_row_is_empty_or_null($row)) {
|
|
$this->myLogger->logme('error', "Empty row found at index {$row_key}, stopping row iteration");
|
|
break;
|
|
}
|
|
|
|
//iterate each row for columns validations
|
|
foreach ($row as $col_key => $col) {
|
|
|
|
$is_mandatory = $columns_to_check[$keys[$col_key]]['is_mandatory'];
|
|
$format = $columns_to_check[$keys[$col_key]]['format'];
|
|
$allowed_values = $columns_to_check[$keys[$col_key]]['allowed_values'];
|
|
$custom_function = isset($columns_to_check[$keys[$col_key]]['custom']) ? $columns_to_check[$keys[$col_key]]['custom'] : null;
|
|
$binding_params = isset($columns_to_check[$keys[$col_key]]['params']) ? $columns_to_check[$keys[$col_key]]['params'] : null;
|
|
|
|
$column_dispaly_name = $columns_to_check[$keys[$col_key]]['col_name'];
|
|
$column_index = $columns_to_check[$keys[$col_key]]['col_idx'];
|
|
$column_cell = $columns_to_check[$keys[$col_key]]['col_cell_name'];
|
|
|
|
//mandatory check
|
|
if (is_bool($is_mandatory) && $is_mandatory === true) {
|
|
if ($col == "" || $col == null) {
|
|
array_push($result['error_summary'], 1); //push error code for summary
|
|
$result['error_data'][$row_key][$keys[$col_key]]['col_name'] = $column_dispaly_name; //push column name
|
|
$result['error_data'][$row_key][$keys[$col_key]]['col_idx'] = $column_index; //push column index
|
|
$result['error_data'][$row_key][$keys[$col_key]]['error'][] = 'Value is mandatory'; //push exact error desc
|
|
}
|
|
}
|
|
|
|
//if is_mandatory is array (action based mandatory check)
|
|
if (is_array($is_mandatory)) {
|
|
$allowed_actions = $columns_to_check[$keys[$col_key]]['is_mandatory'];
|
|
if ($col == "" || $col == null) {
|
|
array_push($result['error_summary'], 1);
|
|
$result['error_data'][$row_key][$keys[$col_key]]['col_name'] = $column_dispaly_name; //push column name
|
|
$result['error_data'][$row_key][$keys[$col_key]]['col_idx'] = $column_index; //push column index
|
|
$result['error_data'][$row_key][$keys[$col_key]]['error'][] = 'Value is mandatory for this action/event';
|
|
}
|
|
}
|
|
|
|
//format check
|
|
if (isset($format)) {
|
|
$format_error = check_excel_date_format($col, $format);
|
|
if (! $format_error['status']) {
|
|
array_push($result['error_summary'], 2);
|
|
$result['error_data'][$row_key][$keys[$col_key]]['col_name'] = $column_dispaly_name; //push column name
|
|
$result['error_data'][$row_key][$keys[$col_key]]['col_idx'] = $column_index; //push column index
|
|
$result['error_data'][$row_key][$keys[$col_key]]['error'][] = $format_error['error'];
|
|
}
|
|
}
|
|
|
|
//allowed values check
|
|
if (($is_mandatory === true && isset($allowed_values) && is_array($allowed_values)) || (is_array($is_mandatory) && (isset($allowed_values) && is_array($allowed_values)))) {
|
|
if (! in_array((trim($col)), $allowed_values)) {
|
|
array_push($result['error_summary'], 3);
|
|
$result['error_data'][$row_key][$keys[$col_key]]['col_name'] = $column_dispaly_name; //push column name
|
|
$result['error_data'][$row_key][$keys[$col_key]]['col_idx'] = $column_index; //push column index
|
|
$result['error_data'][$row_key][$keys[$col_key]]['error'][] = "Value not allowed: Expected " . implode(",", $allowed_values) . " and received $col";
|
|
}
|
|
}
|
|
|
|
//custom function check
|
|
if (isset($custom_function)) {
|
|
//convert string params into PHP variables
|
|
// Create an array of variables to pass custom helper funcitons
|
|
$param_values = [];
|
|
foreach ($binding_params as $bkey => $bparam) {
|
|
$param_values[] = ($$bparam);
|
|
}
|
|
// dd(($param_values));//die();
|
|
$res = call_user_func_array($custom_function, $param_values);
|
|
if ($res['status'] === false) {
|
|
array_push($result['error_summary'], 4);
|
|
$result['error_data'][$row_key][$keys[$col_key]]['col_name'] = $column_dispaly_name; //push column name
|
|
$result['error_data'][$row_key][$keys[$col_key]]['col_idx'] = $column_index; //push column index
|
|
$result['error_data'][$row_key][$keys[$col_key]]['error'][] = $res['error'];
|
|
}
|
|
}
|
|
}
|
|
|
|
//age validation
|
|
$age_validation = isset($columns_to_check['dob']['age_validation']) ?? null;
|
|
if (isset($age_validation) && $age_validation && $age_validation_check && ! empty($family_composition)) {
|
|
$format_error = check_age_validation($row, $family_composition);
|
|
if (! $format_error['status']) {
|
|
array_push($result['error_summary'], 2);
|
|
$result['error_data'][$row_key][$keys[$columns_to_check['dob']['col_idx']]]['col_name'] = $columns_to_check['dob']['col_name']; //push column name
|
|
$result['error_data'][$row_key][$keys[$columns_to_check['dob']['col_idx']]]['col_idx'] = $columns_to_check['dob']['col_idx']; //push column index
|
|
$result['error_data'][$row_key][$keys[$columns_to_check['dob']['col_idx']]]['error'][] = $format_error['error'];
|
|
}
|
|
}
|
|
|
|
$row['row_index'] = $row_key;
|
|
$relation_idx = $columns_to_check['relationship']['col_idx'];
|
|
$emp_code_idx = $columns_to_check['emp_code']['col_idx'];
|
|
|
|
if (isset($row[$relation_idx]) && strtolower($row[$relation_idx]) == 'self' && isset($member_family_data[$row[$emp_code_idx]])) {
|
|
array_unshift($member_family_data[$row[$emp_code_idx]], $row);
|
|
} else {
|
|
$member_family_data[$row[$emp_code_idx]][] = $row;
|
|
}
|
|
}
|
|
// dd($member_family_data);
|
|
|
|
$this->myLogger->logme('info', 'Row validation completed, starting duplicate check');
|
|
$check_row_dublicate = check_duplicate_rows_and_contacts($excel_data, $columns_to_check, $result);
|
|
// dd($check_row_dublicate);
|
|
|
|
if (count($check_row_dublicate)) {
|
|
$result = $check_row_dublicate;
|
|
}
|
|
|
|
$this->myLogger->logme('info', 'Starting family validation');
|
|
$result = validateFamily($member_family_data, $columns_to_check, $result);
|
|
// dd($family_validation);
|
|
|
|
if (isset($result['error_summary']) && count($result['error_summary'])) {
|
|
$result['error_summary'] = array_count_values($result['error_summary']);
|
|
$status = 'failed';
|
|
$failure_reason = ((json_encode($result)));
|
|
$this->leadFilesModel->where('lead_id', $lead_id)->where('type', 2)->set(['status' => $status, 'error_data' => $failure_reason])->update();
|
|
$this->myLogger->logme("error", '{lead_id} uploaded failed for this lead id', ['lead_id' => $lead_id]);
|
|
} else {
|
|
$this->leadFilesModel->where('lead_id', $lead_id)->where('type', 2)->set(['status' => 'success', 'error_data' => ''])->update();
|
|
$r = Jobs::addJob(['job_name' => 'calculateMembersDemography', 'payload' => ['lead_id' => $lead_id]]);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function getAgeRatioFromRfqJson($lead_id, $porposel_data)
|
|
{
|
|
$age_ratio = [];
|
|
$rfq_data = $this->RFQModel->where('is_active', 1)->where('lead_id', $lead_id)->orderBy('id', 'desc')->first();
|
|
if (empty($rfq_data) || empty($rfq_data['json'])) {
|
|
return $age_ratio;
|
|
}
|
|
|
|
$data = json_decode($rfq_data['json'], true);
|
|
$proposal_and_insurer = json_decode($porposel_data, true);
|
|
$insurer_key = $proposal_and_insurer['insurer_name'] ?? null;
|
|
|
|
if (isset($data['table_data']['data'])) {
|
|
foreach ($data['table_data']['data'] as $key => $value) {
|
|
if ($value['items'] == 'family_composition') {
|
|
foreach ($value['data'] as $family_composition) {
|
|
if ($family_composition['subth'] == $insurer_key) {
|
|
$age_ratio = json_decode($family_composition['input_value'] ?? "", true) ?? [];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $age_ratio;
|
|
}
|
|
|
|
public function getMemberDataExcelFileErrors()
|
|
{
|
|
$lead_id = $this->request->getGet('lead_id');
|
|
// $lead_id = 329;
|
|
|
|
// Render views and capture output
|
|
$result = $this->getMemberDataListExcelErrorData($lead_id);
|
|
|
|
if ($result != 0) {
|
|
|
|
$result['lead_id'] = $lead_id;
|
|
echo view('excel_errors', $result);
|
|
} else if ($result == 0) {
|
|
|
|
$data['message'] = 'File Not Found Physically';
|
|
return view('errors/404', $data);
|
|
} else {
|
|
|
|
echo view('errors/html/production');
|
|
}
|
|
}
|
|
|
|
public function getMemberDataListExcelErrorData($lead_id)
|
|
{
|
|
try {
|
|
$file = $this->leadFilesModel->where('lead_id', $lead_id)->where('type', 2)->where('is_active', 1)->first();
|
|
$error_data = json_decode($file['error_data']);
|
|
// dd($error_data);
|
|
// return $error_data;
|
|
|
|
$file_name_with_path = storage_ensure_local_file(WRITEPATH . 'uploads/lead_files', $file['file_name']);
|
|
|
|
//check the file exist or not
|
|
if (empty($file_name_with_path) || ! file_exists($file_name_with_path)) {
|
|
$error_message = "File not found";
|
|
$this->myLogger->logme('error', ($error_message . ' for file id ' . $lead_id));
|
|
return 0;
|
|
}
|
|
|
|
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file_name_with_path);
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
|
|
$highestRowAndColumn = $sheet->getHighestRowAndColumn();
|
|
$excel_data = $sheet->rangeToArray('A1:' . $highestRowAndColumn['column'] . $highestRowAndColumn['row']);
|
|
$excelErrorData['excel_header'] = $excel_data[0];
|
|
unset($excel_data[0]);
|
|
// Kint::dump($excel_data);
|
|
|
|
if ($error_data->error_type == 1) {
|
|
|
|
$finalArray = [];
|
|
foreach ($error_data->error_data as $key => $value) {
|
|
|
|
foreach ($value as $key2 => $value2) {
|
|
$error_data = $value2->error;
|
|
$data = ['value' => $excel_data[$key][$value2->col_idx], 'error' => $error_data];
|
|
$excel_data[$key][$value2->col_idx] = $data;
|
|
}
|
|
array_push($finalArray, $excel_data[$key]);
|
|
}
|
|
|
|
foreach ($finalArray as $fkey => $value) {
|
|
foreach ($value as $vkey => $arrayData) {
|
|
if (! is_array($arrayData)) {
|
|
$data = ['value' => $arrayData];
|
|
$finalArray[$fkey][$vkey] = $data;
|
|
}
|
|
}
|
|
}
|
|
|
|
$excelErrorData['excel_data'] = $finalArray;
|
|
return $excelErrorData;
|
|
} else if ($error_data->error_type == 2) {
|
|
|
|
$allErrors = [];
|
|
$typeTowArray = [];
|
|
|
|
foreach ($error_data->error_data as $index => $item) {
|
|
|
|
foreach ($item as $field) {
|
|
if (! isset($allErrors[$index])) {
|
|
$allErrors[$index] = [];
|
|
}
|
|
$allErrors[$index] = array_merge($allErrors[$index], $field->error);
|
|
}
|
|
}
|
|
|
|
// dd(array_keys($allErrors));
|
|
foreach ($allErrors as $key => $value) {
|
|
// echo $key;
|
|
// print_r($value);
|
|
foreach ($excel_data as $excel_data_index => $excel_data_value) {
|
|
if ($excel_data_value[0] == $key) {
|
|
$data = ['value' => $excel_data[$excel_data_index][1], 'error' => $value];
|
|
$excel_data[$excel_data_index][1] = $data;
|
|
array_push($typeTowArray, $excel_data[$excel_data_index]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// dd($data);
|
|
foreach ($typeTowArray as $fkey => $value) {
|
|
foreach ($value as $vkey => $arrayData) {
|
|
if (! is_array($arrayData)) {
|
|
$data = ['value' => $arrayData];
|
|
$typeTowArray[$fkey][$vkey] = $data;
|
|
}
|
|
}
|
|
}
|
|
|
|
$excelErrorData['excel_data'] = $typeTowArray;
|
|
return $excelErrorData;
|
|
}
|
|
} catch (\Exception $e) {
|
|
// Handle any exceptions
|
|
$errorMessage = $e->getMessage(); //die();
|
|
$this->myLogger->logme('error', $errorMessage);
|
|
return false; // You can return an error response here
|
|
}
|
|
}
|
|
|
|
public function downloadFullMemberDataExcelErrorFile($lead_id, $rowIndex = 1, $colIndex = 1)
|
|
{
|
|
// Get file data from the database
|
|
$file_data = $this->leadFilesModel->where('lead_id', $lead_id)->where('type', 2)->where('is_active', 1)->first();
|
|
|
|
$error = json_decode($file_data['error_data']);
|
|
|
|
// Check if the file exists
|
|
if (! $file_data) {
|
|
$error_message = "File not found";
|
|
$this->myLogger->logme('error', $error_message . ' for file id ' . $lead_id);
|
|
return $error_message;
|
|
}
|
|
|
|
$fileName = $file_data['file_name'];
|
|
$filePath = storage_ensure_local_file(WRITEPATH . 'uploads/lead_files', $fileName);
|
|
|
|
// Check if the file exists
|
|
if (empty($filePath) || ! file_exists($filePath)) {
|
|
$error_message = "File not found";
|
|
$this->myLogger->logme('error', $error_message . ' for file id ' . $lead_id);
|
|
$data['message'] = 'Physical File Not Found';
|
|
return view('errors/404', $data);
|
|
}
|
|
|
|
// Load the Excel file
|
|
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($filePath);
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
|
|
foreach ($error->error_data as $index => $error_data) {
|
|
|
|
$rowIndex = $index + 1;
|
|
|
|
if ($error->error_type == 1) {
|
|
|
|
foreach ($error_data as $key => $value) {
|
|
|
|
$colIndex = $value->col_idx + 1;
|
|
|
|
$originalValue = $sheet->getCell([$colIndex, $rowIndex])->getValue();
|
|
|
|
$newValue = implode(', ', $value->error);
|
|
$val = $originalValue . ' ( ' . $newValue . ' )';
|
|
$sheet->setCellValue([$colIndex, $rowIndex], $val);
|
|
|
|
$style = [
|
|
'fill' => [
|
|
'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID,
|
|
'startColor' => ['rgb' => 'ffad99'], // Red color
|
|
],
|
|
];
|
|
|
|
$sheet->getStyle([$colIndex, $rowIndex])->applyFromArray($style);
|
|
}
|
|
} else if ($error->error_type == 2) {
|
|
|
|
foreach ($error_data as $key => $value) {
|
|
|
|
$originalValue = $sheet->getCell([1, $rowIndex])->getValue();
|
|
|
|
$newValue = implode(', ', $value->error);
|
|
$val = $originalValue . ' ( ' . $newValue . ' )';
|
|
$sheet->setCellValue([$colIndex, $rowIndex], $val);
|
|
|
|
$style = [
|
|
'fill' => [
|
|
'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID,
|
|
'startColor' => ['rgb' => 'ffad99'], // Red color
|
|
],
|
|
];
|
|
$sheet->getStyle([$colIndex, $rowIndex])->applyFromArray($style);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Create a temporary error Excel for download only (not persisted to S3)
|
|
$newFileName = 'error_with_highlight_' . $fileName;
|
|
$tmpDir = rtrim(WRITEPATH, '/\\') . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR . 'claim_files_runtime';
|
|
if (! is_dir($tmpDir)) {
|
|
@mkdir($tmpDir, 0755, true);
|
|
}
|
|
$newFilePath = $tmpDir . DIRECTORY_SEPARATOR . $newFileName;
|
|
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
|
|
$writer->save($newFilePath);
|
|
|
|
// Set headers to force download
|
|
$response = service('response');
|
|
$response->setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
|
$response->setHeader('Content-Disposition', 'attachment;filename="' . $newFileName . '"');
|
|
$response->setHeader('Cache-Control', 'max-age=0');
|
|
$response->setHeader('Content-Length', filesize($newFilePath));
|
|
$response->setBody(file_get_contents($newFilePath));
|
|
|
|
// Delete the temporary file
|
|
unlink($newFilePath);
|
|
|
|
// Return the response
|
|
return $response;
|
|
}
|
|
|
|
public function savePlacementDataAndValidateMemberDataFile()
|
|
{
|
|
try {
|
|
|
|
$this->myLogger->logme('error', '--- savePlacementDataAndValidateMemberDataFile START ---');
|
|
|
|
$params = $this->request->getPost();
|
|
$this->myLogger->logme('error', 'Received params: ' . json_encode($params));
|
|
|
|
if (empty($params['lead_id'])) {
|
|
$this->myLogger->logme('error', 'Lead ID missing');
|
|
return $this->respond([
|
|
'status' => false,
|
|
'code' => 400,
|
|
'message' => 'Opportunity ID is required',
|
|
], 400);
|
|
}
|
|
|
|
$lead_id = $params['lead_id'];
|
|
$proposal_insurer = $params['proposal_insurer'] ?? '';
|
|
|
|
// Handle proposal and insurer details
|
|
if (! empty($proposal_insurer) && strpos($proposal_insurer, '-') !== false) {
|
|
list($proposal_key, $insurer_key) = explode('-', $proposal_insurer, 2);
|
|
$lead_update_data = json_encode([
|
|
'proposel_name' => $proposal_key,
|
|
'insurer_name' => $insurer_key,
|
|
'insurer' => $params['insurer_and_branch'] ?? null,
|
|
]);
|
|
$this->myLogger->logme('error', "Proposal/Insurer parsed successfully: $proposal_key - $insurer_key");
|
|
} else {
|
|
$lead_update_data = null;
|
|
$this->myLogger->logme('error', 'Proposal/Insurer not provided or invalid format');
|
|
}
|
|
|
|
$data = [
|
|
'proposel_data' => $lead_update_data,
|
|
'placement_date' => ! empty($params['placement_date']) ? change_date_format($params['placement_date']) : null,
|
|
'payment_date' => ! empty($params['payment_date']) ? change_date_format($params['payment_date']) : null,
|
|
'utr_no' => $params['utr_no'] ?? null,
|
|
'is_cd' => $params['is_cd'] ?? null,
|
|
'premium_amount' => $params['premium_amount'] ?? null,
|
|
'total_amount' => $params['total_amount'] ?? null,
|
|
'cd_amount' => $params['cd_amount'] ?? null,
|
|
'no_of_installment' => $params['no_of_installment'] ?? null,
|
|
'is_installment' => $params['is_installment'] ?? null,
|
|
'acm_id' => $params['acm_pk'] ?? null,
|
|
];
|
|
|
|
// get lead data
|
|
$lead_data = $this->leadsModel->where('id', $lead_id)->first();
|
|
|
|
// Compare and update only if changed the start and end date
|
|
if (! empty($params['policy_start_date'])) {
|
|
$converted_start = change_date_format($params['policy_start_date']);
|
|
if ($converted_start !== $lead_data['policy_start_date']) {
|
|
$data['policy_start_date'] = $converted_start;
|
|
$this->myLogger->logme('error', "Policy start date updated: $converted_start");
|
|
}
|
|
}
|
|
|
|
if (! empty($params['policy_end_date'])) {
|
|
$converted_end = change_date_format($params['policy_end_date']);
|
|
if ($converted_end !== $lead_data['policy_end_date']) {
|
|
$data['policy_end_date'] = $converted_end;
|
|
$this->myLogger->logme('error', "Policy end date updated: $converted_end");
|
|
}
|
|
}
|
|
|
|
// Handle TPA details
|
|
if (! empty($params['tpa_id']) && strpos($params['tpa_id'], '-') !== false) {
|
|
list($tpaBranchId, $tpaId) = explode('-', $params['tpa_id']);
|
|
$data['tpa_branch_id'] = $tpaBranchId;
|
|
$data['tpa_id'] = $tpaId;
|
|
$this->myLogger->logme('error', "TPA details added: branch=$tpaBranchId, id=$tpaId");
|
|
}
|
|
|
|
$this->myLogger->logme('error', 'Prepared lead update data: ' . json_encode($data));
|
|
|
|
// Update main lead record
|
|
$this->leadsModel->update($lead_id, $data);
|
|
$this->myLogger->logme('error', "Lead updated successfully for ID: $lead_id");
|
|
|
|
// Save installment details
|
|
$savedInstallments = [];
|
|
if (! empty($params['installments'])) {
|
|
$savedInstallments = $this->saveLeadInstallmentDetails((int) $lead_id, $params['installments']);
|
|
$this->myLogger->logme('error', 'Installments saved: ' . json_encode($savedInstallments));
|
|
} else {
|
|
$this->myLogger->logme('error', 'No installments provided');
|
|
}
|
|
|
|
// Update lead file status to pending
|
|
$this->leadFilesModel->where('lead_id', $lead_id)->where('type', 2)->set(['status' => 'pending'])->update();
|
|
|
|
// Queue job after save
|
|
$r = Jobs::addJob(['job_name' => 'memberDataListExcelFileFormatValidation', 'payload' => ['lead_id' => $lead_id, 'age_validation' => true]]);
|
|
$this->myLogger->logme('error', "Job queued successfully: " . json_encode($r));
|
|
|
|
$this->myLogger->logme('error', "--- savePlacementDataAndValidateMemberDataFile END (SUCCESS) ---");
|
|
|
|
return $this->respond([
|
|
'status' => true,
|
|
'code' => 200,
|
|
'message' => 'Placement data saved successfully. File being validated',
|
|
'lead_id' => $lead_id,
|
|
'installments' => $savedInstallments,
|
|
'data' => $data,
|
|
'params' => $params,
|
|
], 200);
|
|
|
|
} catch (\Exception $e) {
|
|
$errorDetails = [
|
|
'error_message' => $e->getMessage(),
|
|
'file' => $e->getFile(),
|
|
'line' => $e->getLine(),
|
|
'stack_trace' => $e->getTraceAsString(),
|
|
];
|
|
$this->myLogger->logme('error', "--- savePlacementDataAndValidateMemberDataFile ERROR --- " . json_encode($errorDetails));
|
|
return $this->respond([
|
|
'status' => false,
|
|
'code' => 500,
|
|
'message' => 'Error while validating the member data',
|
|
'error' => $errorDetails,
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
public function savePlacementDataWithoutMail()
|
|
{
|
|
try {
|
|
$params = $this->request->getPost();
|
|
|
|
if (empty($params['lead_id'])) {
|
|
return $this->respond([
|
|
'status' => false,
|
|
'code' => 400,
|
|
'message' => 'Opportunity ID is required',
|
|
], 400);
|
|
}
|
|
|
|
$lead_id = $params['lead_id'];
|
|
$lead_data = $this->leadsModel->where('id', $lead_id)->first();
|
|
|
|
if (! $lead_data) {
|
|
return $this->respond([
|
|
'status' => false,
|
|
'code' => 404,
|
|
'message' => 'Lead not found',
|
|
], 404);
|
|
}
|
|
|
|
$data = [
|
|
'placement_date' => ! empty($params['placement_date']) ? change_date_format($params['placement_date']) : null,
|
|
'payment_date' => ! empty($params['payment_date']) ? change_date_format($params['payment_date']) : null,
|
|
'utr_no' => $params['utr_no'] ?? null,
|
|
'is_cd' => $params['is_cd'] ?? null,
|
|
'premium_amount' => $params['premium_amount'] ?? null,
|
|
'total_amount' => $params['total_amount'] ?? null,
|
|
'cd_amount' => $params['cd_amount'] ?? null,
|
|
'no_of_installment' => $params['no_of_installment'] ?? null,
|
|
'is_installment' => $params['is_installment'] ?? null,
|
|
'agreed_percentage' => $params['agreed_percentage'] ?? null,
|
|
];
|
|
|
|
if (! empty($params['acm_pk'])) {
|
|
$data['acm_id'] = $params['acm_pk'];
|
|
}
|
|
|
|
if (! empty($params['policy_start_date'])) {
|
|
$converted_start = change_date_format($params['policy_start_date']);
|
|
if ($converted_start !== $lead_data['policy_start_date']) {
|
|
$data['policy_start_date'] = $converted_start;
|
|
}
|
|
}
|
|
|
|
if (! empty($params['policy_end_date'])) {
|
|
$converted_end = change_date_format($params['policy_end_date']);
|
|
if ($converted_end !== $lead_data['policy_end_date']) {
|
|
$data['policy_end_date'] = $converted_end;
|
|
}
|
|
}
|
|
|
|
if (! empty($params['tpa_id']) && strpos($params['tpa_id'], '-') !== false) {
|
|
list($tpaBranchId, $tpaId) = explode('-', $params['tpa_id']);
|
|
$data['tpa_branch_id'] = $tpaBranchId;
|
|
$data['tpa_id'] = $tpaId;
|
|
}
|
|
|
|
$this->leadsModel->update($lead_id, $data);
|
|
|
|
$savedInstallments = [];
|
|
if (! empty($params['installments'])) {
|
|
$savedInstallments = $this->saveLeadInstallmentDetails((int) $lead_id, $params['installments']);
|
|
}
|
|
|
|
return $this->respond([
|
|
'status' => true,
|
|
'code' => 200,
|
|
'message' => 'Placement data saved successfully',
|
|
'lead_id' => $lead_id,
|
|
'installments' => $savedInstallments,
|
|
], 200);
|
|
} catch (\Exception $e) {
|
|
return $this->respond([
|
|
'status' => false,
|
|
'code' => 500,
|
|
'message' => 'Error while saving placement data',
|
|
'error' => $e->getMessage(),
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
public function checkMemberDataFileValidationStatus()
|
|
{
|
|
$lead_id = $this->request->getVar('lead_id');
|
|
if (empty($lead_id)) {
|
|
return $this->respond([
|
|
'status' => false,
|
|
'code' => 400,
|
|
'message' => 'lead_id is required',
|
|
], 400);
|
|
}
|
|
|
|
// Fetch file validation status
|
|
$lead_file = $this->leadFilesModel
|
|
->select('id, lead_id, status')
|
|
->where('lead_id', $lead_id)
|
|
->where('type', 2)
|
|
->first();
|
|
|
|
if (! $lead_file) {
|
|
return $this->respond([
|
|
'status' => false,
|
|
'code' => 404,
|
|
'message' => 'No file found for this lead_id',
|
|
], 404);
|
|
}
|
|
|
|
// If validation is still running
|
|
if ($lead_file['status'] === 'pending' || $lead_file['status'] === null) {
|
|
return $this->respond([
|
|
'status' => true,
|
|
'code' => 202, // Accepted - still processing
|
|
'message' => 'Validation in progress',
|
|
'data' => ['status' => $lead_file['status']],
|
|
], 200);
|
|
}
|
|
|
|
// If validation finished (success or failed)
|
|
return $this->respond([
|
|
'status' => true,
|
|
'code' => 200,
|
|
'message' => 'Validation completed',
|
|
'data' => $lead_file,
|
|
], 200);
|
|
}
|
|
|
|
// ----------- END OF MEMBER DATA VALIDAATION ------------------------------------------------------------------------------------------------------
|
|
|
|
}
|