FEAT_DAILY_ACTIVITY_REPORT_AND_OTHER_ISSUES_FIXES

This commit is contained in:
VENKATESHWARAN 2026-03-04 11:49:57 +05:30
parent 3b357901e0
commit e18831785f
10 changed files with 785 additions and 51 deletions

View File

@ -446,12 +446,14 @@ $routes->group("/util", ["filter" => "authMVC"], function ($routes) {
$routes->get('generateDemographyDataTable', 'LeadsController::generateDemographyDataTable');
$routes->post('insufficientCdBalanceHrMailSend', 'EmployeeController::insufficientCdBalanceHrMailSend');
$routes->get('getTpaClaimDumpErrorData/(:any)', 'TicketServiceController::getTpaClaimDumpErrorData/$1');
$routes->get('croneDailyActivityReport', 'DashboardController::croneDailyActivityReport');
});
$routes->post("policy_tranction/sendInstallmentRemainderMail","PolicyTransactionController::sendInstallmentRemainderMail");
$routes->cli("cli/sendInstallmentRemainderMail","PolicyTransactionController::sendInstallmentRemainderMail");
$routes->cli("cli/cronDailyBDSReport", "PolicyTransactionController::cronDailyBDSReport");
$routes->cli('cli/croneDailyActivityReport', 'DashboardController::croneDailyActivityReport');
$routes->group("policy_tranction", ["filter" => "authMVC"], function ($routes) {

View File

@ -6975,7 +6975,9 @@ class ClientController extends AdminController
// $response = $ticketServiceController->tpaClaimDumpImporter(["file_id" => 53]); //icici
// $response = $ticketServiceController->tpaClaimDumpImporter(["file_id" => 54]); //mediassist
// $response = $ticketServiceController->tpaClaimDumpImporter(["file_id" => 52]); //reliance
// $response = $ticketServiceController->tpaClaimDumpImporter(["file_id" => 48]); //vidal
// $response = $ticketServiceController->tpaClaimDumpImporter(["file_id" => 48]); //vidal`
// $response = $ticketServiceController->tpaClaimDumpImporter(["file_id" => 57]); //mediassist
// $response = $ticketServiceController->tpaClaimDumpToTicketMasterImporters(["file_id" => 51]); //abhi
// $response = $ticketServiceController->tpaClaimDumpToTicketMasterImporters(["file_id" => 50]); //fhpl

View File

@ -7,6 +7,7 @@ use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Psr\Log\LoggerInterface;
use App\Helpers\sendMailNotification;
use App\Helpers\MailHelper;
use CodeIgniter\API\ResponseTrait;
@ -24,6 +25,11 @@ use App\Controllers\EmpDataServiceController;
use App\Models\TicketMasterModel;
use App\Models\LeadsModel;
use App\Models\TicketClaimStatusModel;
use App\Models\FileModel;
use App\Models\BatchFileModel;
use App\Models\SalesActivityModel;
use App\Models\SalesActualLeadModel;
class DashboardController extends AdminController
@ -43,6 +49,13 @@ class DashboardController extends AdminController
protected $policyStatus;
protected $colorShades;
protected $claimDashLimit;
protected $filesModel;
protected $batchFilesModel;
protected $leadsModel;
protected $ticketMasterModel;
protected $ticketClaimStatusModel;
protected $salesActivityModel;
protected $salesActualModel;
protected $myLogger;
@ -59,6 +72,13 @@ class DashboardController extends AdminController
$this->ticketModel = new TicketMasterModel();
$this->leadModel = new LeadsModel();
$this->ticketStatusModel = new TicketClaimStatusModel();
$this->filesModel = new FileModel();
$this->batchFilesModel = new BatchFileModel();
$this->leadsModel = new LeadsModel();
$this->ticketMasterModel = new TicketMasterModel();
$this->ticketClaimStatusModel = new TicketClaimStatusModel();
$this->salesActivityModel = new SalesActivityModel();
$this->salesActualModel = new SalesActualLeadModel();
$this->myLogger = \Config\Services::mylogger();
@ -787,4 +807,298 @@ class DashboardController extends AdminController
$data['ticket_type_id'] = $ticketTypeId;
return $this->respond(['status' => "success", "data" => $data], 200);
}
public function croneDailyActivityReport()
{
// $today = date('Y-m-d');
$today = date('Y-m-d', strtotime('-1 day'));
// Inception & endorsement counts (file uploads)
$total_inception_count = $this->filesModel
->where('is_active', 1)
->where('DATE(created_at)', $today)
->where('action', 'inception')
->where('status', 'success')
->countAllResults();
$total_endorsement_count = $this->filesModel
->where('is_active', 1)
->where('DATE(created_at)', $today)
->where('action !=', 'inception')
->where('status', 'success')
->countAllResults();
// TPA & Insurer batch file counts
$total_tpa_incetion_count = $this->batchFilesModel
->where('is_active', 1)
->where('DATE(created_at)', $today)
->where('event_type', 'inception')
->where('insurer_or_tpa', 'tpa')
->where('status', 'success')
->countAllResults();
$total_tpa_endorsement_count = $this->batchFilesModel
->where('is_active', 1)
->where('DATE(created_at)', $today)
->where('event_type !=', 'inception')
->where('insurer_or_tpa', 'tpa')
->where('status', 'success')
->countAllResults();
$total_insurer_incetion_count = $this->batchFilesModel
->where('is_active', 1)
->where('DATE(created_at)', $today)
->where('event_type', 'inception')
->where('insurer_or_tpa', 'insurer')
->where('status', 'success')
->countAllResults();
$total_insurer_endorsement_count = $this->batchFilesModel
->where('is_active', 1)
->where('DATE(created_at)', $today)
->where('event_type !=', 'inception')
->where('insurer_or_tpa', 'insurer')
->where('status', 'success')
->countAllResults();
// Claim counts
$total_claim_count = $this->ticketMasterModel
->where('is_active', 1)
->where('DATE(created_at)', $today)
->countAllResults();
$total_gmc_status_wise_claim_count = $this->ticketMasterModel
->select('tcs.claim_status, count(*) as count')
->join('ticket_claim_status tcs', 'tcs.id = ticket_master.claim_status_id', 'left')
->where('ticket_master.is_active', 1)
->where('ticket_master.ticket_type_id', 1)
// ->where('DATE(ticket_master.created_at)', $today)
->where('tcs.is_active', 1)
->groupBy('tcs.claim_status')
->findAll();
$total_gpa_status_wise_claim_count = $this->ticketMasterModel
->select('tcs.claim_status, count(*) as count')
->join('ticket_claim_status tcs', 'tcs.id = ticket_master.claim_status_id', 'left')
->where('ticket_master.is_active', 1)
->where('ticket_master.ticket_type_id', 2)
// ->where('DATE(ticket_master.created_at)', $today)
->where('tcs.is_active', 1)
->groupBy('tcs.claim_status')
->findAll();
$total_edli_status_wise_claim_count = $this->ticketMasterModel
->select('tcs.claim_status, count(*) as count')
->join('ticket_claim_status tcs', 'tcs.id = ticket_master.claim_status_id', 'left')
->where('ticket_master.is_active', 1)
->where('ticket_master.ticket_type_id', 3)
// ->where('DATE(ticket_master.created_at)', $today)
->where('tcs.is_active', 1)
->groupBy('tcs.claim_status')
->findAll();
$total_gtli_status_wise_claim_count = $this->ticketMasterModel
->select('tcs.claim_status, count(*) as count')
->join('ticket_claim_status tcs', 'tcs.id = ticket_master.claim_status_id', 'left')
->where('ticket_master.is_active', 1)
->where('ticket_master.ticket_type_id', 4)
// ->where('DATE(ticket_master.created_at)', $today)
->where('tcs.is_active', 1)
->groupBy('tcs.claim_status')
->findAll();
// Sales / lead counts
$total_opportunity_count = $this->leadsModel
->where('is_active', 1)
->where('DATE(created_at)', $today)
->countAllResults();
$total_rfq_created_count = $this->leadsModel
->where('is_active', 1)
->where('DATE(created_at)', $today)
->where('status', 'rfq_created')
->countAllResults();
$total_rfq_insurer_send_count = $this->leadsModel
->where('is_active', 1)
->where('DATE(created_at)', $today)
->where('status', 'rfq_sent')
->countAllResults();
$total_qcr_created_count = $this->leadsModel
->where('is_active', 1)
->where('DATE(created_at)', $today)
->where('status', 'qcr_created')
->countAllResults();
$total_qcr_client_send_count = $this->leadsModel
->where('is_active', 1)
->where('DATE(created_at)', $today)
->where('status', 'qcr_sent')
->countAllResults();
$total_placement_count = $this->leadsModel
->where('is_active', 1)
->where('DATE(created_at)', $today)
->where('status', 'won')
->countAllResults();
$total_activity_count = $this->salesActivityModel
->where('DATE(created_at)', $today)
->countAllResults();
$total_lead_count = $this->salesActualModel
->where('DATE(created_at)', $today)
->countAllResults();
$total_bds_count = $this->policyTransactionModel
->select('pt_co_share_details.*')
->join('pt_co_share_details', 'policy_transaction.id = pt_co_share_details.pt_id')
->where('DATE(policy_transaction.created_at)', $today)
->where('pt_co_share_details.is_active', 1)
->where('policy_transaction.is_active', 1)
->countAllResults();
$total_bds_policy_wise_count = $this->policyTransactionModel
->select('pt_co_share_details.*')
->join('pt_co_share_details', 'policy_transaction.id = pt_co_share_details.pt_id')
->where('DATE(policy_transaction.created_at)', $today)
->where('pt_co_share_details.is_active', 1)
->where('policy_transaction.action_type', 'inception')
->where('policy_transaction.is_active', 1)
->countAllResults();
$total_bds_endorsement_wise_count = $this->policyTransactionModel
->select('pt_co_share_details.*')
->join('pt_co_share_details', 'policy_transaction.id = pt_co_share_details.pt_id')
->where('DATE(policy_transaction.created_at)', $today)
->where('pt_co_share_details.is_active', 1)
->where('policy_transaction.action_type !=', 'inception')
->where('policy_transaction.is_active', 1)
->countAllResults();
$total_bds_policy_type_wise_count = $this->policyTransactionModel
->select('policy_type.policy_type, count(*) as count')
->join('pt_co_share_details', 'policy_transaction.id = pt_co_share_details.pt_id')
->join('policy_type', 'policy_transaction.policy_type_id = policy_type.id')
->where('DATE(policy_transaction.created_at)', $today)
->where('pt_co_share_details.is_active', 1)
->where('policy_transaction.is_active', 1)
->groupBy('policy_transaction.policy_type_id')
->findAll();
// Connect Pre DB for Employee Enrollment Count
$db2 = \Config\Database::connect('preDB');
$builder = $db2->table('employees');
$total_employee_draft_count = $builder->join('employee_polices', 'employees.id = employee_polices.employee_id')
->select('employee_polices.status, count(*) as count')
->where('DATE(employee_polices.created_at)', $today)
->where('employee_polices.is_active', 1)
->where('employees.is_active', 1)
->whereIn('employee_polices.status', ['draft'])
->groupBy('employee_polices.status')
->countAllResults();
$builder1 = $db2->table('employees');
$total_employee_enrolled_count = $builder1->join('employee_polices', 'employees.id = employee_polices.employee_id')
->select('employee_polices.status, count(*) as count')
->where('DATE(employee_polices.created_at)', $today)
->where('employee_polices.is_active', 1)
->where('employees.is_active', 1)
->whereIn('employee_polices.status', ['enrolled'])
->groupBy('employee_polices.status')
->countAllResults();
$builder2 = $db2->table('files');
$total_open_for_enrollemnt_policy_count = $builder2
->select('COUNT(*) as count')
->where('enrollment_open_date <=', $today)
->where('enrollment_close_date >=', $today)
->where('is_active', 1)
->where('status', 'success')
->countAllResults();
$data = [
'total_inception_count' => $total_inception_count,
'total_endorsement_count' => $total_endorsement_count,
'total_tpa_incetion_count' => $total_tpa_incetion_count,
'total_tpa_endorsement_count' => $total_tpa_endorsement_count,
'total_insurer_incetion_count' => $total_insurer_incetion_count,
'total_insurer_endorsement_count' => $total_insurer_endorsement_count,
'total_claim_count' => $total_claim_count,
'total_gmc_status_wise_claim_count' => $total_gmc_status_wise_claim_count,
'total_gpa_status_wise_claim_count' => $total_gpa_status_wise_claim_count,
'total_edli_status_wise_claim_count' => $total_edli_status_wise_claim_count,
'total_gtli_status_wise_claim_count' => $total_gtli_status_wise_claim_count,
'total_opportunity_count' => $total_opportunity_count,
'total_rfq_created_count' => $total_rfq_created_count,
'total_rfq_insurer_send_count' => $total_rfq_insurer_send_count,
'total_qcr_created_count' => $total_qcr_created_count,
'total_qcr_client_send_count' => $total_qcr_client_send_count,
'total_placement_count' => $total_placement_count,
'total_activity_count' => $total_activity_count,
'total_lead_count' => $total_lead_count,
'total_bds_count' => $total_bds_count,
'total_bds_policy_wise_count' => $total_bds_policy_wise_count,
'total_bds_endorsement_wise_count' => $total_bds_endorsement_wise_count,
'total_bds_policy_type_wise_count' => $total_bds_policy_type_wise_count,
'total_employee_draft_count' => $total_employee_draft_count,
'total_employee_enrolled_count' => $total_employee_enrolled_count,
'total_open_for_enrollemnt_policy_count' => $total_open_for_enrollemnt_policy_count,
];
// dd($data);
$today = date('d-m-Y', strtotime($today));
$data['today'] = $today;
// Render the HTML email using the dedicated view
$message = view('daily_report_email_template', $data);
// return $message;
// Recipients: prefer dedicated env, fallback to BDS report emails if not set
$emailList = getenv('activity.dailyReportEmails') ?: getenv('bds.dailyReportEmails') ?: '';
$recipientEmails = array_filter(array_map('trim', explode(',', $emailList)));
if (empty($recipientEmails)) {
$this->myLogger->logme('error', 'croneDailyActivityReport: No recipients configured (set activity.dailyReportEmails in .env).');
return $this->respond([
'status' => 'success',
'message' => 'Daily activity data prepared but no recipients configured.',
'data' => $data,
], 200);
}
$subject = "Daily Activity Report - {$today}";
$res = MailHelper::send_email([
'mail' => $recipientEmails,
'subject' => $subject,
'message' => $message,
]);
$resDecoded = is_string($res) ? json_decode($res, true) : $res;
if (isset($resDecoded['status']) && $resDecoded['status'] === 'success') {
$this->myLogger->logme('error', 'croneDailyActivityReport: Report email sent to ' . count($recipientEmails) . ' recipients');
return $this->respond([
'status' => true,
'message' => 'Daily activity report emailed successfully.',
'recipients' => count($recipientEmails),
], 200);
}
$this->myLogger->logme('error', 'croneDailyActivityReport: Email send failed - ' . json_encode($resDecoded));
return $this->respond([
'status' => false,
'message' => 'Daily activity data prepared but email send failed.',
'data' => $data,
], 500);
}
}

View File

@ -2586,61 +2586,90 @@ class EmployeeRestController extends AdminController
$required_docs = $this->ticketMaster->select('required_docs')->where('id', $ticket_id)->first();
$data['required_docs'] = json_decode($required_docs['required_docs'] ?? '{}', true) ?? [];
// $ticketData = $data['ticket_data'];
// $ticketHistory = $data['ticket_history'];
// print_r($ticketHistory); die;
// print_rr($data['ticket_history']); die;
$filteredArray = array_filter($data['ticket_history'], function($item) {
return $item['field_name'] == 'claim_status_id';
});
$filteredArray = array_reverse(array_values($filteredArray));
$currentClaimStatus = $this->claimStatusModel->select("claim_status")->where('id', $data['claims_data']['claim_status_id'])->where('is_active', 1)->first();
$ticketClaimStatus = $this->claimStatusModel->select('claim_status, display_name')->where('display_name is not null')->where('ticket_type', $data['claims_data']['ticket_type_id'])->where('is_active', 1)->findAll();
$status_list = array_column($ticketClaimStatus, 'display_name', 'claim_status');
// print_r($currentClaimStatus); die;
// dd($filteredArray, $status_list); die;
$data['ticket_data'] = array_fill_keys(array_keys($data['ticket_data']), []);
$filtered_history = [];
$counter = 0;
foreach ($filteredArray as $key => $value) {
foreach ($status_list as $status => $display_name) {
if ($value['new_value'] == $status) {
// Loop through ticket_data
foreach ($data['ticket_data'] as $status => &$fields) {
// Search ticket_history for matching old_status_value
foreach ($data['ticket_history'] as $history) {
if($display_name == 'Under Process'){
$unique_key = $display_name . str_repeat("\u{200B}", $counter++);
}else{
$unique_key = $display_name;
}
if ($history['old_status_value'] === $status) {
// Attach modified_by and created_at
// $fields['modified_by'] = $history['modified_by'];
$fields['modified_by'] = "";
$fields['modified_at'] = date('d-m-Y h:i A', strtotime($history['created_at']));
// Break after first match (assuming latest entry is enough)
break;
$filtered_history[$unique_key] = [
'modified_by' => "",
'modified_at' => date('d-m-Y h:i A', strtotime($value['created_at'])),
];
}
}
}
// dd($filteredArray, $status_list, $filtered_history); die;
$data['ticket_data'][$currentClaimStatus['claim_status']]['modified_by'] = "";
$data['ticket_data'][$currentClaimStatus['claim_status']]['modified_at'] = $formatted = date('d-m-Y h:i A', strtotime($data['claims_data']['updated_at']));
$new_ticket_data = [];
foreach ($data['ticket_data'] as $oldKey => $value) {
// $data['ticket_data'] = array_fill_keys(array_keys($data['ticket_data']), []);
// Only process if key exists in status_list
if (! isset($status_list[$oldKey])) {
continue; // skip and do NOT add to new array
}
// // Loop through ticket_data
// foreach ($data['ticket_data'] as $status => &$fields) {
// // Search ticket_history for matching old_status_value
// foreach ($data['ticket_history'] as $history) {
// Get new key based on mapping
$newKey = $status_list[$oldKey];
// if ($history['old_status_value'] === $status) {
// // Attach modified_by and created_at
// // $fields['modified_by'] = $history['modified_by'];
// $fields['modified_by'] = "";
// $fields['modified_at'] = date('d-m-Y h:i A', strtotime($history['created_at']));
// // Break after first match (assuming latest entry is enough)
// break;
// }
// }
// }
// Avoid duplicates
if (! isset($new_ticket_data[$newKey])) {
$new_ticket_data[$newKey] = $value;
}
}
// $data['ticket_data'][$currentClaimStatus['claim_status']]['modified_by'] = "";
// $data['ticket_data'][$currentClaimStatus['claim_status']]['modified_at'] = $formatted = date('d-m-Y h:i A', strtotime($data['claims_data']['updated_at']));
uasort($new_ticket_data, function ($a, $b) {
$timeA = \DateTime::createFromFormat('d-m-Y h:i A', $a['modified_at']);
$timeB = \DateTime::createFromFormat('d-m-Y h:i A', $b['modified_at']);
return $timeA <=> $timeB; // Ascending
});
// $new_ticket_data = [];
$data['ticket_data'] = $new_ticket_data;
// foreach ($data['ticket_data'] as $oldKey => $value) {
// // Only process if key exists in status_list
// if (! isset($status_list[$oldKey])) {
// continue; // skip and do NOT add to new array
// }
// // Get new key based on mapping
// $newKey = $status_list[$oldKey];
// // Avoid duplicates
// if (! isset($new_ticket_data[$newKey])) {
// $new_ticket_data[$newKey] = $value;
// }
// }
// uasort($new_ticket_data, function ($a, $b) {
// $timeA = \DateTime::createFromFormat('d-m-Y h:i A', $a['modified_at']);
// $timeB = \DateTime::createFromFormat('d-m-Y h:i A', $b['modified_at']);
// return $timeA <=> $timeB; // Ascending
// });
// $data['ticket_data'] = $new_ticket_data;
$data['ticket_data'] = $filtered_history;
$ticketMesssageModel = new TicketMessageModel();
$ticket_message = $ticketMesssageModel
@ -5456,7 +5485,7 @@ class EmployeeRestController extends AdminController
'dashboard' => $database_id,
],
'exp' => time() + (10 * 60),
'params' => (object) [],
'params' => (object) ['client_policy' => $policy_id ], // MUST be object for Metabase
];
$token = JWT::encode($payload, $METABASE_SECRET_KEY, 'HS256');

View File

@ -6121,9 +6121,9 @@ class PolicyTransactionController extends BaseController
$filePath = null;
try {
$today = date('Y-m-d');
$today = date('Y-m-d', strtotime('-1 day'));
$reportList = $this->policyTransactionModel->getBDSReportList($today, $today,0,0,0,'created_at',0,0,0,0,0,[]);
if (empty($reportList)) {
$this->myLogger->logme('error', "cronDailyBDSReport: No BDS records for {$today}");
return $this->respond(['status' => 'success', 'message' => 'No BDS records for today. No report sent.'], 200);
@ -6219,6 +6219,7 @@ class PolicyTransactionController extends BaseController
];
}
$today = date('d-m-Y', strtotime($today));
$fileName = 'BDS_Daily_Report_' . $today . '.xlsx';
$tmpDir = WRITEPATH . 'tmp' . DIRECTORY_SEPARATOR;
if (!is_dir($tmpDir)) {
@ -6244,8 +6245,8 @@ class PolicyTransactionController extends BaseController
], 200);
}
$subject = "Daily BDS Report - {$today}";
$message = "<p>Please find attached the daily BDS report for {$today}.</p>";
$subject = "BDS Report Up to - {$today}";
$message = "<p>Please find attached the BDS report up to {$today}.</p>";
$message .= "<p>Total records: " . count($reportList) . "</p>";
$attachments = [

View File

@ -1097,10 +1097,12 @@ class TestingController extends BaseController
'dashboard' => $database_id
],
'exp' => time() + (10 * 60), // 10 minutes
'params' => (object)[]
'params' => (object) ['client_policy' => $policy_id ], // MUST be object for Metabase
];
$token = JWT::encode($payload, $METABASE_SECRET_KEY, 'HS256');
// dd($token);
if ($this->request->getGet('api') == 1) {
return $this->respond([

View File

@ -1173,9 +1173,13 @@ class TicketController extends BaseController
'regex_match' => 'Policy Number can only contain letters, numbers, spaces, hyphens(-) underscores(_), and slashes(/).'
]
],
'tpa_no' => ['label' => 'TPA ID','rules' => 'permit_empty|regex_match[/^[a-zA-Z0-9]+$/]','errors' => [
'regex_match' => 'TPA ID can only contain letters and numbers.'
]],
'tpa_no' => [
'label' => 'TPA ID',
'rules' => 'permit_empty|regex_match[/^[a-zA-Z0-9\/]+$/]',
'errors' => [
'regex_match' => 'TPA ID can only contain letters, numbers, and /.'
]
],
'emp_mobile' => ['label' => 'Employee Mobile No','rules' => 'required|numeric|exact_length[10]',
'errors' => [
'required' => 'Mobile number is required',
@ -1522,9 +1526,13 @@ class TicketController extends BaseController
'regex_match' => 'Policy Number can only contain letters, numbers, spaces, hyphens(-) underscores(_), and slashes(/).'
]
],
'tpa_no' => ['label' => 'TPA ID','rules' => 'permit_empty|regex_match[/^[a-zA-Z0-9]+$/]','errors' => [
'regex_match' => 'TPA ID can only contain letters and numbers.'
]],
'tpa_no' => [
'label' => 'TPA ID',
'rules' => 'permit_empty|regex_match[/^[a-zA-Z0-9\/]+$/]',
'errors' => [
'regex_match' => 'TPA ID can only contain letters, numbers, and /.'
]
],
'emp_mobile' => ['label' => 'Employee Mobile No','rules' => 'required|numeric|exact_length[10]',
'errors' => [
'required' => 'Mobile number is required',

View File

@ -9,17 +9,30 @@ use App\Models\TicketMasterModel;
use App\Models\EmployeeModel;
use App\Models\ClaimDumpFileModel;
use App\Models\ClaimsDumpFhplModel;
use App\Models\ClientPolicyModel;
use RuntimeException;
abstract class BaseTpaClaimImportService
{
protected BaseConnection $db;
protected $claimDumpFileModel;
protected $clientPolicyModel;
protected $policyNumberMapping;
public function __construct()
{
$this->db = db_connect();
$this->claimDumpFileModel = new ClaimDumpFileModel();
$this->clientPolicyModel = new ClientPolicyModel();
$this->policyNumberMapping = [
(int) env('VIDAL_PRIMARY_KEY_CONSTANT') => 'Insurer Policy Number',
(int) env('ABHI_PRIMARY_KEY_CONSTANT') => 'Policy Number',
(int) env('MEDI_ASSIST_PRIMARY_KEY_CONSTANT') => 'policy_no',
(int) env('FHPL_PRIMARY_KEY_CONSTANT') => 'Policy No',
(int) env('R_CARE_PRIMARY_KEY_CONSTANT') => 'Policy Number',
(int) env('ICICI_PRIMARY_KEY_CONSTANT') => 'POLICY_NO',
];
}
/**
@ -33,6 +46,8 @@ abstract class BaseTpaClaimImportService
try {
$fileData = $this->claimDumpFileModel->where('id', $fileId)->first();
$client_policy_data = $this->clientPolicyModel->where('id', $fileData['client_policy_id'])->first();
// Determine sheet name logic...
if (env('FHPL_PRIMARY_KEY_CONSTANT') == $fileData['tpa_id']) {
$rows = $this->readExcelBySheetName($filePath, 'Claims&Preauth');
@ -47,6 +62,18 @@ abstract class BaseTpaClaimImportService
return ['status' => false, 'message' => 'Excel file contains no data or wrong file upload'];
}
if(isset($this->policyNumberMapping[$fileData['tpa_id']]) && !empty($this->policyNumberMapping[$fileData['tpa_id']])){
$policy_number_column = $this->policyNumberMapping[$fileData['tpa_id']];
}else{
$policy_number_column = 'policy_no';
}
if($client_policy_data['policy_no'] != ($rows[0][$policy_number_column] ?? '')){
$this->db->transRollback();
return ['status' => false, 'message' => 'Policy number mismatch in the file and in the system'];
}
$tpaInsertData = $this->mapTPAData($rows, $fileId);
if (empty($tpaInsertData)) {

View File

@ -3098,6 +3098,8 @@
if ($date_type === "policy_issue_date") {
$conditions .= " AND pcsd.pt_policy_issue_date >= '$startDate' ";
$conditions .= " AND pcsd.pt_policy_issue_date <= '$endDate' ";
} else if ($date_type === "created_at") {
$conditions .= " AND pt.created_at <= '$endDate' ";
} else {
$conditions .= " AND pt.$date_type >= '$startDate' ";
$conditions .= " AND pt.$date_type <= '$endDate' ";

View File

@ -0,0 +1,347 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
/* Base */
body {
font-family: 'Segoe UI', Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f4f7f6;
color: #333;
-webkit-text-size-adjust: 100%;
}
.container {
width: 100%;
max-width: 680px;
margin: 0 auto;
background: #ffffff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 4px 10px rgba(0,0,0,0.06);
}
/* Header */
.header {
background: linear-gradient(135deg, #1f618d, #21618c, #117a65);
color: #ffffff;
padding: 24px 16px;
text-align: center;
}
.header h1 {
margin: 0;
font-size: 24px;
letter-spacing: 0.5px;
}
.header-subtitle {
margin-top: 6px;
font-size: 13px;
opacity: 0.9;
}
/* Content */
.content {
padding: 20px;
}
.report-date {
color: #7f8c8d;
font-size: 13px;
margin-bottom: 16px;
text-align: right;
}
.section-title {
font-size: 17px;
color: #2c3e50;
border-bottom: 2px solid #3498db;
display: inline-block;
margin: 18px 0 12px;
padding-bottom: 4px;
}
/* Stats Grid - stacked for better email support */
.stats-grid {
margin-bottom: 18px;
}
.stat-card {
width: 100%;
display: block;
background: #f8f9fa;
padding: 12px 14px;
border-radius: 6px;
border-left: 4px solid #3498db;
box-sizing: border-box;
margin-bottom: 10px;
}
.stat-label {
font-size: 11px;
text-transform: uppercase;
color: #7f8c8d;
font-weight: 600;
letter-spacing: 0.5px;
}
.stat-value {
font-size: 18px;
color: #2c3e50;
margin-top: 4px;
font-weight: bold;
}
.stat-note {
font-size: 11px;
color: #95a5a6;
margin-top: 2px;
}
/* Table */
.table-container {
width: 100%;
}
.status-table {
width: 100%;
border-collapse: collapse;
margin-top: 8px;
}
.status-table th {
background-color: #ecf0f1;
text-align: left;
padding: 10px 8px;
font-size: 13px;
border-bottom: 2px solid #bdc3c7;
}
.status-table td {
padding: 10px 8px;
border-bottom: 1px solid #eee;
font-size: 13px;
}
.badge {
display: inline-block;
padding: 2px 8px;
border-radius: 10px;
font-size: 11px;
background: #ecf0f1;
color: #2c3e50;
}
/* Footer */
.footer {
background: #f8f9fa;
padding: 14px 18px;
text-align: center;
font-size: 11px;
color: #95a5a6;
}
/* Mobile */
@media only screen and (max-width: 480px) {
.content {
padding: 14px;
}
.header h1 {
font-size: 20px;
}
.header-subtitle {
font-size: 12px;
}
.section-title {
font-size: 15px;
}
.stat-card {
min-width: 100%;
}
.report-date {
text-align: left;
}
}
</style>
</head>
<body>
<div class="container" style="width:100%;max-width:680px;margin:0 auto;background:#ffffff;border-radius:8px;overflow:hidden;box-shadow:0 4px 10px rgba(0,0,0,0.06);">
<div class="header" style="background:#1f618d;color:#ffffff;padding:24px 16px;text-align:center;">
<h1>Daily Activity Report</h1>
<div class="header-subtitle">
Key operations, sales and claim metrics for the day
</div>
</div>
<div class="content" style="padding:20px;">
<div class="report-date" style="color:#7f8c8d;font-size:13px;margin-bottom:16px;text-align:right;">Date: <?= $today ?></div>
<!-- File Operations -->
<h3 class="section-title" style="font-size:17px;color:#2c3e50;border-bottom:2px solid #3498db;display:inline-block;margin:18px 0 12px;padding-bottom:4px;">Inception &amp; Endorsement (File Upload)</h3>
<div class="stats-grid">
<div class="stat-card" style="width:100%;display:block;background:#f8f9fa;padding:12px 14px;border-radius:6px;border-left:4px solid #3498db;box-sizing:border-box;margin-bottom:10px;">
<div class="stat-label">Total Inception</div>
<div class="stat-value"><?= $total_inception_count ?></div>
<div class="stat-note">Employee file uploads marked as inception</div>
</div>
<div class="stat-card" style="width:100%;display:block;background:#f8f9fa;padding:12px 14px;border-radius:6px;border-left:4px solid #3498db;box-sizing:border-box;margin-bottom:10px;">
<div class="stat-label">Total Endorsement</div>
<div class="stat-value"><?= $total_endorsement_count ?></div>
<div class="stat-note">All noninception successful uploads</div>
</div>
</div>
<!-- Employee Enrollment (new data points as cards only) -->
<h3 class="section-title" style="font-size:17px;color:#2c3e50;border-bottom:2px solid #3498db;display:inline-block;margin:18px 0 12px;padding-bottom:4px;">Employee Enrollment</h3>
<div class="stats-grid">
<div class="stat-card" style="width:100%;display:block;background:#f8f9fa;padding:12px 14px;border-radius:6px;border-left:4px solid #3498db;box-sizing:border-box;margin-bottom:10px;">
<div class="stat-label">Draft / Enrolled </div>
<div class="stat-value"><?= $total_employee_draft_count ?? 0 ?> / <?= $total_employee_enrolled_count ?? 0 ?></div>
<div class="stat-note">Employees in draft / enrolled status for the day</div>
</div>
<div class="stat-card" style="width:100%;display:block;background:#f8f9fa;padding:12px 14px;border-radius:6px;border-left:4px solid #9b59b6;box-sizing:border-box;margin-bottom:10px;">
<div class="stat-label">Open for Enrollment Policies</div>
<div class="stat-value"><?= $total_open_for_enrollemnt_policy_count ?? 0 ?></div>
<div class="stat-note">Policies currently open for enrollment</div>
</div>
</div>
<!-- TPA / Insurer -->
<h3 class="section-title" style="font-size:17px;color:#2c3e50;border-bottom:2px solid #3498db;display:inline-block;margin:18px 0 12px;padding-bottom:4px;">TPA &amp; Insurer Batch Summary</h3>
<div class="stats-grid">
<div class="stat-card" style="width:100%;display:block;background:#f8f9fa;padding:12px 14px;border-radius:6px;border-left:4px solid #e67e22;box-sizing:border-box;margin-bottom:10px;">
<div class="stat-label">TPA (Inception / Endorsement)</div>
<div class="stat-value"><?= $total_tpa_incetion_count ?> / <?= $total_tpa_endorsement_count ?></div>
<div class="stat-note">Successful TPA events</div>
</div>
<div class="stat-card" style="width:100%;display:block;background:#f8f9fa;padding:12px 14px;border-radius:6px;border-left:4px solid #9b59b6;box-sizing:border-box;margin-bottom:10px;">
<div class="stat-label">Insurer (Inception / Endorsement)</div>
<div class="stat-value"><?= $total_insurer_incetion_count ?> / <?= $total_insurer_endorsement_count ?></div>
<div class="stat-note">Successful insurer events</div>
</div>
</div>
<!-- Sales Funnel -->
<h3 class="section-title" style="font-size:17px;color:#2c3e50;border-bottom:2px solid #3498db;display:inline-block;margin:18px 0 12px;padding-bottom:4px;">Sales Funnel &amp; Leads</h3>
<div class="stats-grid">
<div class="stat-card" style="width:100%;display:block;background:#f8f9fa;padding:12px 14px;border-radius:6px;border-left:4px solid #27ae60;box-sizing:border-box;margin-bottom:10px;">
<div class="stat-label">Opportunities &amp; Won</div>
<div class="stat-value"><?= $total_opportunity_count ?> / <?= $total_placement_count ?></div>
<div class="stat-note">Total opportunities created vs converted</div>
</div>
<div class="stat-card" style="width:100%;display:block;background:#f8f9fa;padding:12px 14px;border-radius:6px;border-left:4px solid #16a085;box-sizing:border-box;margin-bottom:10px;">
<div class="stat-label">RFQ (Created / Sent to Insurer)</div>
<div class="stat-value"><?= $total_rfq_created_count ?> / <?= $total_rfq_insurer_send_count ?></div>
<div class="stat-note">Movement from opportunity to RFQ</div>
</div>
<div class="stat-card" style="width:100%;display:block;background:#f8f9fa;padding:12px 14px;border-radius:6px;border-left:4px solid #2980b9;box-sizing:border-box;margin-bottom:10px;">
<div class="stat-label">QCR (Created / Sent to Client)</div>
<div class="stat-value"><?= $total_qcr_created_count ?> / <?= $total_qcr_client_send_count ?></div>
<div class="stat-note">Quotes prepared and shared</div>
</div>
<div class="stat-card" style="width:100%;display:block;background:#f8f9fa;padding:12px 14px;border-radius:6px;border-left:4px solid #8e44ad;box-sizing:border-box;margin-bottom:10px;">
<div class="stat-label">Total Leads &amp; Activities</div>
<div class="stat-value"><?= $total_lead_count ?> / <?= $total_activity_count ?></div>
<div class="stat-note">Lead entries and logged touchpoints</div>
</div>
</div>
<!-- BDS / Policy Transactions -->
<h3 class="section-title" style="font-size:17px;color:#2c3e50;border-bottom:2px solid #3498db;display:inline-block;margin:18px 0 12px;padding-bottom:4px;">BDS Policy Transactions</h3>
<div class="stats-grid">
<div class="stat-card" style="width:100%;display:block;background:#f8f9fa;padding:12px 14px;border-radius:6px;border-left:4px solid #d35400;box-sizing:border-box;margin-bottom:10px;">
<div class="stat-label">Total BDS Transactions</div>
<div class="stat-value"><?= $total_bds_count ?></div>
<div class="stat-note">All policy transactions processed</div>
</div>
<div class="stat-card" style="width:100%;display:block;background:#f8f9fa;padding:12px 14px;border-radius:6px;border-left:4px solid #c0392b;box-sizing:border-box;margin-bottom:10px;">
<div class="stat-label">BDS (Policy / Endorsement)</div>
<div class="stat-value"><?= $total_bds_policy_wise_count ?> / <?= $total_bds_endorsement_wise_count ?></div>
<div class="stat-note">Split of inceptions vs endorsements</div>
</div>
</div>
<!-- Claims -->
<h3 class="section-title" style="font-size:17px;color:#2c3e50;border-bottom:2px solid #3498db;display:inline-block;margin:18px 0 12px;padding-bottom:4px;">Claims</h3>
<div class="stats-grid">
<div class="stat-card" style="width:100%;display:block;background:#f8f9fa;padding:12px 14px;border-radius:6px;border-left:4px solid #d35400;box-sizing:border-box;margin-bottom:10px;">
<div class="stat-label">Total Claims Registered for the day</div>
<div class="stat-value"><?= $total_claim_count ?></div>
<div class="stat-note"></div>
</div>
</div>
<!-- BDS by Policy Type -->
<h3 class="section-title" style="font-size:17px;color:#2c3e50;border-bottom:2px solid #3498db;display:inline-block;margin:18px 0 12px;padding-bottom:4px;">BDS by Policy Type</h3>
<div class="table-container" style="width:100%;">
<table class="status-table" style="width:100%;border-collapse:collapse;margin-top:8px;">
<thead>
<tr>
<th style="background-color:#ecf0f1;text-align:left;padding:10px 8px;font-size:13px;border-bottom:2px solid #bdc3c7;">Policy Type</th>
<th style="background-color:#ecf0f1;text-align:right;padding:10px 8px;font-size:13px;border-bottom:2px solid #bdc3c7;">Count</th>
</tr>
</thead>
<tbody>
<?php if (!empty($total_bds_policy_type_wise_count)): ?>
<?php foreach ($total_bds_policy_type_wise_count as $row): ?>
<tr>
<td style="padding:10px 8px;border-bottom:1px solid #eee;font-size:13px;">
<span class="badge" style="display:inline-block;padding:2px 8px;border-radius:10px;font-size:11px;background:#ecf0f1;color:#2c3e50;"><?= esc($row['policy_type']) ?></span>
</td>
<td style="padding:10px 8px;border-bottom:1px solid #eee;font-size:13px;text-align:right;font-weight:bold;"><?= $row['count'] ?></td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr>
<td colspan="2" style="padding:10px 8px;border-bottom:1px solid #eee;font-size:12px;text-align:center;color:#7f8c8d;">
No BDS activity recorded for today.
</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
<h3 class="section-title" style="font-size:17px;color:#2c3e50;border-bottom:2px solid #3498db;display:inline-block;margin:18px 0 12px;padding-bottom:4px;">Claim Status Breakdown</h3>
<div style="padding:10px 8px;border:1px solid #eee;border-radius:4px;font-size:12px;text-align:center;color:#7f8c8d;margin-top:8px;">
The total claims received so far are listed ticket type-wise.
</div>
<?php
$claimSections = [
'GMC Claims' => $total_gmc_status_wise_claim_count ?? [],
'GPA Claims' => $total_gpa_status_wise_claim_count ?? [],
'EDLI Claims' => $total_edli_status_wise_claim_count ?? [],
'GTLI Claims' => $total_gtli_status_wise_claim_count ?? [],
];
$hasAnyClaimData = false;
?>
<?php foreach ($claimSections as $sectionTitle => $rows): ?>
<?php if (!empty($rows)): ?>
<?php $hasAnyClaimData = true; ?>
<h4 style="font-size:14px;color:#34495e;margin:14px 0 6px;"><?= esc($sectionTitle) ?></h4>
<div class="table-container" style="width:100%;margin-bottom:10px;">
<table class="status-table" style="width:100%;border-collapse:collapse;margin-top:4px;">
<thead>
<tr>
<th style="background-color:#ecf0f1;text-align:left;padding:10px 8px;font-size:13px;border-bottom:2px solid #bdc3c7;">Status</th>
<th style="background-color:#ecf0f1;text-align:right;padding:10px 8px;font-size:13px;border-bottom:2px solid #bdc3c7;">Count</th>
</tr>
</thead>
<tbody>
<?php foreach ($rows as $row): ?>
<tr>
<td style="padding:10px 8px;border-bottom:1px solid #eee;font-size:13px;">
<span class="badge" style="display:inline-block;padding:2px 8px;border-radius:10px;font-size:11px;background:#ecf0f1;color:#2c3e50;"><?= esc($row['claim_status']) ?></span>
</td>
<td style="padding:10px 8px;border-bottom:1px solid #eee;font-size:13px;text-align:right;font-weight:bold;"><?= $row['count'] ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
<?php endforeach; ?>
</div>
<div class="footer" style="background:#f8f9fa;padding:14px 18px;text-align:center;font-size:11px;color:#95a5a6;">
This is an automated system generated report. Please do not reply to this email.
</div>
</div>
</body>
</html>