1195 lines
56 KiB
PHP
1195 lines
56 KiB
PHP
<?php
|
|
|
|
namespace App\Controllers;
|
|
|
|
use App\Controllers\BaseController;
|
|
use CodeIgniter\API\ResponseTrait;
|
|
|
|
use App\Models\NonEbTicketMasterModel;
|
|
use App\Models\NonEbClaimAssetModel;
|
|
use App\Models\ClaimFilesModel;
|
|
use App\Models\TicketClaimStatusModel;
|
|
use App\Models\ClientModel;
|
|
use App\Models\TicketHistoryModel;
|
|
use App\Models\TicketMailTemplateModel;
|
|
use App\Models\TicketMessageModel;
|
|
use App\Models\TicketNoteModel;
|
|
use App\Models\UserModel;
|
|
use App\Models\InsurerModel;
|
|
use App\Models\PolicyTypeModel;
|
|
use App\Models\ClientPolicyModel;
|
|
|
|
use DOMDocument;
|
|
use DOMXPath;
|
|
use App\Helpers\MailHelper;
|
|
|
|
class NonEbClaimController extends BaseController
|
|
{
|
|
use ResponseTrait;
|
|
|
|
protected $myLogger;
|
|
public $priorityType;
|
|
public $placeHolders;
|
|
public $triggerType;
|
|
|
|
protected $nonEbTicketModel;
|
|
protected $assetModel;
|
|
protected $claimFilesModel;
|
|
protected $claimStatus;
|
|
protected $clientModel;
|
|
protected $ticketHistoryModel;
|
|
protected $ticketMailTemplateModel;
|
|
protected $ticketMessageModel;
|
|
protected $ticketNoteModel;
|
|
protected $userModel;
|
|
protected $insurerModel;
|
|
protected $policyTypeModel;
|
|
protected $clientPolicyModel;
|
|
|
|
// Sections visible per claim_status value
|
|
protected $statusSectionVisibility;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->myLogger = \Config\Services::mylogger();
|
|
set_session_context('Non EB Claim Controller');
|
|
|
|
$this->nonEbTicketModel = new NonEbTicketMasterModel();
|
|
$this->assetModel = new NonEbClaimAssetModel();
|
|
$this->claimFilesModel = new ClaimFilesModel();
|
|
$this->claimStatus = new TicketClaimStatusModel();
|
|
$this->clientModel = new ClientModel();
|
|
$this->ticketHistoryModel = new TicketHistoryModel();
|
|
$this->ticketMailTemplateModel = new TicketMailTemplateModel();
|
|
$this->ticketMessageModel = new TicketMessageModel();
|
|
$this->ticketNoteModel = new TicketNoteModel();
|
|
$this->userModel = new UserModel();
|
|
$this->insurerModel = new InsurerModel();
|
|
$this->policyTypeModel = new PolicyTypeModel();
|
|
$this->clientPolicyModel = new ClientPolicyModel();
|
|
|
|
$this->priorityType = [
|
|
1 => 'Low', 2 => 'Medium', 3 => 'High',
|
|
4 => 'Urgent', 5 => 'Emergency', 6 => 'Critical'
|
|
];
|
|
|
|
$this->triggerType = [
|
|
1 => 'Trigger 1', 2 => 'Trigger 2', 3 => 'Trigger 3',
|
|
4 => 'Trigger 4', 5 => 'Trigger 5', 6 => 'Trigger 6',
|
|
7 => 'Trigger 7', 8 => 'Trigger 8', 9 => 'Trigger 9',
|
|
];
|
|
|
|
$this->placeHolders = [
|
|
'((ACM))' => 'acm',
|
|
'((ACM_CONTACT))' => 'acm_mobile',
|
|
'((INSURED_NAME))' => 'insured_contact_name',
|
|
'((CORPORATE_NAME))' => 'client_name',
|
|
'((CLAIM_NO))' => 'claim_number',
|
|
'((POLICY_TYPE))' => 'policy_type_name',
|
|
'((NHANCE_REF_NO))' => 'nhance_claim_ref_no',
|
|
'((LOSS_DATE))' => 'loss_date',
|
|
'((LOSS_LOCATION))' => 'loss_location',
|
|
'((NATURE_OF_LOSS))' => 'nature_of_loss',
|
|
];
|
|
|
|
$this->statusSectionVisibility = [
|
|
'Claim Intimation - Insured' => ['policy_account', 'loss_incident', 'intimation', 'insured_contact', 'asset', 'documents'],
|
|
'Claim Intimation - Insurer' => ['policy_account', 'loss_incident', 'intimation', 'insured_contact', 'asset', 'documents','surveyor'],
|
|
'Survey Appointment - Awaited' => ['policy_account', 'loss_incident', 'intimation', 'insured_contact', 'asset', 'documents','surveyor'],
|
|
'Surveyor Appointed' => ['policy_account', 'loss_incident', 'intimation', 'insured_contact', 'asset', 'documents', 'surveyor'],
|
|
'LOR Awaited - Surveyor' => ['policy_account', 'loss_incident', 'intimation', 'insured_contact', 'asset', 'documents', 'surveyor'],
|
|
'Documents Awaited - Insured' => ['policy_account', 'loss_incident', 'intimation', 'insured_contact', 'asset', 'documents', 'surveyor'],
|
|
'Partial Documents Awaited - Insured' => ['policy_account', 'loss_incident', 'intimation', 'insured_contact', 'asset', 'documents', 'surveyor'],
|
|
'Documents Submitted - Awaiting Loss Assessment' => ['policy_account', 'loss_incident', 'intimation', 'insured_contact', 'asset', 'documents', 'surveyor'],
|
|
'Loss Assessment - Discrepancy' => ['policy_account', 'loss_incident', 'intimation', 'insured_contact', 'asset', 'documents', 'surveyor'],
|
|
'Loss Assessment - Consent Awaited - Insured' => ['policy_account', 'loss_incident', 'intimation', 'insured_contact', 'asset', 'documents', 'surveyor'],
|
|
'Consent Agreed' => ['policy_account', 'loss_incident', 'intimation', 'insured_contact', 'asset', 'documents', 'surveyor', 'settlement'],
|
|
'Claim Approved' => ['policy_account', 'loss_incident', 'intimation', 'insured_contact', 'asset', 'documents', 'surveyor', 'settlement'],
|
|
'Claim Settled' => ['policy_account', 'loss_incident', 'intimation', 'insured_contact', 'asset', 'documents', 'surveyor', 'settlement'],
|
|
'Claim Closed' => ['policy_account', 'loss_incident', 'intimation', 'insured_contact', 'asset', 'documents', 'surveyor', 'settlement'],
|
|
'Claim Rejected' => ['policy_account', 'loss_incident', 'intimation', 'insured_contact', 'asset', 'documents', 'surveyor'],
|
|
'Claim Withdrawn' => ['policy_account', 'loss_incident', 'intimation', 'insured_contact', 'asset', 'documents', 'surveyor'],
|
|
'Workshop Pending' => ['policy_account', 'loss_incident', 'intimation', 'insured_contact', 'asset', 'documents', 'surveyor'],
|
|
];
|
|
}
|
|
|
|
// ===================== LIST =====================
|
|
|
|
public function claimList()
|
|
{
|
|
$data['policy_types'] = $this->policyTypeModel->whereIn('allocg', ['Non-EB', 'Marine'])->where('is_active', 1)->findAll();
|
|
$data['priorityType'] = $this->priorityType;
|
|
$data['tab_name'] = 'Non-EB Claims';
|
|
$data['claim_status'] = $this->claimStatus->select('id,ticket_type,claim_status,display_name')->where('is_active', 1)->findAll();
|
|
$data['client_list'] = $this->clientModel->select('id,client_name')->where('is_active', 1)->findAll();
|
|
$data['insurer_list'] = $this->insurerModel->where('is_active', 1)->findAll();
|
|
$data['date_type'] = ['created_date' => 'Created Date', 'updated_date' => 'Updated Date'];
|
|
|
|
if ($this->request->is('get')) {
|
|
$data['page_name'] = 'Non-EB Claims';
|
|
$data['ticket_data'] = $this->claimSearch(1);
|
|
return $this->loadLayout('non_eb_claim_search', $data);
|
|
} else {
|
|
$data['ticket_data'] = $this->claimSearch();
|
|
$html = view('non_eb_claim_list', $data);
|
|
return $this->respond(['status' => true, 'html' => $html], 200);
|
|
}
|
|
}
|
|
|
|
public function claimSearch($action = null)
|
|
{
|
|
$db = db_connect();
|
|
$rawWhere = [];
|
|
|
|
$query = $db->table('non_eb_ticket_master tm')
|
|
->select([
|
|
'tm.id',
|
|
'tm.policy_type_id',
|
|
'tm.claim_status_id',
|
|
'tcs.claim_status AS status',
|
|
'tcs.display_name AS status_display',
|
|
'tm.claim_number',
|
|
'tm.nhance_claim_ref_no',
|
|
'c.client_name', 'c.short_name',
|
|
'i.name AS insurer_name', 'i.short_name AS insurer_short_name',
|
|
'pt.policy_type AS policy_type_name',
|
|
'tm.loss_date', 'tm.loss_location', 'tm.nature_of_loss', 'tm.loss_estimate',
|
|
'tm.insured_contact_name', 'tm.insured_contact_number', 'tm.insured_contact_email',
|
|
'tm.policy_no',
|
|
'tm.intimation_recd_date', 'tm.intimated_to_insurer_date',
|
|
'tm.surveyor_name', 'tm.loss_assessed_value', 'tm.settled_amount', 'tm.settlement_utr',
|
|
'tm.priority', 'tm.acm_id', 'tm.insurer_id', 'tm.client_policy_id',
|
|
'DATE_FORMAT(tm.created_at, "%d-%m-%Y") AS ticket_created_date',
|
|
'DATE_FORMAT(tm.updated_at, "%d-%m-%Y") AS ticket_updated_date',
|
|
'(SELECT first_name FROM user_profiles WHERE user_profiles.id = tm.acm_id) AS acm_name',
|
|
])
|
|
->join('clients c', 'c.id = tm.client_id AND c.is_active = 1', 'left')
|
|
->join('insurers i', 'i.id = tm.insurer_id AND i.is_active = 1', 'left')
|
|
->join('ticket_claim_status tcs', 'tcs.id = tm.claim_status_id AND tcs.is_active = 1', 'left')
|
|
->join('policy_type pt', 'pt.id = tm.policy_type_id AND pt.is_active = 1', 'left')
|
|
->where('tm.is_active', 1)
|
|
->orderBy('tm.id', 'DESC');
|
|
|
|
if ($action == 1) {
|
|
// Default: open claims (exclude terminal statuses by display_name)
|
|
$query->whereNotIn('tcs.display_name', ['Claim Settled', 'Claim Closed', 'Claim Rejected', 'Claim Withdrawn']);
|
|
return $query->get()->getResultArray();
|
|
}
|
|
|
|
// Filter mode
|
|
$search_data = $this->request->getPost();
|
|
$where = [];
|
|
|
|
foreach ($search_data as $key => $val) {
|
|
if ($val != null && $val != '' && $val != 0) {
|
|
if ($key == 'date_type' && $val === 'created_date') {
|
|
$startDate = date('Y-m-d 00:00:00', strtotime($search_data['start_date']));
|
|
$endDate = date('Y-m-d 23:59:59', strtotime($search_data['end_date']));
|
|
$rawWhere[] = "tm.created_at BETWEEN '$startDate' AND '$endDate'";
|
|
} elseif ($key == 'date_type' && $val === 'updated_date') {
|
|
$startDate = date('Y-m-d 00:00:00', strtotime($search_data['start_date']));
|
|
$endDate = date('Y-m-d 23:59:59', strtotime($search_data['end_date']));
|
|
$rawWhere[] = "tm.updated_at BETWEEN '$startDate' AND '$endDate'";
|
|
} elseif (!in_array($key, ['date_type', 'start_date', 'end_date'])) {
|
|
if ($key == 'policy_type_id') {
|
|
$where['tm.policy_type_id'] = $val;
|
|
} elseif ($key == 'claim_status_id') {
|
|
$where['tm.claim_status_id'] = $val;
|
|
} elseif ($key == 'client_id') {
|
|
$where['tm.client_id'] = $val;
|
|
} elseif ($key == 'insurer_id') {
|
|
$where['tm.insurer_id'] = $val;
|
|
} elseif ($key == 'claim_number') {
|
|
$query->like('tm.claim_number', $val);
|
|
} elseif ($key == 'nhance_claim_ref_no') {
|
|
$query->like('tm.nhance_claim_ref_no', $val);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!empty($where)) {
|
|
$query->where($where);
|
|
}
|
|
foreach ($rawWhere as $condition) {
|
|
$query->where($condition, null, false);
|
|
}
|
|
|
|
return $query->get()->getResultArray();
|
|
}
|
|
|
|
// ===================== FORM (NEW) =====================
|
|
|
|
public function claimForm($policy_type_id)
|
|
{
|
|
$data = $this->getFormData($policy_type_id);
|
|
$data['tab_name'] = 'Non-EB Claims';
|
|
$data['page_name'] = 'Non-EB Claims';
|
|
return $this->loadLayout('non_eb_claim_form', $data);
|
|
}
|
|
|
|
protected function getFormData($policy_type_id, $claim_status_id = null)
|
|
{
|
|
$data = [
|
|
'policy_type_id' => $policy_type_id,
|
|
'priorityType' => $this->priorityType,
|
|
];
|
|
|
|
// Policy type info
|
|
$data['policy_type_info'] = $this->policyTypeModel->where('id', $policy_type_id)->where('is_active', 1)->first();
|
|
$data['policy_type_name'] = $data['policy_type_info']['policy_type'] ?? '';
|
|
|
|
// ACMs
|
|
$db = db_connect();
|
|
$data['acms'] = $db->table('user_profiles')->select('id, first_name')->where(['is_active' => 1, 'role' => 3])->get()->getResultArray();
|
|
|
|
// Clients
|
|
$data['clients'] = $this->clientModel->select('id, client_name')->where('is_active', 1)->findAll();
|
|
|
|
// Insurers
|
|
$data['insurer_list'] = $this->insurerModel->where('is_active', 1)->findAll();
|
|
|
|
// Claim status
|
|
$data['claim_status'] = $this->getClaimStatusForPolicyType($policy_type_id, $claim_status_id);
|
|
|
|
// Visible sections
|
|
$current_status = !empty($data['claim_status']) ? $data['claim_status'][0] : null;
|
|
$data['visible_sections'] = $this->getVisibleSections($current_status, $data['claim_status']);
|
|
|
|
return $data;
|
|
}
|
|
|
|
public function getClaimStatusForPolicyType($policy_type_id, $claim_status_id = null)
|
|
{
|
|
if (empty($claim_status_id)) {
|
|
// Get the first status for this policy type
|
|
$firstStatus = $this->claimStatus
|
|
->where(['is_active' => 1, 'ticket_type' => $policy_type_id])
|
|
->orderBy('id', 'ASC')
|
|
->first();
|
|
$claim_status_id = $firstStatus['id'] ?? null;
|
|
}
|
|
|
|
if (empty($claim_status_id)) return [];
|
|
|
|
$claimStatusData = $this->claimStatus
|
|
->where(['is_active' => 1, 'ticket_type' => $policy_type_id, 'id' => $claim_status_id])
|
|
->first();
|
|
|
|
$filtered = [];
|
|
if (!empty($claimStatusData)) {
|
|
$filtered[] = $claimStatusData;
|
|
$allowedIds = json_decode($claimStatusData['allowed_status'] ?? '[]', true);
|
|
if (!empty($allowedIds) && is_array($allowedIds)) {
|
|
$additional = $this->claimStatus
|
|
->where(['is_active' => 1, 'ticket_type' => $policy_type_id])
|
|
->whereIn('id', $allowedIds)
|
|
->findAll();
|
|
$filtered = array_merge($filtered, $additional);
|
|
}
|
|
}
|
|
|
|
return $filtered;
|
|
}
|
|
|
|
public function getVisibleSections($currentStatus, $allStatuses)
|
|
{
|
|
$sections = ['policy_account', 'loss_incident', 'intimation', 'insured_contact', 'asset', 'documents'];
|
|
|
|
if (!empty($currentStatus)) {
|
|
$claimStatus = $currentStatus['claim_status'] ?? '';
|
|
if (isset($this->statusSectionVisibility[$claimStatus])) {
|
|
$sections = $this->statusSectionVisibility[$claimStatus];
|
|
}
|
|
}
|
|
|
|
return array_values($sections);
|
|
}
|
|
|
|
public function getVisibleSectionsAjax()
|
|
{
|
|
$claim_status_id = $this->request->getPost('claim_status_id');
|
|
$policy_type_id = $this->request->getPost('policy_type_id');
|
|
|
|
$statuses = $this->getClaimStatusForPolicyType($policy_type_id, $claim_status_id);
|
|
// print_rr($statuses);die;
|
|
$currentStatus = !empty($statuses) ? $statuses[0] : null;
|
|
$sections = $this->getVisibleSections($currentStatus, $statuses);
|
|
|
|
return $this->respond(['status' => true, 'sections' => $sections], 200);
|
|
}
|
|
|
|
// ===================== VIEW / EDIT =====================
|
|
|
|
public function view_claim($claim_id)
|
|
{
|
|
$ticket_data = $this->nonEbTicketModel->getTicketDataByTicketID($claim_id);
|
|
|
|
if (empty($ticket_data)) {
|
|
return redirect()->to(base_url('non-eb-claim/list'))->with('error', 'Claim not found');
|
|
}
|
|
|
|
$ticket_data = $this->formatDatesForClaim($ticket_data, 'd/m/Y');
|
|
|
|
$template_data = $this->nonEbTicketModel->getTemplateDataByTicketID($claim_id);
|
|
if (!empty($template_data)) {
|
|
$template_data['mail_content'] = $this->replacePlaceholders($template_data['mail_content'] ?? '', $ticket_data);
|
|
$template_data['subject'] = $this->replacePlaceholders($template_data['subject'] ?? '', $ticket_data);
|
|
}
|
|
|
|
$data = $this->getFormData($ticket_data['policy_type_id'], $ticket_data['claim_status_id']);
|
|
$data['reply_data'] = $template_data;
|
|
$data['placeHolders'] = $this->placeHolders;
|
|
$data['message_data'] = $this->getTicketMessage($claim_id);
|
|
$data['view_ticket_page'] = true;
|
|
$data['ticket_data'] = $ticket_data;
|
|
$data['ticket_history'] = $this->claimHistory($claim_id);
|
|
$data['assets_data'] = $this->getAssets($claim_id);
|
|
$data['tab_name'] = 'Non-EB Claims';
|
|
$data['page_name'] = 'Non-EB Claims';
|
|
|
|
// Visible sections for current + allowed next statuses
|
|
$data['visible_sections'] = $this->getVisibleSections(
|
|
!empty($data['claim_status']) ? $data['claim_status'][0] : null,
|
|
$data['claim_status']
|
|
);
|
|
|
|
return $this->loadLayout('non_eb_claim_edit', $data);
|
|
}
|
|
|
|
// ===================== CREATE =====================
|
|
|
|
public function createClaim()
|
|
{
|
|
$rules = $this->getValidationRules();
|
|
|
|
if (!$this->validate($rules)) {
|
|
return $this->response->setStatusCode(400)->setJSON([
|
|
'status' => false, 'message' => 'Input validation failed',
|
|
'code' => 400, 'errors' => $this->validator->getErrors()
|
|
]);
|
|
}
|
|
|
|
$request_data = $this->request->getPost();
|
|
$sanitized_data = sanitizeInputArrayAdvanced($request_data);
|
|
$ticket_data = $this->formatDatesForClaim($sanitized_data);
|
|
|
|
// Remove fields not in DB
|
|
unset($ticket_data['remark_mode']);
|
|
|
|
// Remove asset arrays from ticket data
|
|
$assetFields = ['asset_id_code', 'serial_no', 'vehicle_no', 'asset_description'];
|
|
foreach ($assetFields as $f) {
|
|
unset($ticket_data[$f]);
|
|
}
|
|
|
|
// Handle asset file upload
|
|
$assetFileName = $this->handleAssetFileUpload();
|
|
if ($assetFileName) {
|
|
$ticket_data['asset_file'] = $assetFileName;
|
|
// Loss description required when asset file uploaded
|
|
if (empty(trim($ticket_data['loss_description'] ?? ''))) {
|
|
return $this->response->setStatusCode(400)->setJSON([
|
|
'status' => false, 'message' => 'Input validation failed', 'code' => 400,
|
|
'errors' => ['loss_description' => 'Loss Description is required when uploading an asset file.']
|
|
]);
|
|
}
|
|
}
|
|
|
|
// Duplicate check
|
|
if ($this->checkDuplicateNonEbClaim($ticket_data)) {
|
|
return $this->respond([
|
|
'status' => false, 'code' => 409,
|
|
'message' => 'Duplicate claim found for Client + Loss Date + Policy No combination'
|
|
], 200);
|
|
}
|
|
|
|
$return_value = $this->nonEbTicketModel->insert($ticket_data);
|
|
if ($return_value) {
|
|
// Save assets
|
|
$this->saveAssets($return_value, $request_data);
|
|
|
|
// History
|
|
$this->putHistoryAfterInsert($ticket_data, $return_value);
|
|
|
|
// Auto mail
|
|
$mail_responce = $this->sendAutoMailTrigger($return_value);
|
|
$this->autoMessageInsertBasedOnMailResponse($mail_responce, $return_value);
|
|
|
|
return $this->respond([
|
|
'status' => true, 'ticket_id' => $return_value, 'code' => 200,
|
|
'message' => 'Non-EB Claim created successfully', 'mail_responce' => $mail_responce
|
|
], 200);
|
|
}
|
|
|
|
return $this->respond(['status' => false, 'code' => 404, 'message' => 'Failed to create claim'], 200);
|
|
}
|
|
|
|
// ===================== UPDATE =====================
|
|
|
|
public function updateClaim()
|
|
{
|
|
$rules = $this->getValidationRules();
|
|
|
|
if (!$this->validate($rules)) {
|
|
return $this->response->setStatusCode(400)->setJSON([
|
|
'status' => false, 'message' => 'Input validation failed',
|
|
'code' => 400, 'errors' => $this->validator->getErrors()
|
|
]);
|
|
}
|
|
|
|
$request_data = $this->request->getPost();
|
|
$sanitized_data = sanitizeInputArrayAdvanced($request_data);
|
|
$ticket_data = $this->formatDatesForClaim($sanitized_data);
|
|
$ticket_id = $this->request->getPost('ticket_master_id');
|
|
|
|
// Handle closure remark append mode
|
|
$remark_mode = $request_data['remark_mode'] ?? 'overwrite';
|
|
unset($ticket_data['remark_mode']);
|
|
if ($remark_mode === 'append' && !empty($ticket_data['closure_remark'])) {
|
|
$existing = $this->nonEbTicketModel->select('closure_remark')->where('id', $ticket_id)->first();
|
|
$existingRemark = $existing['closure_remark'] ?? '';
|
|
if (!empty($existingRemark)) {
|
|
$ticket_data['closure_remark'] = $existingRemark . "\n---\n" . $ticket_data['closure_remark'];
|
|
}
|
|
}
|
|
|
|
// Remove asset arrays
|
|
foreach (['asset_id_code', 'serial_no', 'vehicle_no', 'asset_description'] as $f) {
|
|
unset($ticket_data[$f]);
|
|
}
|
|
|
|
// Handle asset file upload
|
|
$assetFileName = $this->handleAssetFileUpload();
|
|
if ($assetFileName) {
|
|
$ticket_data['asset_file'] = $assetFileName;
|
|
// Loss description required when asset file uploaded
|
|
if (empty(trim($ticket_data['loss_description'] ?? ''))) {
|
|
return $this->response->setStatusCode(400)->setJSON([
|
|
'status' => false, 'message' => 'Input validation failed', 'code' => 400,
|
|
'errors' => ['loss_description' => 'Loss Description is required when uploading an asset file.']
|
|
]);
|
|
}
|
|
}
|
|
|
|
$old_ticket_data = $this->nonEbTicketModel->where('id', $ticket_id)->where('is_active', 1)->first();
|
|
$ticket_data['last_updated_by'] = 'USER';
|
|
|
|
$this->myLogger->logme('error', "[UPDATE_NON_EB_CLAIM] Ticket Master ID: {data}", ['data' => $ticket_id]);
|
|
|
|
$return_value = $this->nonEbTicketModel->where('id', $ticket_id)->set($ticket_data)->update();
|
|
if ($return_value) {
|
|
// Save assets
|
|
$this->saveAssets($ticket_id, $request_data);
|
|
|
|
// Mail on status change
|
|
$mail_responce = null;
|
|
if ($old_ticket_data['claim_status_id'] != $ticket_data['claim_status_id']) {
|
|
$mail_responce = $this->sendAutoMailTrigger($ticket_id);
|
|
$this->autoMessageInsertBasedOnMailResponse($mail_responce, $ticket_id);
|
|
}
|
|
|
|
return $this->respond([
|
|
'status' => true, 'code' => 200,
|
|
'message' => 'Non-EB Claim updated successfully', 'mail_responce' => $mail_responce
|
|
], 200);
|
|
}
|
|
|
|
return $this->respond(['status' => false, 'code' => 404, 'message' => 'Failed to update claim'], 200);
|
|
}
|
|
|
|
// ===================== REMOVE =====================
|
|
|
|
public function removeClaim()
|
|
{
|
|
$ticket_id = $this->request->getGet('ticket_id');
|
|
if (!empty($ticket_id)) {
|
|
$this->nonEbTicketModel->where('id', $ticket_id)->set(['is_active' => 0])->update();
|
|
return $this->respond(['status' => true, 'code' => 200, 'message' => 'Claim removed successfully'], 200);
|
|
}
|
|
return $this->respond(['status' => false, 'code' => 404, 'message' => 'Failed to remove Claim'], 200);
|
|
}
|
|
|
|
// ===================== ASSETS =====================
|
|
|
|
public function saveAssets($claim_id, $post_data)
|
|
{
|
|
// Soft delete existing assets
|
|
$this->assetModel->where('non_eb_ticket_id', $claim_id)->set(['is_active' => 0])->update();
|
|
|
|
$assetCodes = $post_data['asset_id_code'] ?? [];
|
|
$serialNos = $post_data['serial_no'] ?? [];
|
|
$vehicleNos = $post_data['vehicle_no'] ?? [];
|
|
$descriptions = $post_data['asset_description'] ?? [];
|
|
|
|
if (!is_array($assetCodes)) return;
|
|
|
|
for ($i = 0; $i < count($assetCodes); $i++) {
|
|
$code = trim($assetCodes[$i] ?? '');
|
|
$serial = trim($serialNos[$i] ?? '');
|
|
$vehicle = trim($vehicleNos[$i] ?? '');
|
|
$desc = trim($descriptions[$i] ?? '');
|
|
|
|
if (empty($code) && empty($serial) && empty($vehicle) && empty($desc)) continue;
|
|
|
|
$this->assetModel->insert([
|
|
'non_eb_ticket_id' => $claim_id,
|
|
'asset_id_code' => $code,
|
|
'serial_no' => $serial,
|
|
'vehicle_no' => $vehicle,
|
|
'asset_description' => $desc,
|
|
'is_active' => 1,
|
|
]);
|
|
}
|
|
}
|
|
|
|
public function getAssets($claim_id)
|
|
{
|
|
return $this->assetModel->where('non_eb_ticket_id', $claim_id)->where('is_active', 1)->findAll();
|
|
}
|
|
|
|
// ===================== NOTES =====================
|
|
|
|
public function crudNote($action)
|
|
{
|
|
if ($action == 1) {
|
|
$ticket_master_id = $this->request->getPost('id');
|
|
$is_auto_query = $this->request->getPost('is_auto_query') ?? 0;
|
|
if (!empty($ticket_master_id)) {
|
|
$data = $this->ticketNoteModel->where('is_active', 1)->where('ticket_id', $ticket_master_id)->where('is_auto_query', $is_auto_query)->first();
|
|
return $this->respond(['status' => !empty($data), 'data' => $data ?? []], 200);
|
|
}
|
|
} elseif ($action == 2) {
|
|
$request_data = $this->request->getPost();
|
|
$rules = [
|
|
'note' => ['label' => 'Add Notes', 'rules' => 'required|min_length[3]|max_length[1000]',
|
|
'errors' => ['required' => 'Note field cannot be empty.', 'min_length' => 'Note too short.', 'max_length' => 'Note cannot exceed 1000 characters.']
|
|
],
|
|
];
|
|
if (!$this->validate($rules)) {
|
|
return $this->response->setStatusCode(400)->setJSON(['status' => false, 'message' => 'Validation failed', 'code' => 400, 'errors' => $this->validator->getErrors()]);
|
|
}
|
|
$data = sanitizeInputArrayAdvanced($request_data);
|
|
$status = $this->ticketNoteModel->save($data);
|
|
$id = isset($data['id']) ? $data['id'] : $this->ticketNoteModel->insertID();
|
|
return $this->respond(['status' => (bool)$status, 'id' => $id], 200);
|
|
}
|
|
}
|
|
|
|
// ===================== REPLY / MESSAGES =====================
|
|
|
|
public function saveReply()
|
|
{
|
|
$received_data = $this->request->getPost();
|
|
$rules = [
|
|
'emp_mail' => ['label' => 'To', 'rules' => 'required|regex_match[/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/]',
|
|
'errors' => ['required' => 'Email is required.', 'regex_match' => 'Invalid email format.']
|
|
],
|
|
'mail_subject' => ['label' => 'Subject', 'rules' => 'required|min_length[5]',
|
|
'errors' => ['required' => 'Subject is required.', 'min_length' => 'Subject should be at least 5 characters.']
|
|
],
|
|
];
|
|
if (!$this->validate($rules)) {
|
|
return $this->response->setStatusCode(400)->setJSON(['status' => false, 'message' => 'Validation failed', 'code' => 400, 'errors' => $this->validator->getErrors()]);
|
|
}
|
|
$received_data['sender'] = 'staff';
|
|
$status = $this->ticketMessageModel->insert($received_data);
|
|
if ($status) {
|
|
$return = $this->sendReplyMessage($received_data);
|
|
return $this->respond(['status' => true, 'code' => 200, 'return' => $return], 200);
|
|
}
|
|
return $this->respond(['status' => false, 'code' => 404], 404);
|
|
}
|
|
|
|
public function getTicketMessage($ticket_master_id)
|
|
{
|
|
$dataToSend = [];
|
|
$dataToSend['messages'] = $this->ticketMessageModel
|
|
->select('ticket_messages.*, up.first_name as user_name')
|
|
->join('user_profiles up', 'up.id = ticket_messages.created_by', 'left')
|
|
->where('ticket_messages.is_active', 1)
|
|
->where('ticket_messages.ticket_id', $ticket_master_id)
|
|
->orderBy('ticket_messages.created_at', 'DESC')
|
|
->findAll();
|
|
|
|
foreach ($dataToSend['messages'] as &$message) {
|
|
$message['mail_content'] = $this->convertHtmlToText($message['mail_content']);
|
|
}
|
|
unset($message);
|
|
|
|
$claim = $this->nonEbTicketModel->select('insured_contact_name')->where('id', $ticket_master_id)->where('is_active', 1)->first();
|
|
$dataToSend['insured_name'] = $claim['insured_contact_name'] ?? '';
|
|
|
|
return $dataToSend;
|
|
}
|
|
|
|
// ===================== MAIL TEMPLATE =====================
|
|
|
|
public function mailTemplate()
|
|
{
|
|
$data = [];
|
|
$data['trigger_type'] = $this->triggerType;
|
|
$data['policy_types'] = $this->policyTypeModel->whereIn('allocg', ['Non-EB', 'Marine'])->where('is_active', 1)->findAll();
|
|
$data['placeHolders'] = $this->placeHolders;
|
|
$data['ticket_data'] = $this->ticketMailTemplateModel->where('is_active', 1)->findAll();
|
|
|
|
foreach ($data['ticket_data'] as $key => $td) {
|
|
$tooltip = $this->claimStatus->select('claim_status')
|
|
->where('ticket_type', $td['ticket_type'])
|
|
->where('trigger_type', $td['trigger_type'])
|
|
->where('is_active', 1)->first();
|
|
$data['ticket_data'][$key]['tool_tip'] = $tooltip['claim_status'] ?? $td['template_name'];
|
|
}
|
|
|
|
$data['tab_name'] = 'Non-EB Claims';
|
|
$data['page_name'] = 'Non-EB Claims';
|
|
return $this->loadLayout('non_eb_claim_mail_template', $data);
|
|
}
|
|
|
|
public function crudTemplate($action)
|
|
{
|
|
if ($action == 1) {
|
|
$rules = [
|
|
'template_name' => ['rules' => 'required', 'errors' => ['required' => 'Template Name is required']],
|
|
'ticket_type' => ['rules' => 'required', 'errors' => ['required' => 'Policy Type is required']],
|
|
'trigger_type' => ['rules' => 'required', 'errors' => ['required' => 'Trigger Type is required']],
|
|
'subject' => ['rules' => 'required', 'errors' => ['required' => 'Subject is required']],
|
|
'mail_content' => ['rules' => 'required', 'errors' => ['required' => 'Mail Content is required']],
|
|
];
|
|
if (!$this->validate($rules)) {
|
|
return $this->response->setStatusCode(400)->setJSON(['status' => false, 'message' => 'Validation failed', 'code' => 400, 'errors' => $this->validator->getErrors()]);
|
|
}
|
|
$data = sanitizeInputArrayAdvanced($this->request->getPost());
|
|
$status = $this->ticketMailTemplateModel->save($data);
|
|
return $this->respond(['status' => (bool)$status], 200);
|
|
} elseif ($action == 2) {
|
|
$table_id = (int)$this->request->getPost('id');
|
|
$data = $this->ticketMailTemplateModel->where('id', $table_id)->where('is_active', 1)->first();
|
|
if ($data) {
|
|
$tooltip = $this->claimStatus->select('claim_status')
|
|
->where('ticket_type', $data['ticket_type'])->where('trigger_type', $data['trigger_type'])->where('is_active', 1)->first();
|
|
$data['tool_tip'] = $tooltip['claim_status'] ?? $data['template_name'];
|
|
return $this->respond(['status' => true, 'data' => $data], 200);
|
|
}
|
|
return $this->respond(['status' => false], 404);
|
|
} elseif ($action == 3) {
|
|
$table_id = (int)$this->request->getPost('id');
|
|
$status = $this->ticketMailTemplateModel->query("UPDATE ticket_mail_template SET is_active = 0 WHERE id = :table_id:", ['table_id' => $table_id]);
|
|
return $this->respond(['status' => (bool)$status], 200);
|
|
}
|
|
}
|
|
|
|
// ===================== HISTORY =====================
|
|
|
|
public function claimHistory($ticket_id)
|
|
{
|
|
$sql = "SELECT
|
|
th.id, th.field_name, th.display_name, th.old_value, th.new_value, th.created_at, th.updated_by,
|
|
CONCAT_WS(' ', creator.first_name, creator.last_name) AS modified_by,
|
|
old_status.claim_status AS old_status_value,
|
|
new_status.claim_status AS new_status_value,
|
|
CONCAT(old_acm.first_name, ' ', old_acm.last_name) AS old_account_manager,
|
|
CONCAT(new_acm.first_name, ' ', new_acm.last_name) AS new_account_manager
|
|
FROM ticket_history th
|
|
LEFT JOIN user_profiles creator ON th.created_by = creator.id
|
|
LEFT JOIN ticket_claim_status old_status ON th.field_name = 'claim_status_id' AND th.old_value = old_status.id AND old_status.is_active = 1
|
|
LEFT JOIN ticket_claim_status new_status ON th.field_name = 'claim_status_id' AND th.new_value = new_status.id
|
|
LEFT JOIN user_profiles old_acm ON th.field_name = 'acm_id' AND th.old_value = old_acm.id
|
|
LEFT JOIN user_profiles new_acm ON th.field_name = 'acm_id' AND th.new_value = new_acm.id
|
|
WHERE th.ticket_id = :ticket_id: AND th.is_active = 1
|
|
ORDER BY th.created_at DESC";
|
|
|
|
$data = $this->ticketHistoryModel->query($sql, ['ticket_id' => (int)$ticket_id])->getResultArray();
|
|
$priorityType = $this->priorityType;
|
|
|
|
foreach ($data as &$row) {
|
|
if ($row['field_name'] == 'claim_status_id') {
|
|
$row['old_value'] = $row['old_status_value'] ?? '-';
|
|
$row['new_value'] = $row['new_status_value'] ?? '-';
|
|
} elseif ($row['field_name'] == 'acm_id') {
|
|
$row['old_value'] = $row['old_account_manager'] ?? '-';
|
|
$row['new_value'] = $row['new_account_manager'] ?? '-';
|
|
} elseif ($row['field_name'] == 'priority') {
|
|
$row['old_value'] = $priorityType[$row['old_value']] ?? '-';
|
|
$row['new_value'] = $priorityType[$row['new_value']] ?? '-';
|
|
}
|
|
}
|
|
unset($row);
|
|
|
|
return $data;
|
|
}
|
|
|
|
public function putHistoryAfterInsert($ticket_data, $ticket_id)
|
|
{
|
|
$this->myLogger->logme('error', "Put History After Insert (Non-EB) : $ticket_id");
|
|
if (!empty($ticket_data)) {
|
|
$this->ticketHistoryModel->insert([
|
|
'ticket_id' => $ticket_id,
|
|
'field_name' => 'claim_status_id',
|
|
'display_name' => 'Claim Created',
|
|
'old_value' => null,
|
|
'new_value' => $ticket_data['claim_status_id'],
|
|
'created_by' => get_session_userid(),
|
|
'is_active' => 1
|
|
]);
|
|
}
|
|
}
|
|
|
|
// ===================== EMAIL =====================
|
|
|
|
public function constructMailContent($ticket_id, $status_id = null)
|
|
{
|
|
$this->myLogger->logme('error', "Constructing mail content for Non-EB Ticket ID: $ticket_id");
|
|
try {
|
|
$ticket_data = $this->nonEbTicketModel->getTicketDataByTicketID($ticket_id);
|
|
if (!$ticket_data) return null;
|
|
$template_data = $this->nonEbTicketModel->getTemplateDataByTicketID($ticket_id, $status_id);
|
|
if (!$template_data) return null;
|
|
|
|
if ($status_id && isset($template_data['claim_status'])) {
|
|
$ticket_data['claim_status'] = $template_data['claim_status'];
|
|
}
|
|
|
|
$subject = $this->replacePlaceholders($template_data['subject'] ?? '', $ticket_data);
|
|
$message = $this->replacePlaceholders($template_data['mail_content'] ?? '', $ticket_data);
|
|
if (empty($ticket_data['insured_contact_email']) || empty($subject) || empty($message)) return null;
|
|
|
|
return [
|
|
'mail' => [$ticket_data['insured_contact_email']],
|
|
'subject' => $subject,
|
|
'message' => $message,
|
|
'cc' => $ticket_data['common_mails'] ?? '',
|
|
'attachments' => []
|
|
];
|
|
} catch (\Exception $e) {
|
|
$this->myLogger->logme('error', "Exception in constructMailContent (Non-EB): " . $e->getMessage());
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public function replacePlaceholders($content, $ticket_data)
|
|
{
|
|
if (!empty($ticket_data) && !empty($content)) {
|
|
foreach ($this->placeHolders as $key => $value) {
|
|
$replaceData = $ticket_data[$value] ?? '';
|
|
$content = str_replace($key, $replaceData, $content);
|
|
}
|
|
}
|
|
return $content;
|
|
}
|
|
|
|
public function sendTrigger($mail_content)
|
|
{
|
|
if (!empty($mail_content)) {
|
|
$mail_content['from_mail'] = 'claims@nhanceindia.in';
|
|
return MailHelper::send_email($mail_content);
|
|
}
|
|
return ['status' => false, 'code' => 404, 'message' => 'Mail not sent, data empty'];
|
|
}
|
|
|
|
public function sendReplyMessage($mail_data)
|
|
{
|
|
$ticket_data = $this->nonEbTicketModel->getTicketDataByTicketID($mail_data['ticket_id']);
|
|
if (!$ticket_data) return null;
|
|
|
|
if (!empty($mail_data)) {
|
|
$mail_data['mail_content'] = $this->replacePlaceholders($mail_data['mail_content'] ?? '', $ticket_data);
|
|
$mail_data['mail_subject'] = $this->replacePlaceholders($mail_data['mail_subject'] ?? '', $ticket_data);
|
|
}
|
|
|
|
$emailData = [
|
|
'mail' => [$mail_data['emp_mail']],
|
|
'subject' => $mail_data['mail_subject'],
|
|
'message' => $mail_data['mail_content'],
|
|
'common' => [],
|
|
'cc' => $ticket_data['common_mails'] ?? '',
|
|
'attachments' => []
|
|
];
|
|
|
|
return $this->sendTrigger($emailData);
|
|
}
|
|
|
|
public function testAutoMailTrigger($ticket_id)
|
|
{
|
|
$status_id = $this->request->getGet('status_id') ? (int)$this->request->getGet('status_id') : null;
|
|
$preview = (bool)$this->request->getGet('preview');
|
|
|
|
if ($preview) {
|
|
$ticket_data = $this->nonEbTicketModel->getTicketDataByTicketID($ticket_id);
|
|
$template_data = $this->nonEbTicketModel->getTemplateDataByTicketID($ticket_id, $status_id);
|
|
|
|
if ($status_id && !empty($template_data['claim_status'])) {
|
|
$ticket_data['claim_status'] = $template_data['claim_status'];
|
|
}
|
|
|
|
$replaced_subject = $this->replacePlaceholders($template_data['subject'] ?? '', $ticket_data ?? []);
|
|
$replaced_message = $this->replacePlaceholders($template_data['mail_content'] ?? '', $ticket_data ?? []);
|
|
|
|
return $this->respond([
|
|
'status' => true,
|
|
'code' => 200,
|
|
'ticket_id' => $ticket_id,
|
|
'status_id' => $status_id,
|
|
'ticket_data' => $ticket_data,
|
|
'template_data' => $template_data,
|
|
'replaced_subject' => $replaced_subject,
|
|
'replaced_message' => $replaced_message,
|
|
]);
|
|
}
|
|
|
|
$mail_content = $this->constructMailContent($ticket_id, $status_id);
|
|
$mail_responce = $this->sendTrigger($mail_content);
|
|
|
|
return $this->respond([
|
|
'status' => true,
|
|
'code' => 200,
|
|
'ticket_id' => $ticket_id,
|
|
'status_id' => $status_id,
|
|
'mail_responce' => $mail_responce,
|
|
'message' => 'testAutoMailTrigger executed',
|
|
]);
|
|
}
|
|
|
|
public function sendAutoMailTrigger($ticket_id)
|
|
{
|
|
$auto_mail_enable = $this->nonEbTicketModel->getTemplateDataByTicketID($ticket_id);
|
|
$mail_responce = [];
|
|
if (!empty($auto_mail_enable) && ($auto_mail_enable['is_auto_mail'] ?? 0) == 1) {
|
|
$mail_content = $this->constructMailContent($ticket_id);
|
|
$mail_responce = $this->sendTrigger($mail_content);
|
|
$this->myLogger->logme('error', 'Non-EB Auto Mail Sent Successfully');
|
|
}
|
|
return $mail_responce;
|
|
}
|
|
|
|
public function autoMessageInsertBasedOnMailResponse($mail_sent_status, $ticket_id)
|
|
{
|
|
if (gettype($mail_sent_status) == 'array') {
|
|
// already array
|
|
} else {
|
|
$mail_sent_status = json_decode($mail_sent_status);
|
|
}
|
|
|
|
if (!empty($mail_sent_status) && isset($mail_sent_status->status) && $mail_sent_status->status == 'success') {
|
|
$sent_message_data = [
|
|
'ticket_id' => $ticket_id,
|
|
'sender' => 'staff',
|
|
'emp_mail' => isset($mail_sent_status->data->params->mail[0]) ? $mail_sent_status->data->params->mail[0] : ($mail_sent_status->data->params->mail ?? null),
|
|
'mail_subject' => $mail_sent_status->data->params->subject,
|
|
'mail_content' => $mail_sent_status->data->params->message,
|
|
];
|
|
$this->ticketMessageModel->insert($sent_message_data);
|
|
}
|
|
}
|
|
|
|
// ===================== REPORTS =====================
|
|
|
|
public function claimReports()
|
|
{
|
|
if ($this->request->is('get')) {
|
|
$default_start = new \DateTime();
|
|
$data['default_end'] = $default_start->format('d-m-Y');
|
|
$data['default_start'] = $default_start->modify('-60 days')->format('d-m-Y');
|
|
$data['policy_types'] = $this->policyTypeModel->whereIn('allocg', ['Non-EB', 'Marine'])->where('is_active', 1)->findAll();
|
|
$data['account_manager'] = $this->userModel->select('first_name')->where('is_active', 1)->where('role', 3)->findAll();
|
|
$data['tab_name'] = 'Non-EB Claim Reports';
|
|
$data['page_name'] = 'Non-EB Claims';
|
|
$this->loadLayout('non_eb_claim_reports', $data);
|
|
}
|
|
}
|
|
|
|
// ===================== AJAX HELPERS =====================
|
|
|
|
public function getBranchAndPolicyByClientID()
|
|
{
|
|
$client_id = $this->request->getPost('client_id');
|
|
if (empty($client_id)) {
|
|
return $this->respond(['status' => false, 'message' => 'Client ID required'], 200);
|
|
}
|
|
|
|
$db = db_connect();
|
|
|
|
// Fetch branches for this client
|
|
$branch_list = $db->table('client_branch')
|
|
->select('id, branch_name')
|
|
->where('client_id', $client_id)
|
|
->where('is_active', 1)
|
|
->get()->getResultArray();
|
|
|
|
// Fetch Non-EB/Marine policies grouped by branch_id
|
|
$policy_list = [];
|
|
foreach ($branch_list as $branch) {
|
|
$policies = $db->table('client_policy cp')
|
|
->select("cp.id, cp.policy_no, DATE(cp.policy_start_date) as policy_start_date, DATE(cp.policy_end_date) as policy_end_date, cp.insurer_id, cp.insurer_branch_id, cp.client_branch_id, pt.policy_type, pt.id as policy_type_id, i.name as insurer_name, i.short_name as insurer_short_name, ib.branch_code as insurer_branch_code", false)
|
|
->join('policy_type pt', 'pt.id = cp.policy_type_id AND pt.is_active = 1')
|
|
->join('insurers i', 'i.id = cp.insurer_id AND i.is_active = 1', 'left')
|
|
->join('insurer_branch ib', 'ib.id = cp.insurer_branch_id AND ib.is_active = 1', 'left')
|
|
->where('cp.client_id', $client_id)
|
|
->where('cp.client_branch_id', $branch['id'])
|
|
->where('cp.is_active', 1)
|
|
->whereIn('pt.allocg', ['Non-EB', 'Marine'])
|
|
->get()->getResultArray();
|
|
$policy_list[$branch['id']] = $policies;
|
|
}
|
|
|
|
// Fetch client contacts grouped by branch_id
|
|
$contact_list = [];
|
|
foreach ($branch_list as $branch) {
|
|
$contacts = $db->table('level_contacts')
|
|
->select('name, email, mobile')
|
|
->where('ref_id', $branch['id'])
|
|
->where('contact_type', 'client')
|
|
->where('is_active', 1)
|
|
->get()->getResultArray();
|
|
if (!empty($contacts)) {
|
|
$contact_list[$branch['id']] = $contacts[0];
|
|
}
|
|
}
|
|
|
|
return $this->respond([
|
|
'status' => true,
|
|
'branch_data' => $branch_list,
|
|
'policy_data' => $policy_list,
|
|
'contact_data' => $contact_list
|
|
], 200);
|
|
}
|
|
|
|
public function getMoreInfo($requestFrom = null, $ticket_id = null)
|
|
{
|
|
if ($this->request->is('post')) {
|
|
$ticket_id = $this->request->getPost('ticket_id');
|
|
}
|
|
if (empty($ticket_id)) {
|
|
return $this->respond(['status' => false, 'message' => 'Ticket ID required'], 200);
|
|
}
|
|
$data = $this->nonEbTicketModel->getTicketDataByTicketID($ticket_id);
|
|
if ($data) {
|
|
return $this->respond(['status' => true, 'data' => $data], 200);
|
|
}
|
|
return $this->respond(['status' => false, 'message' => 'Not found'], 200);
|
|
}
|
|
|
|
// ===================== UTILITIES =====================
|
|
|
|
protected function getValidationRules()
|
|
{
|
|
return [
|
|
'client_id' => ['rules' => 'required', 'errors' => ['required' => 'Client is required']],
|
|
'branch_id' => ['rules' => 'required', 'errors' => ['required' => 'Branch is required']],
|
|
'policy_type_id' => ['rules' => 'required', 'errors' => ['required' => 'Policy Type is required']],
|
|
'claim_status_id' => ['rules' => 'required', 'errors' => ['required' => 'Status is required']],
|
|
'acm_id' => ['rules' => 'required', 'errors' => ['required' => 'Account Manager is required']],
|
|
'nature_of_loss' => ['label' => 'Nature of Loss', 'rules' => 'required|min_length[3]', 'errors' => ['required' => 'Nature of Loss is required']],
|
|
'loss_date' => ['label' => 'Loss Date', 'rules' => 'required', 'errors' => ['required' => 'Loss Date is required']],
|
|
'loss_location' => ['label' => 'Loss Location', 'rules' => 'required', 'errors' => ['required' => 'Loss Location is required']],
|
|
'insured_contact_name' => ['label' => 'Contact Name', 'rules' => 'required|min_length[3]|regex_match[/^[a-zA-Z0-9\s_-]+$/]', 'errors' => ['required' => 'Insured Contact Name is required', 'regex_match' => 'Only letters, numbers, spaces, hyphens, underscores allowed.']],
|
|
'insured_contact_number' => ['label' => 'Contact Number', 'rules' => 'required|numeric|min_length[10]|max_length[15]', 'errors' => ['required' => 'Contact number is required', 'numeric' => 'Must be numeric']],
|
|
'insured_contact_email' => ['label' => 'Contact Email', 'rules' => 'permit_empty|regex_match[/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/]', 'errors' => ['regex_match' => 'Invalid email format']],
|
|
'policy_no' => ['label' => 'Policy Number', 'rules' => 'permit_empty|max_length[100]'],
|
|
'loss_description' => ['label' => 'Loss Description', 'rules' => 'permit_empty'],
|
|
'loss_estimate' => ['label' => 'Loss Estimate', 'rules' => 'permit_empty|numeric', 'errors' => ['numeric' => 'Must be numeric']],
|
|
'nhance_claim_ref_no' => ['label' => 'Nhance Ref No', 'rules' => 'permit_empty|max_length[100]'],
|
|
'claim_number' => ['label' => 'Claim Number', 'rules' => 'permit_empty|regex_match[/^[a-zA-Z0-9\/_-]+$/]'],
|
|
'surveyor_name' => ['rules' => 'permit_empty|max_length[255]'],
|
|
'surveyor_contact_person' => ['rules' => 'permit_empty|max_length[255]'],
|
|
'surveyor_contact_number' => ['rules' => 'permit_empty|numeric|min_length[10]|max_length[15]'],
|
|
'surveyor_email' => ['rules' => 'permit_empty|regex_match[/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/]'],
|
|
'loss_assessed_value' => ['rules' => 'permit_empty|numeric'],
|
|
'settled_amount' => ['rules' => 'permit_empty|numeric'],
|
|
'settlement_utr' => ['rules' => 'permit_empty|max_length[100]'],
|
|
];
|
|
}
|
|
|
|
public function formatDatesForClaim($ticket_data, $out_put_format = 'Y-m-d')
|
|
{
|
|
$dateFields = ['loss_date', 'intimation_recd_date', 'intimated_to_insurer_date', 'eta_for_documents'];
|
|
foreach ($dateFields as $field) {
|
|
if (empty($ticket_data[$field])) {
|
|
$ticket_data[$field] = null;
|
|
} else {
|
|
$ticket_data[$field] = change_date_format($ticket_data[$field], null, $out_put_format);
|
|
}
|
|
}
|
|
return $ticket_data;
|
|
}
|
|
|
|
protected function checkDuplicateNonEbClaim($data)
|
|
{
|
|
$client_id = $data['client_id'] ?? null;
|
|
$loss_date = $data['loss_date'] ?? null;
|
|
$policy_no = $data['policy_no'] ?? null;
|
|
|
|
if (empty($client_id) || empty($loss_date)) return false;
|
|
|
|
$query = $this->nonEbTicketModel
|
|
->where('client_id', $client_id)
|
|
->where('loss_date', $loss_date)
|
|
->where('is_active', 1);
|
|
|
|
if (!empty($policy_no)) {
|
|
$query->where('policy_no', $policy_no);
|
|
}
|
|
|
|
return !empty($query->first());
|
|
}
|
|
|
|
protected function handleAssetFileUpload()
|
|
{
|
|
$file = $this->request->getFile('asset_file');
|
|
if ($file === null || !$file->isValid() || $file->hasMoved()) {
|
|
return null;
|
|
}
|
|
|
|
$uploadPath = WRITEPATH . 'uploads/non_eb_asset_files/';
|
|
$fileName = file_Upload($file, $uploadPath, UPLOAD_EXT_ASSET_FILES);
|
|
|
|
return !empty($fileName) ? $fileName : null;
|
|
}
|
|
|
|
public function convertHtmlToText($html)
|
|
{
|
|
if (empty($html)) return '';
|
|
$html = preg_replace('/[\x00-\x1F\x80-\xFF]/', ' ', $html);
|
|
$dom = new DOMDocument();
|
|
libxml_use_internal_errors(true);
|
|
$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
|
|
$xpath = new DOMXPath($dom);
|
|
foreach ($xpath->query('//style|//script') as $node) {
|
|
$node->parentNode->removeChild($node);
|
|
}
|
|
$text = $dom->textContent;
|
|
$text = preg_replace('/\s+/', ' ', $text);
|
|
return trim($text);
|
|
}
|
|
|
|
// ===================== CLAIM FILES =====================
|
|
|
|
public function uploadFile()
|
|
{
|
|
$request_data = $this->request->getPost();
|
|
$data = sanitizeInputArrayAdvanced($request_data);
|
|
|
|
$rules = [
|
|
'ticket_id_url' => ['rules' => 'required|numeric', 'errors' => ['required' => 'System could not identify the Ticket.', 'numeric' => 'Invalid format.']],
|
|
'docs_name.*' => ['rules' => 'required|regex_match[/^[a-zA-Z0-9_\- ]+$/]', 'errors' => ['required' => 'Document Name is required', 'regex_match' => 'Only letters, numbers, hyphens, underscores allowed']],
|
|
];
|
|
|
|
if (!$this->validate($rules)) {
|
|
return $this->response->setStatusCode(400)->setJSON(['status' => false, 'message' => 'Input validation failed', 'code' => 400, 'errors' => $this->validator->getErrors()]);
|
|
}
|
|
|
|
$ticket_id = $data['ticket_id_url'];
|
|
$get_file_data = $this->request->getFiles('file_upload') ?? [];
|
|
|
|
if (empty($get_file_data)) {
|
|
$insertArr = [];
|
|
foreach ($data['docs_name'] as $key => $docName) {
|
|
if (!empty($docName)) {
|
|
$insertArr[] = [
|
|
'doc_name' => $docName,
|
|
'url' => convertGoogleDriveToDownloadLink($data['url'][$key] ?? ''),
|
|
'ticket_id' => $ticket_id,
|
|
'ticket_type' => 2,
|
|
'file_type' => 1,
|
|
'is_active' => 1,
|
|
'created_by' => get_session_userid(),
|
|
];
|
|
}
|
|
}
|
|
if (!empty($insertArr)) {
|
|
$insert = $this->claimFilesModel->insertBatch($insertArr);
|
|
}
|
|
if (isset($insert) && !empty($insert)) {
|
|
return $this->respond(['status' => true, 'message' => 'File uploaded successfully']);
|
|
}
|
|
return $this->respond(['status' => false, 'message' => 'Failed to upload file']);
|
|
} else {
|
|
$file_path = WRITEPATH . 'uploads/claim_files/';
|
|
$file_data = multi_file_Upload($get_file_data, $file_path, $data['docs_name'], UPLOAD_EXT_CLAIM_DOCS);
|
|
if (!empty($file_data)) {
|
|
$insertArr = [];
|
|
foreach ($file_data as $f) {
|
|
$insertArr[] = [
|
|
'ticket_id' => $ticket_id,
|
|
'ticket_type' => 2,
|
|
'doc_name' => $f['doc_name'],
|
|
'file_name' => $f['file_name'],
|
|
'url' => $f['file_path'],
|
|
'file_type' => 2,
|
|
'mime_type' => getMimeTypeByFileName($f['file_name']),
|
|
'is_active' => 1,
|
|
'created_by' => get_session_userid(),
|
|
];
|
|
}
|
|
$insert = $this->claimFilesModel->insertBatch($insertArr);
|
|
if ($insert) {
|
|
return $this->respond(['status' => true, 'message' => 'File uploaded successfully']);
|
|
}
|
|
}
|
|
return $this->respond(['status' => false, 'message' => 'Failed to upload file']);
|
|
}
|
|
}
|
|
|
|
public function getClaimFiles()
|
|
{
|
|
$ticket_id = $this->request->getPost('ticket_id');
|
|
if (!$ticket_id) {
|
|
return $this->response->setJSON(['status' => false, 'message' => 'Ticket ID is required', 'data' => []]);
|
|
}
|
|
$files = $this->claimFilesModel
|
|
->select("*, CASE WHEN file_type = 2 AND url IS NOT NULL AND url != '' THEN CONCAT('" . base_url('downloadClaimFile/') . "', id) ELSE url END AS url")
|
|
->where('ticket_id', $ticket_id)
|
|
->where('ticket_type', 2)
|
|
->where('is_active', 1)
|
|
->findAll();
|
|
return $this->response->setJSON(['status' => true, 'data' => $files]);
|
|
}
|
|
|
|
public function removeFile()
|
|
{
|
|
$id = $this->request->getGet('id');
|
|
if (empty(trim($id ?? ''))) {
|
|
return $this->response->setJSON(['status' => false, 'message' => 'Invalid ID']);
|
|
}
|
|
$updated = $this->claimFilesModel->where('id', $id)->set(['is_active' => 0])->update();
|
|
if ($updated) {
|
|
return $this->response->setJSON(['status' => true, 'message' => 'File removed successfully.']);
|
|
}
|
|
return $this->response->setJSON(['status' => false, 'message' => 'Failed to remove file.']);
|
|
}
|
|
|
|
public function saveIRDocs()
|
|
{
|
|
$request_data = $this->request->getPost();
|
|
$data = sanitizeInputArrayAdvanced($request_data);
|
|
$ticket_id = $data['ticket_id'] ?? '';
|
|
$required_docs = $data['required_docs'] ?? '';
|
|
|
|
$rules = [
|
|
'ticket_id' => ['rules' => 'required|numeric', 'errors' => ['required' => 'Ticket ID required.', 'numeric' => 'Invalid format.']],
|
|
'required_docs' => ['rules' => 'required', 'errors' => ['required' => 'Document data is required']],
|
|
];
|
|
if (!$this->validate($rules)) {
|
|
return $this->response->setStatusCode(400)->setJSON(['status' => false, 'message' => 'Input validation failed', 'code' => 400, 'errors' => $this->validator->getErrors()]);
|
|
}
|
|
|
|
$docsArray = json_decode($required_docs, true);
|
|
if (json_last_error() !== JSON_ERROR_NONE || !isset($docsArray['docs']) || !is_array($docsArray['docs'])) {
|
|
return $this->response->setStatusCode(400)->setJSON(['status' => false, 'message' => 'Invalid document data', 'code' => 400, 'errors' => ['required_docs' => 'Invalid JSON structure']]);
|
|
}
|
|
|
|
foreach ($docsArray['docs'] as $index => $doc) {
|
|
if (!isset($doc['document_name']) || !preg_match('/^[a-zA-Z0-9_\- ]+$/', $doc['document_name'])) {
|
|
return $this->response->setStatusCode(400)->setJSON(['status' => false, 'message' => 'Invalid document name at row ' . ($index + 1), 'code' => 400, 'errors' => ['required_docs' => 'Invalid document name at row ' . ($index + 1)]]);
|
|
}
|
|
}
|
|
|
|
db_connect()->query("UPDATE non_eb_ticket_master SET required_docs = ? WHERE id = ?", [$required_docs, $ticket_id]);
|
|
|
|
$saved = $this->nonEbTicketModel->select('required_docs')->where('id', $ticket_id)->first();
|
|
$savedDocs = json_decode($saved['required_docs'] ?? '{}', true) ?? [];
|
|
|
|
return $this->respond(['status' => true, 'code' => 200, 'message' => 'IR docs saved successfully', 'data' => $savedDocs], 200);
|
|
}
|
|
}
|