diff --git a/app/Commands/TestIciciStatusUpdate.php b/app/Commands/TestIciciStatusUpdate.php
new file mode 100644
index 00000000..8221514f
--- /dev/null
+++ b/app/Commands/TestIciciStatusUpdate.php
@@ -0,0 +1,413 @@
+ 'Optional claim_dump_files.id to process',
+ ];
+ protected $options = [
+ '--scenario' => 'Seed a controlled pending dump row for one existing ICICI ticket and test status update',
+ '--apply' => 'Actually run runTicketMasterInsert (default is map-only dry-run)',
+ '--new-status' => 'Dump status string to use in scenario (default: REJECTED)',
+ ];
+
+ public function run(array $params)
+ {
+ helper('utility_helper');
+
+ $db = db_connect();
+ $iciciTpaId = (int) env('ICICI_PRIMARY_KEY_CONSTANT');
+ $fileId = $this->resolveFileId($params);
+ $apply = $this->hasFlag('apply');
+ $scenario = $this->hasFlag('scenario');
+ $newStatus = $this->resolveOptionValue('new-status', 'REJECTED');
+
+ CLI::write("ICICI_PRIMARY_KEY_CONSTANT = {$iciciTpaId}", 'yellow');
+ CLI::write('Parsed args: file_id=' . $fileId . ', apply=' . ($apply ? 'yes' : 'no') . ', scenario=' . ($scenario ? 'yes' : 'no') . ', new_status=' . $newStatus, 'yellow');
+
+ if ($scenario) {
+ $fileId = $this->seedScenario($db, $iciciTpaId, $newStatus);
+ if ($fileId <= 0) {
+ return;
+ }
+ }
+
+ if ($fileId <= 0) {
+ $recent = $db->table('claim_dump_files')
+ ->select('id, tpa_id, client_id, client_policy_id, file_name, status, created_at')
+ ->where('tpa_id', $iciciTpaId)
+ ->orderBy('id', 'DESC')
+ ->limit(10)
+ ->get()
+ ->getResultArray();
+
+ CLI::write('No --file_id provided. Recent ICICI claim_dump_files:', 'cyan');
+ if (empty($recent)) {
+ CLI::error('No ICICI claim dump files found.');
+ $this->printMatchPreview($db, $iciciTpaId);
+ return;
+ }
+
+ foreach ($recent as $row) {
+ CLI::write(json_encode($row));
+ }
+
+ CLI::newLine();
+ CLI::write('Controlled scenario test:', 'green');
+ CLI::write(' php spark tpa:test-icici-status --scenario');
+ CLI::write(' php spark tpa:test-icici-status --scenario --apply');
+ CLI::write('Existing file (use positional file_id):');
+ CLI::write(' php spark tpa:test-icici-status 68');
+ CLI::write(' php spark tpa:test-icici-status 68 --apply');
+ $this->printMatchPreview($db, $iciciTpaId);
+ return;
+ }
+
+ $file = $db->table('claim_dump_files')->where('id', $fileId)->get()->getRowArray();
+ if (empty($file)) {
+ CLI::error("claim_dump_files id={$fileId} not found");
+ return;
+ }
+
+ CLI::write('File: ' . json_encode([
+ 'id' => $file['id'],
+ 'tpa_id' => $file['tpa_id'],
+ 'status' => $file['status'],
+ 'file_name' => $file['file_name'],
+ 'client_policy_id' => $file['client_policy_id'],
+ ]), 'cyan');
+
+ if ((int) $file['tpa_id'] !== $iciciTpaId) {
+ CLI::error("File tpa_id={$file['tpa_id']} is not ICICI ({$iciciTpaId}). Aborting.");
+ return;
+ }
+
+ $pendingDump = $db->table('claims_dump_icici')
+ ->where('file_id', $fileId)
+ ->where('is_active', 1)
+ ->where('ticket_id IS NULL', null, false)
+ ->where('master_reject_reason IS NULL', null, false)
+ ->countAllResults();
+
+ CLI::write("Pending dump rows for mapClaimMasterData: {$pendingDump}", 'yellow');
+
+ $service = new IciciClaimImportService();
+
+ if ($apply) {
+ CLI::write('APPLY mode: running runTicketMasterInsert...', 'light_red');
+
+ $pendingBefore = $db->table('claims_dump_icici')
+ ->select('id, ticket_id, master_reject_reason, updated_status, employee_member_id, uhid, claimed_amount, doa')
+ ->where('file_id', $fileId)
+ ->where('is_active', 1)
+ ->get()
+ ->getResultArray();
+ CLI::write('Dump rows BEFORE: ' . json_encode($pendingBefore, JSON_PRETTY_PRINT));
+
+ $result = $service->runTicketMasterInsert(['file_id' => $fileId]);
+ CLI::write('Result: ' . json_encode($result, JSON_PRETTY_PRINT));
+
+ $pendingAfter = $db->table('claims_dump_icici')
+ ->select('id, ticket_id, master_reject_reason, updated_status, employee_member_id, uhid, claimed_amount, doa')
+ ->where('file_id', $fileId)
+ ->where('is_active', 1)
+ ->get()
+ ->getResultArray();
+ CLI::write('Dump rows AFTER: ' . json_encode($pendingAfter, JSON_PRETTY_PRINT));
+
+ $ticketIds = array_values(array_filter(array_column($pendingAfter, 'ticket_id')));
+ if (!empty($ticketIds)) {
+ $ticketsAfter = $db->table('ticket_master')
+ ->select('id, claim_status_id, claim_dump_ref_id, emp_code, tpa_no, claim_amount, doa')
+ ->whereIn('id', $ticketIds)
+ ->get()
+ ->getResultArray();
+ CLI::write('Linked tickets AFTER: ' . json_encode($ticketsAfter, JSON_PRETTY_PRINT));
+ }
+
+ return;
+ }
+
+ CLI::write('DRY-RUN mode: calling mapClaimMasterData only (no DB writes)...', 'green');
+
+ $ref = new \ReflectionClass($service);
+ $method = $ref->getMethod('mapClaimMasterData');
+ $method->setAccessible(true);
+ $mapped = $method->invoke($service, $fileId);
+
+ if (empty($mapped['status'])) {
+ CLI::error('mapClaimMasterData failed: ' . ($mapped['message'] ?? 'unknown'));
+ if (!empty($mapped['error_data'])) {
+ CLI::write(json_encode($mapped['error_data'], JSON_PRETTY_PRINT));
+ }
+ return;
+ }
+
+ $inserts = $mapped['mapped_array'] ?? [];
+ $rejects = $mapped['rejected_reason_array'] ?? [];
+ $updates = $mapped['status_update_array'] ?? [];
+
+ CLI::newLine();
+ CLI::write('=== RESULT COUNTS ===', 'yellow');
+ CLI::write('New tickets to insert : ' . count($inserts));
+ CLI::write('Status updates (existing) : ' . count($updates));
+ CLI::write('Rejected / skipped rows : ' . count($rejects));
+
+ CLI::newLine();
+ CLI::write('=== STATUS UPDATE ARRAY ===', 'cyan');
+ CLI::write(empty($updates) ? '(none)' : json_encode($updates, JSON_PRETTY_PRINT));
+
+ CLI::newLine();
+ CLI::write('=== REJECT / SKIP REASONS (first 20) ===', 'cyan');
+ CLI::write(json_encode(array_slice($rejects, 0, 20), JSON_PRETTY_PRINT));
+
+ if (!empty($updates)) {
+ CLI::newLine();
+ CLI::write('Ticket fields BEFORE update:', 'yellow');
+ $ids = array_column($updates, 'id');
+ $before = $db->table('ticket_master')
+ ->select('id, emp_code, tpa_no, claim_amount, doa, claim_status_id, claim_dump_ref_id, file_id')
+ ->whereIn('id', $ids)
+ ->get()
+ ->getResultArray();
+ CLI::write(json_encode($before, JSON_PRETTY_PRINT));
+ }
+
+ CLI::newLine();
+ CLI::write('To apply for real:', 'green');
+ CLI::write(" php spark tpa:test-icici-status {$fileId} --apply");
+ }
+
+ private function resolveFileId(array $params): int
+ {
+ if (!empty($params['file_id'])) {
+ return (int) $params['file_id'];
+ }
+ if (!empty($params[0]) && is_numeric($params[0])) {
+ return (int) $params[0];
+ }
+
+ // Fallback for --file_id=68 / --file_id 68 (CI option parsing can miss these)
+ $argv = $_SERVER['argv'] ?? [];
+ foreach ($argv as $i => $arg) {
+ if (preg_match('/^--file[_-]id=(.+)$/', (string) $arg, $m)) {
+ return (int) $m[1];
+ }
+ if (in_array($arg, ['--file_id', '--file-id'], true) && isset($argv[$i + 1])) {
+ return (int) $argv[$i + 1];
+ }
+ }
+
+ $opt = CLI::getOption('file_id') ?? CLI::getOption('file-id');
+ return (int) ($opt ?? 0);
+ }
+
+ private function hasFlag(string $name): bool
+ {
+ if (CLI::getOption($name) !== null) {
+ return true;
+ }
+
+ $argv = $_SERVER['argv'] ?? [];
+ return in_array('--' . $name, $argv, true);
+ }
+
+ private function resolveOptionValue(string $name, string $default): string
+ {
+ $opt = CLI::getOption($name);
+ if (is_string($opt) && $opt !== '') {
+ return $opt;
+ }
+
+ $argv = $_SERVER['argv'] ?? [];
+ foreach ($argv as $i => $arg) {
+ if (preg_match('/^--' . preg_quote($name, '/') . '=(.+)$/', (string) $arg, $m)) {
+ return trim($m[1]);
+ }
+ if ($arg === '--' . $name && isset($argv[$i + 1]) && strpos((string) $argv[$i + 1], '--') !== 0) {
+ return (string) $argv[$i + 1];
+ }
+ }
+
+ return $default;
+ }
+
+ /**
+ * Create a temporary claim_dump_files + one pending claims_dump_icici row
+ * matching an existing ticket, with a different dump status.
+ */
+ private function seedScenario($db, int $iciciTpaId, string $newStatus): int
+ {
+ CLI::write("Seeding controlled ICICI status-update scenario (new_status={$newStatus})...", 'cyan');
+
+ $ticket = $db->table('ticket_master')
+ ->select('id, client_id, client_policy_id, emp_code, tpa_no, claim_amount, doa, claim_status_id, claim_dump_ref_id, tpa_id')
+ ->where('tpa_id', $iciciTpaId)
+ ->where('is_active', 1)
+ ->where('emp_code IS NOT NULL', null, false)
+ ->where('tpa_no IS NOT NULL', null, false)
+ ->where('claim_amount IS NOT NULL', null, false)
+ ->where('doa IS NOT NULL', null, false)
+ ->orderBy('id', 'DESC')
+ ->get()
+ ->getRowArray();
+
+ if (empty($ticket)) {
+ // Fall back to any ticket, then override tpa matching by using that ticket's keys
+ $ticket = $db->table('ticket_master')
+ ->select('id, client_id, client_policy_id, emp_code, tpa_no, claim_amount, doa, claim_status_id, claim_dump_ref_id, tpa_id')
+ ->where('is_active', 1)
+ ->where('claim_created_by', 'DUMP_TPA')
+ ->where('emp_code IS NOT NULL', null, false)
+ ->where('tpa_no IS NOT NULL', null, false)
+ ->where('claim_amount IS NOT NULL', null, false)
+ ->where('doa IS NOT NULL', null, false)
+ ->orderBy('id', 'DESC')
+ ->get()
+ ->getRowArray();
+ }
+
+ if (empty($ticket)) {
+ CLI::error('No suitable existing ticket found to seed a status-update scenario.');
+ return 0;
+ }
+
+ CLI::write('Using existing ticket: ' . json_encode([
+ 'id' => $ticket['id'],
+ 'emp_code' => $ticket['emp_code'],
+ 'tpa_no' => $ticket['tpa_no'],
+ 'claim_amount' => $ticket['claim_amount'],
+ 'doa' => $ticket['doa'],
+ 'claim_status_id' => $ticket['claim_status_id'],
+ 'claim_dump_ref_id' => $ticket['claim_dump_ref_id'] ?? null,
+ 'tpa_id' => $ticket['tpa_id'],
+ ]), 'yellow');
+
+ // Clear stale claim_dump_ref_id so the scenario can re-test link backfill.
+ if (!empty($ticket['claim_dump_ref_id'])) {
+ $db->table('ticket_master')->where('id', $ticket['id'])->update([
+ 'claim_dump_ref_id' => null,
+ ]);
+ $ticket['claim_dump_ref_id'] = null;
+ CLI::write('Cleared stale ticket.claim_dump_ref_id for retest.', 'yellow');
+ }
+
+ // Ensure a physical file exists for resolveTpaClaimDumpFile if --apply uses controller later
+ $uploadDir = WRITEPATH . 'uploads' . DIRECTORY_SEPARATOR . 'claim_dump_excel' . DIRECTORY_SEPARATOR;
+ if (!is_dir($uploadDir)) {
+ mkdir($uploadDir, 0775, true);
+ }
+ $fileName = 'icici_status_test_' . date('Ymd_His') . '.xlsx';
+ $filePath = $uploadDir . $fileName;
+ if (!is_file($filePath)) {
+ file_put_contents($filePath, 'placeholder');
+ }
+
+ $fileInsert = [
+ 'tpa_id' => $iciciTpaId,
+ 'client_id' => $ticket['client_id'],
+ 'client_policy_id' => $ticket['client_policy_id'],
+ 'file_name' => $fileName,
+ 'status' => 'pending',
+ 'created_by' => 1,
+ 'created_at' => date('Y-m-d H:i:s'),
+ 'is_active' => 1,
+ ];
+
+ // claim_dump_files may have different nullable columns; insert only known-safe ones
+ $fileCols = array_column($db->query('SHOW COLUMNS FROM claim_dump_files')->getResultArray(), 'Field');
+ $fileInsert = array_intersect_key($fileInsert, array_flip($fileCols));
+
+ $db->table('claim_dump_files')->insert($fileInsert);
+ $fileId = (int) $db->insertID();
+ if ($fileId <= 0) {
+ CLI::error('Failed to create claim_dump_files row for scenario.');
+ return 0;
+ }
+
+ $dumpInsert = [
+ 'client_id' => $ticket['client_id'],
+ 'client_policy_id' => $ticket['client_policy_id'],
+ 'file_id' => $fileId,
+ 'employee_member_id' => $ticket['emp_code'],
+ 'uhid' => $ticket['tpa_no'],
+ 'claimed_amount' => $ticket['claim_amount'],
+ 'doa' => $ticket['doa'],
+ 'updated_status' => $newStatus,
+ 'relation' => 'SELF',
+ 'is_active' => 1,
+ 'created_by' => 1,
+ 'created_at' => date('Y-m-d H:i:s'),
+ 'ticket_id' => null,
+ 'master_reject_reason' => null,
+ ];
+
+ $dumpCols = array_column($db->query('SHOW COLUMNS FROM claims_dump_icici')->getResultArray(), 'Field');
+ $dumpInsert = array_intersect_key($dumpInsert, array_flip($dumpCols));
+
+ $db->table('claims_dump_icici')->insert($dumpInsert);
+ $dumpId = (int) $db->insertID();
+
+ CLI::write("Seeded file_id={$fileId}, dump_id={$dumpId}", 'green');
+ CLI::write("Expected: if ticket claim_status_id ({$ticket['claim_status_id']}) != mapped REJECTED(8)/chosen status, status_update_array should contain ticket {$ticket['id']}", 'green');
+
+ return $fileId;
+ }
+
+ private function printMatchPreview($db, int $iciciTpaId): void
+ {
+ CLI::newLine();
+ CLI::write('Preview: dump rows that match existing tickets (possible status updates)', 'cyan');
+
+ $sql = "
+ SELECT
+ cd.id AS dump_id,
+ cd.file_id,
+ cd.employee_member_id,
+ cd.uhid,
+ cd.claimed_amount,
+ cd.doa,
+ cd.updated_status AS dump_status,
+ tm.id AS ticket_id,
+ tm.claim_status_id AS current_status_id
+ FROM claims_dump_icici cd
+ INNER JOIN ticket_master tm
+ ON tm.is_active = 1
+ AND tm.emp_code = cd.employee_member_id
+ AND tm.tpa_no = cd.uhid
+ AND tm.claim_amount = cd.claimed_amount
+ AND tm.doa = cd.doa
+ WHERE cd.is_active = 1
+ AND tm.tpa_id = ?
+ ORDER BY cd.id DESC
+ LIMIT 10
+ ";
+
+ $rows = $db->query($sql, [$iciciTpaId])->getResultArray();
+ if (empty($rows)) {
+ CLI::write('No overlapping dump/ticket pairs found.');
+ return;
+ }
+
+ CLI::write(json_encode($rows, JSON_PRETTY_PRINT));
+ }
+}
diff --git a/app/Commands/TestTpaStatusUpdate.php b/app/Commands/TestTpaStatusUpdate.php
new file mode 100644
index 00000000..6dc61edc
--- /dev/null
+++ b/app/Commands/TestTpaStatusUpdate.php
@@ -0,0 +1,524 @@
+ 'Optional claim_dump_files.id to process',
+ ];
+ protected $options = [
+ '--tpa' => 'TPA key: icici|abhi|mediassist|fhpl|rcare|vidal|all (default: all for --scenario)',
+ '--scenario' => 'Seed one pending dump row matching an existing ticket',
+ '--apply' => 'Actually run runTicketMasterInsert (default is map-only dry-run)',
+ '--new-status' => 'Dump status string for scenario (defaults per TPA)',
+ ];
+
+ /**
+ * Per-TPA dump column mapping used to seed scenario rows.
+ */
+ private function tpaConfigs(): array
+ {
+ return [
+ 'icici' => [
+ 'env' => 'ICICI_PRIMARY_KEY_CONSTANT',
+ 'table' => 'claims_dump_icici',
+ 'status_column' => 'updated_status',
+ 'default_status'=> 'REJECTED',
+ 'same_status' => 'PAID',
+ 'dump_to_ticket'=> [
+ 'employee_member_id' => 'emp_code',
+ 'uhid' => 'tpa_no',
+ 'claimed_amount' => 'claim_amount',
+ 'doa' => 'doa',
+ ],
+ 'extra_dump' => [
+ 'relation' => 'SELF',
+ ],
+ ],
+ 'abhi' => [
+ 'env' => 'ABHI_PRIMARY_KEY_CONSTANT',
+ 'table' => 'claims_dump_abhi',
+ 'status_column' => 'claim_status',
+ 'default_status'=> 'Rejected',
+ 'same_status' => 'Settled',
+ 'dump_to_ticket'=> [
+ 'member_code' => 'emp_code',
+ 'healthcard_id' => 'tpa_no',
+ 'claimed_amount' => 'claim_amount',
+ 'doa' => 'doa',
+ ],
+ 'extra_dump' => [
+ 'relation' => 'SELF',
+ ],
+ ],
+ 'mediassist' => [
+ 'env' => 'MEDI_ASSIST_PRIMARY_KEY_CONSTANT',
+ 'table' => 'claims_dump_medi_assist',
+ 'status_column' => 'claim_status',
+ 'default_status'=> 'Rejected',
+ 'same_status' => 'Settled',
+ 'dump_to_ticket'=> [
+ 'pribenef_employee_code' => 'emp_code',
+ 'event_id' => 'tpa_no',
+ 'claim_amount' => 'claim_amount',
+ 'date_of_admission' => 'doa',
+ ],
+ 'extra_dump' => [
+ 'benef_relation' => 'SELF',
+ ],
+ ],
+ 'fhpl' => [
+ 'env' => 'FHPL_PRIMARY_KEY_CONSTANT',
+ 'table' => 'claims_dump_fhpl',
+ 'status_column' => 'current_claim_status',
+ 'default_status'=> 'Rejected',
+ 'same_status' => 'Settled',
+ 'dump_to_ticket'=> [
+ 'employee_id' => 'emp_code',
+ 'uhid_no' => 'tpa_no',
+ 'claim_amount' => 'claim_amount',
+ 'admission_date' => 'doa',
+ ],
+ 'extra_dump' => [
+ 'relationship' => 'SELF',
+ ],
+ ],
+ 'rcare' => [
+ 'env' => 'R_CARE_PRIMARY_KEY_CONSTANT',
+ 'table' => 'claims_dump_reliance',
+ 'status_column' => 'final_status',
+ 'default_status'=> 'Rejected',
+ 'same_status' => 'Settled',
+ 'dump_to_ticket'=> [
+ 'employee_member_id' => 'emp_code',
+ 'uhid' => 'tpa_no',
+ 'claimed_amount' => 'claim_amount',
+ 'doa_opd_treatment_from' => 'doa',
+ ],
+ 'extra_dump' => [
+ 'relation' => 'SELF',
+ ],
+ ],
+ 'vidal' => [
+ 'env' => 'VIDAL_PRIMARY_KEY_CONSTANT',
+ 'table' => 'claims_dump_vidal',
+ 'status_column' => 'claim_status',
+ 'default_status'=> 'Rejected',
+ 'same_status' => 'Settled',
+ 'dump_to_ticket'=> [
+ 'employee_number' => 'emp_code',
+ 'primary_policy_holder_card_id' => 'tpa_no',
+ 'claim_amount' => 'claim_amount',
+ 'date_of_admission' => 'doa',
+ ],
+ 'extra_dump' => [
+ 'relation' => 'SELF',
+ ],
+ ],
+ ];
+ }
+
+ public function run(array $params)
+ {
+ helper('utility_helper');
+
+ $db = db_connect();
+ $apply = $this->hasFlag('apply');
+ $scenario = $this->hasFlag('scenario');
+ $tpaOpt = strtolower((string) ($this->resolveOptionValue('tpa', '') ?: (CLI::getOption('tpa') ?? '')));
+ $fileId = $this->resolveFileId($params);
+ $newStatusOverride = $this->resolveOptionValue('new-status', '');
+
+ $configs = $this->tpaConfigs();
+
+ // Resolve which TPAs to run
+ if ($tpaOpt === '' || $tpaOpt === 'all') {
+ $selected = array_keys($configs);
+ if (!$scenario && $fileId <= 0) {
+ $this->printUsage($configs);
+ return;
+ }
+ } elseif (isset($configs[$tpaOpt])) {
+ $selected = [$tpaOpt];
+ } else {
+ CLI::error("Unknown --tpa={$tpaOpt}. Use: " . implode('|', array_keys($configs)) . '|all');
+ return;
+ }
+
+ foreach ($selected as $tpaKey) {
+ CLI::newLine();
+ CLI::write(str_repeat('=', 60), 'yellow');
+ CLI::write('TPA: ' . strtoupper($tpaKey), 'yellow');
+ CLI::write(str_repeat('=', 60), 'yellow');
+
+ try {
+ $this->runForTpa(
+ $db,
+ $tpaKey,
+ $configs[$tpaKey],
+ $scenario,
+ $apply,
+ $fileId,
+ $newStatusOverride
+ );
+ } catch (\Throwable $e) {
+ CLI::error("[{$tpaKey}] " . $e->getMessage());
+ }
+ }
+ }
+
+ private function runForTpa(
+ $db,
+ string $tpaKey,
+ array $cfg,
+ bool $scenario,
+ bool $apply,
+ int $fileId,
+ string $newStatusOverride
+ ): void {
+ $tpaId = (int) env($cfg['env']);
+ CLI::write("{$cfg['env']} = {$tpaId}", 'cyan');
+ CLI::write("table={$cfg['table']}, status_column={$cfg['status_column']}", 'cyan');
+
+ if (!$this->tableExists($db, $cfg['table'])) {
+ CLI::error("Table {$cfg['table']} does not exist. Skipping.");
+ return;
+ }
+
+ $newStatus = $newStatusOverride !== '' ? $newStatusOverride : $cfg['default_status'];
+ $currentFileId = $fileId;
+
+ if ($scenario) {
+ $currentFileId = $this->seedScenario($db, $tpaKey, $cfg, $tpaId, $newStatus);
+ if ($currentFileId <= 0) {
+ return;
+ }
+ }
+
+ if ($currentFileId <= 0) {
+ $this->listRecentFiles($db, $tpaId, $tpaKey);
+ return;
+ }
+
+ $file = $db->table('claim_dump_files')->where('id', $currentFileId)->get()->getRowArray();
+ if (empty($file)) {
+ CLI::error("claim_dump_files id={$currentFileId} not found");
+ return;
+ }
+
+ CLI::write('File: ' . json_encode([
+ 'id' => $file['id'],
+ 'tpa_id' => $file['tpa_id'],
+ 'status' => $file['status'],
+ 'file_name' => $file['file_name'],
+ 'client_policy_id' => $file['client_policy_id'],
+ ]));
+
+ if ((int) $file['tpa_id'] !== $tpaId) {
+ CLI::error("File tpa_id={$file['tpa_id']} does not match {$tpaKey} ({$tpaId}). Skipping.");
+ return;
+ }
+
+ $pending = $db->table($cfg['table'])
+ ->where('file_id', $currentFileId)
+ ->where('is_active', 1)
+ ->where('ticket_id IS NULL', null, false)
+ ->where('master_reject_reason IS NULL', null, false)
+ ->countAllResults();
+ CLI::write("Pending dump rows: {$pending}");
+
+ $service = TpaClaimsImportFactory::make($tpaId);
+
+ if ($apply) {
+ CLI::write('APPLY mode...', 'light_red');
+
+ $beforeDump = $db->table($cfg['table'])
+ ->select($this->dumpSelectColumns($cfg))
+ ->where('file_id', $currentFileId)
+ ->where('is_active', 1)
+ ->get()->getResultArray();
+ CLI::write('Dump BEFORE: ' . json_encode($beforeDump, JSON_PRETTY_PRINT));
+
+ $result = $service->runTicketMasterInsert(['file_id' => $currentFileId]);
+ CLI::write('Result: ' . json_encode($result, JSON_PRETTY_PRINT));
+
+ $afterDump = $db->table($cfg['table'])
+ ->select($this->dumpSelectColumns($cfg))
+ ->where('file_id', $currentFileId)
+ ->where('is_active', 1)
+ ->get()->getResultArray();
+ CLI::write('Dump AFTER: ' . json_encode($afterDump, JSON_PRETTY_PRINT));
+
+ $ticketIds = array_values(array_filter(array_column($afterDump, 'ticket_id')));
+ if (!empty($ticketIds)) {
+ $tickets = $db->table('ticket_master')
+ ->select('id, claim_status_id, claim_dump_ref_id, emp_code, tpa_no, claim_amount, doa')
+ ->whereIn('id', $ticketIds)
+ ->get()->getResultArray();
+ CLI::write('Tickets AFTER: ' . json_encode($tickets, JSON_PRETTY_PRINT));
+ }
+ return;
+ }
+
+ CLI::write('DRY-RUN mode (mapClaimMasterData only)...', 'green');
+ $ref = new \ReflectionClass($service);
+ $method = $ref->getMethod('mapClaimMasterData');
+ $method->setAccessible(true);
+ $mapped = $method->invoke($service, $currentFileId);
+
+ if (empty($mapped['status'])) {
+ CLI::write('mapClaimMasterData: ' . ($mapped['message'] ?? 'failed'));
+ if (!empty($mapped['already_processed'])) {
+ CLI::write('(already processed — dump rows were NOT deleted)', 'green');
+ }
+ return;
+ }
+
+ $inserts = $mapped['mapped_array'] ?? [];
+ $rejects = $mapped['rejected_reason_array'] ?? [];
+ $updates = $mapped['status_update_array'] ?? [];
+
+ CLI::write('inserts=' . count($inserts) . ' updates=' . count($updates) . ' rejects=' . count($rejects));
+ CLI::write('status_update_array: ' . (empty($updates) ? '(none)' : json_encode($updates, JSON_PRETTY_PRINT)));
+ CLI::write('rejected_reason_array: ' . json_encode(array_slice($rejects, 0, 10), JSON_PRETTY_PRINT));
+
+ if (!empty($updates)) {
+ $ids = array_column($updates, 'id');
+ $before = $db->table('ticket_master')
+ ->select('id, emp_code, tpa_no, claim_amount, doa, claim_status_id, claim_dump_ref_id')
+ ->whereIn('id', $ids)
+ ->get()->getResultArray();
+ CLI::write('Tickets BEFORE: ' . json_encode($before, JSON_PRETTY_PRINT));
+ }
+
+ CLI::write("To apply: php spark tpa:test-status --tpa={$tpaKey} {$currentFileId} --apply", 'green');
+ }
+
+ private function seedScenario($db, string $tpaKey, array $cfg, int $tpaId, string $newStatus): int
+ {
+ CLI::write("Seeding scenario for {$tpaKey} (new_status={$newStatus})...", 'cyan');
+
+ $ticket = $db->table('ticket_master')
+ ->select('id, client_id, client_policy_id, emp_code, tpa_no, claim_amount, doa, claim_status_id, claim_dump_ref_id, tpa_id')
+ ->where('tpa_id', $tpaId)
+ ->where('is_active', 1)
+ ->where('emp_code IS NOT NULL', null, false)
+ ->where('tpa_no IS NOT NULL', null, false)
+ ->where('claim_amount IS NOT NULL', null, false)
+ ->where('doa IS NOT NULL', null, false)
+ ->orderBy('id', 'DESC')
+ ->get()->getRowArray();
+
+ if (empty($ticket)) {
+ // Fall back: any ticket with identity keys (still allows match by doa/emp/amount/tpa_no)
+ $ticket = $db->table('ticket_master')
+ ->select('id, client_id, client_policy_id, emp_code, tpa_no, claim_amount, doa, claim_status_id, claim_dump_ref_id, tpa_id')
+ ->where('is_active', 1)
+ ->where('emp_code IS NOT NULL', null, false)
+ ->where('tpa_no IS NOT NULL', null, false)
+ ->where('claim_amount IS NOT NULL', null, false)
+ ->where('doa IS NOT NULL', null, false)
+ ->orderBy('id', 'DESC')
+ ->get()->getRowArray();
+ }
+
+ if (empty($ticket)) {
+ CLI::error("[{$tpaKey}] No suitable existing ticket found to seed.");
+ return 0;
+ }
+
+ CLI::write('Using ticket: ' . json_encode([
+ 'id' => $ticket['id'],
+ 'emp_code' => $ticket['emp_code'],
+ 'tpa_no' => $ticket['tpa_no'],
+ 'claim_amount' => $ticket['claim_amount'],
+ 'doa' => $ticket['doa'],
+ 'claim_status_id' => $ticket['claim_status_id'],
+ 'claim_dump_ref_id' => $ticket['claim_dump_ref_id'],
+ 'tpa_id' => $ticket['tpa_id'],
+ ]));
+
+ if (!empty($ticket['claim_dump_ref_id'])) {
+ $db->table('ticket_master')->where('id', $ticket['id'])->update(['claim_dump_ref_id' => null]);
+ CLI::write('Cleared stale ticket.claim_dump_ref_id for retest.', 'yellow');
+ }
+
+ $uploadDir = WRITEPATH . 'uploads' . DIRECTORY_SEPARATOR . 'claim_dump_excel' . DIRECTORY_SEPARATOR;
+ if (!is_dir($uploadDir)) {
+ mkdir($uploadDir, 0775, true);
+ }
+ $fileName = "{$tpaKey}_status_test_" . date('Ymd_His') . '.xlsx';
+ file_put_contents($uploadDir . $fileName, 'placeholder');
+
+ $fileInsert = [
+ 'tpa_id' => $tpaId,
+ 'client_id' => $ticket['client_id'],
+ 'client_policy_id' => $ticket['client_policy_id'],
+ 'file_name' => $fileName,
+ 'status' => 'pending',
+ 'created_by' => 1,
+ 'created_at' => date('Y-m-d H:i:s'),
+ 'is_active' => 1,
+ ];
+ $fileCols = array_column($db->query('SHOW COLUMNS FROM claim_dump_files')->getResultArray(), 'Field');
+ $fileInsert = array_intersect_key($fileInsert, array_flip($fileCols));
+ $db->table('claim_dump_files')->insert($fileInsert);
+ $fileId = (int) $db->insertID();
+ if ($fileId <= 0) {
+ CLI::error("[{$tpaKey}] Failed to create claim_dump_files row.");
+ return 0;
+ }
+
+ $dumpInsert = [
+ 'client_id' => $ticket['client_id'],
+ 'client_policy_id' => $ticket['client_policy_id'],
+ 'file_id' => $fileId,
+ 'is_active' => 1,
+ 'created_by' => 1,
+ 'created_at' => date('Y-m-d H:i:s'),
+ 'ticket_id' => null,
+ 'master_reject_reason' => null,
+ $cfg['status_column'] => $newStatus,
+ ];
+
+ foreach ($cfg['dump_to_ticket'] as $dumpCol => $ticketCol) {
+ $dumpInsert[$dumpCol] = $ticket[$ticketCol] ?? null;
+ }
+ foreach ($cfg['extra_dump'] as $col => $val) {
+ $dumpInsert[$col] = $val;
+ }
+
+ $dumpCols = array_column($db->query('SHOW COLUMNS FROM ' . $cfg['table'])->getResultArray(), 'Field');
+ $dumpInsert = array_intersect_key($dumpInsert, array_flip($dumpCols));
+
+ $db->table($cfg['table'])->insert($dumpInsert);
+ $dumpId = (int) $db->insertID();
+
+ CLI::write("Seeded file_id={$fileId}, dump_id={$dumpId}", 'green');
+ return $fileId;
+ }
+
+ private function dumpSelectColumns(array $cfg): string
+ {
+ $cols = ['id', 'ticket_id', 'master_reject_reason', 'file_id', $cfg['status_column']];
+ foreach (array_keys($cfg['dump_to_ticket']) as $col) {
+ $cols[] = $col;
+ }
+ return implode(', ', array_unique($cols));
+ }
+
+ private function listRecentFiles($db, int $tpaId, string $tpaKey): void
+ {
+ $recent = $db->table('claim_dump_files')
+ ->select('id, tpa_id, client_id, client_policy_id, file_name, status, created_at')
+ ->where('tpa_id', $tpaId)
+ ->orderBy('id', 'DESC')
+ ->limit(5)
+ ->get()->getResultArray();
+
+ CLI::write("Recent {$tpaKey} claim_dump_files:");
+ if (empty($recent)) {
+ CLI::write('(none)');
+ } else {
+ foreach ($recent as $row) {
+ CLI::write(json_encode($row));
+ }
+ }
+ CLI::write("Seed: php spark tpa:test-status --tpa={$tpaKey} --scenario", 'green');
+ CLI::write("Apply: php spark tpa:test-status --tpa={$tpaKey} --scenario --apply", 'green');
+ }
+
+ private function printUsage(array $configs): void
+ {
+ CLI::write('Test existing-ticket status/link update for TPA claim dumps.', 'cyan');
+ CLI::newLine();
+ CLI::write('Dry-run all TPAs (seed scenario, no DB ticket update):');
+ CLI::write(' php spark tpa:test-status --tpa=all --scenario');
+ CLI::newLine();
+ CLI::write('Apply all TPAs (writes to DB):');
+ CLI::write(' php spark tpa:test-status --tpa=all --scenario --apply');
+ CLI::newLine();
+ CLI::write('Single TPA:');
+ foreach (array_keys($configs) as $key) {
+ CLI::write(" php spark tpa:test-status --tpa={$key} --scenario");
+ CLI::write(" php spark tpa:test-status --tpa={$key} --scenario --apply");
+ }
+ CLI::newLine();
+ CLI::write('Same-status (no status change, only null-link fill):');
+ CLI::write(' php spark tpa:test-status --tpa=abhi --scenario --new-status Settled');
+ }
+
+ private function tableExists($db, string $table): bool
+ {
+ return !empty($db->query("SHOW TABLES LIKE " . $db->escape($table))->getResultArray());
+ }
+
+ private function resolveFileId(array $params): int
+ {
+ if (!empty($params['file_id'])) {
+ return (int) $params['file_id'];
+ }
+ if (!empty($params[0]) && is_numeric($params[0])) {
+ return (int) $params[0];
+ }
+
+ $argv = $_SERVER['argv'] ?? [];
+ foreach ($argv as $i => $arg) {
+ if (preg_match('/^--file[_-]id=(.+)$/', (string) $arg, $m)) {
+ return (int) $m[1];
+ }
+ if (in_array($arg, ['--file_id', '--file-id'], true) && isset($argv[$i + 1])) {
+ return (int) $argv[$i + 1];
+ }
+ }
+
+ return (int) (CLI::getOption('file_id') ?? CLI::getOption('file-id') ?? 0);
+ }
+
+ private function hasFlag(string $name): bool
+ {
+ if (CLI::getOption($name) !== null) {
+ return true;
+ }
+ return in_array('--' . $name, $_SERVER['argv'] ?? [], true);
+ }
+
+ private function resolveOptionValue(string $name, string $default): string
+ {
+ $opt = CLI::getOption($name);
+ if (is_string($opt) && $opt !== '') {
+ return $opt;
+ }
+
+ $argv = $_SERVER['argv'] ?? [];
+ foreach ($argv as $i => $arg) {
+ if (preg_match('/^--' . preg_quote($name, '/') . '=(.+)$/', (string) $arg, $m)) {
+ return trim($m[1]);
+ }
+ if ($arg === '--' . $name && isset($argv[$i + 1]) && strpos((string) $argv[$i + 1], '--') !== 0) {
+ return (string) $argv[$i + 1];
+ }
+ }
+
+ return $default;
+ }
+}
diff --git a/app/Config/Routes.php b/app/Config/Routes.php
index e18e3df7..9989ee54 100755
--- a/app/Config/Routes.php
+++ b/app/Config/Routes.php
@@ -501,6 +501,8 @@ $routes->group("policy_tranction", ["filter" => "authMVC"], function ($routes) {
$routes->group("inception", ["filter" => "authMVC"], function ($routes) {
$routes->match(['get', 'post'], 'list', 'PolicyTransactionController::viewInception');
+ $routes->post('list/datatable', 'PolicyTransactionController::inceptionListDataTable');
+ $routes->post('list/clear-cache', 'PolicyTransactionController::clearInceptionListCache');
$routes->post("create", "PolicyTransactionController::createInceptionPolicy");
$routes->get("list/(:any)", "PolicyTransactionController::getInceptionDataForEdit/$1");
$routes->get("remove/(:any)", "PolicyTransactionController::removeCDMaster/$1");
@@ -511,6 +513,8 @@ $routes->group("policy_tranction", ["filter" => "authMVC"], function ($routes) {
$routes->group("endorsement", ["filter" => "authMVC"], function ($routes) {
$routes->get("list", "PolicyTransactionController::viewEndorsement");
+ $routes->post("list/datatable", "PolicyTransactionController::endorsementListDataTable");
+ $routes->post("list/clear-cache", "PolicyTransactionController::clearEndorsementListCache");
$routes->post("create", "PolicyTransactionController::createEndorsementPolicy");
$routes->get("list/(:any)", "PolicyTransactionController::getEndorsementDataForEdit/$1");
$routes->get("remove/(:any)", "PolicyTransactionController::removeCDMaster/$1");
@@ -520,6 +524,8 @@ $routes->group("policy_tranction", ["filter" => "authMVC"], function ($routes) {
$routes->group("report", ["filter" => "authMVC"], function ($routes) {
$routes->match(['get', 'post'],"list", "PolicyTransactionController::reportBDS");
+ $routes->post("list/datatable", "PolicyTransactionController::reportBDSDataTable");
+ $routes->post("list/clear-cache", "PolicyTransactionController::clearReportBDSCache");
$routes->match(['get', 'post'],"list_new", "PolicyTransactionController::reportBDSNew");
$routes->get("report-varience-list", "PolicyTransactionController::reportVarience");
$routes->get("report-business-list", "PolicyTransactionController::reportBusinessList");
diff --git a/app/Controllers/EmployeeRestController.php b/app/Controllers/EmployeeRestController.php
index dd4a261c..dfcf11a6 100755
--- a/app/Controllers/EmployeeRestController.php
+++ b/app/Controllers/EmployeeRestController.php
@@ -483,6 +483,33 @@ class EmployeeRestController extends AdminController
}
}
+ private function getClaimStatusReason(string $claimStatus, array $claimsData): string
+ {
+ $statusReasonConfig = [
+ 'REJECTED' => ['denial_reason', 'head_rejection_reason'],
+ 'CANCELLED' => ['cancel_remark'],
+ 'CANCELED' => ['cancel_remark'],
+ 'RETURNED' => ['return_remark'],
+ ];
+
+ $claimStatusKey = strtoupper($claimStatus);
+
+ if (! isset($statusReasonConfig[$claimStatusKey])) {
+ return '';
+ }
+
+ foreach ($statusReasonConfig[$claimStatusKey] as $field) {
+ if (! empty($claimsData[$field])) {
+ $reason = trim((string) $claimsData[$field]);
+ if ($reason !== '') {
+ return $reason;
+ }
+ }
+ }
+
+ return '';
+ }
+
public function deleteDependence()
{
try {
@@ -2779,10 +2806,19 @@ class EmployeeRestController extends AdminController
$unique_key = $display_name;
}
- $filtered_history[$unique_key] = [
+ $modifiedAt = date('d-m-Y h:i A', strtotime($value['created_at']));
+ $reason = $this->getClaimStatusReason($status, $data['claims_data']);
+
+ $statusEntry = [
'modified_by' => "",
- 'modified_at' => date('d-m-Y h:i A', strtotime($value['created_at'])),
+ 'modified_at' => $modifiedAt,
];
+
+ if ($reason !== '') {
+ $statusEntry['reason'] = ' Reason : ' . $reason;
+ }
+
+ $filtered_history[$unique_key] = $statusEntry;
}
}
}
diff --git a/app/Controllers/LeadsController.php b/app/Controllers/LeadsController.php
index bd343eee..231ce0e1 100644
--- a/app/Controllers/LeadsController.php
+++ b/app/Controllers/LeadsController.php
@@ -2147,6 +2147,59 @@ class LeadsController extends BaseController
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;
+ }
+
+ $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' => $installment['utr_no'] ?? 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');
@@ -3811,21 +3864,7 @@ class LeadsController extends BaseController
$this->leadsModel->where('id', $lead_id)->set($data)->update();
if (isset($params['installments']) && ! empty($params['installments'])) {
-
- $installment_data = json_decode($params['installments'], true);
- if (! empty($installment_data)) {
- foreach ($installment_data as $key => $value) {
- // print_r($value);die
- $value['payment_date'] = ! empty($value['payment_date'])
- ? change_date_format($value['payment_date'])
- : null;
- if (isset($value['id']) && ! empty($value['id'])) {
- $this->leadInstallmentPaymentDetails->where('id', $value['id'])->set($value)->update();
- } else {
- $this->leadInstallmentPaymentDetails->insert($value);
- }
- }
- }
+ $this->saveLeadInstallmentDetails((int) $lead_id, $params['installments']);
}
}
@@ -8491,29 +8530,12 @@ class LeadsController extends BaseController
$this->myLogger->logme('error', "Lead updated successfully for ID: $lead_id");
// Save installment details
+ $savedInstallments = [];
if (! empty($params['installments'])) {
- $installments = json_decode($params['installments'], true);
- $this->myLogger->logme('error', "Installments data received: " . json_encode($installments));
-
- if (is_array($installments) && ! empty($installments)) {
- foreach ($installments as $installment) {
- $installment['payment_date'] = ! empty($installment['payment_date'])
- ? change_date_format($installment['payment_date'])
- : null;
-
- $installment['lead_id'] = $lead_id;
-
- if (! empty($installment['id'])) {
- $this->leadInstallmentPaymentDetails->update($installment['id'], $installment);
- $this->myLogger->logme('error', "Installment updated: " . json_encode($installment));
- } else {
- $this->leadInstallmentPaymentDetails->insert($installment);
- $this->myLogger->logme('error', "Installment inserted: " . json_encode($installment));
- }
- }
- }
+ $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");
+ $this->myLogger->logme('error', 'No installments provided');
}
// Update lead file status to pending
@@ -8526,12 +8548,13 @@ class LeadsController extends BaseController
$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,
- 'data' => $data,
- 'params' => $params,
+ '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) {
@@ -8614,31 +8637,17 @@ class LeadsController extends BaseController
$this->leadsModel->update($lead_id, $data);
+ $savedInstallments = [];
if (! empty($params['installments'])) {
- $installments = json_decode($params['installments'], true);
-
- if (is_array($installments) && ! empty($installments)) {
- foreach ($installments as $installment) {
- $installment['payment_date'] = ! empty($installment['payment_date'])
- ? change_date_format($installment['payment_date'])
- : null;
-
- $installment['lead_id'] = $lead_id;
-
- if (! empty($installment['id'])) {
- $this->leadInstallmentPaymentDetails->update($installment['id'], $installment);
- } else {
- $this->leadInstallmentPaymentDetails->insert($installment);
- }
- }
- }
+ $savedInstallments = $this->saveLeadInstallmentDetails((int) $lead_id, $params['installments']);
}
return $this->respond([
- 'status' => true,
- 'code' => 200,
- 'message' => 'Placement data saved successfully',
- 'lead_id' => $lead_id,
+ 'status' => true,
+ 'code' => 200,
+ 'message' => 'Placement data saved successfully',
+ 'lead_id' => $lead_id,
+ 'installments' => $savedInstallments,
], 200);
} catch (\Exception $e) {
return $this->respond([
diff --git a/app/Controllers/PolicyTransactionController.php b/app/Controllers/PolicyTransactionController.php
index 8c2436d7..818c3d1f 100644
--- a/app/Controllers/PolicyTransactionController.php
+++ b/app/Controllers/PolicyTransactionController.php
@@ -602,59 +602,9 @@ class PolicyTransactionController extends BaseController
'policy_end_date' => 'Policy End Date',
];
- // Filter data
- $start_date = $this->request->getGet('start_date');
- $end_date = $this->request->getGet('end_date');
- $client_id = $this->request->getGet('client_id');
- $insurer_id = $this->request->getGet('insurer_id');
- $policy_type_id = $this->request->getGet('policy_type_id');
- $date_type = $this->request->getGet('date_type');
- $issuer = $this->request->getGet('issuer');
- $status = $this->request->getGet('status');
-
- // Handle null or empty values
- $start_date = empty($start_date) ? 0 : $start_date;
- $end_date = empty($end_date) ? 0 : $end_date;
- $client_id = empty($client_id) ? 0 : $client_id;
- $insurer_id = empty($insurer_id) ? 0 : $insurer_id;
- $policy_type_id = empty($policy_type_id) ? 0 : $policy_type_id;
- $date_type = empty($date_type) ? 0 : $date_type;
- $issuer = empty($issuer) ? 0 : $issuer;
- $status = empty($status) ? 0 : $status; // Corrected from `$issuer`
-
- if(empty($bds_edit_pt_id) && empty($view)){
- if ($this->request->is('get')) {
-
- // Fetch inception data list
- $data['inception_data_list'] = $this->policyTransactionModel->getInceptionTranctionListData(
- $start_date,
- $end_date,
- $client_id,
- $insurer_id,
- $policy_type_id,
- $date_type,
- $issuer,
- $status
- );
- } else {
-
- $ids = $this->request->getPost('ids');
- $ids = array_filter(explode(',', $ids));
- $data['inception_data_list'] = $this->policyTransactionModel->getInceptionTranctionListData(
- $start_date = 0,
- $end_date = 0,
- $client_id = 0,
- $insurer_id = 0,
- $policy_type_id = 0,
- $date_type = 0,
- $issuer = 0,
- $status = 0,
- $ids
- );
- }
- }else{
- $data['inception_data_list'] = [];
- }
+ // List rows are loaded via server-side DataTables AJAX.
+ $data['inception_data_list'] = [];
+ $data['inception_filters'] = $this->buildInceptionFiltersFromRequest();
@@ -746,6 +696,136 @@ class PolicyTransactionController extends BaseController
$this->loadLayout('policy_transaction_inception_list', $data);
}
+ public function inceptionListDataTable()
+ {
+ if (!$this->request->isAJAX()) {
+ return $this->response->setStatusCode(400)->setJSON([
+ 'status' => false,
+ 'message' => 'Invalid request.',
+ ]);
+ }
+
+ $draw = (int) ($this->request->getPost('draw') ?? 0);
+ $start = max(0, (int) ($this->request->getPost('start') ?? 0));
+ $length = (int) ($this->request->getPost('length') ?? 10);
+ $search = trim((string) ($this->request->getPost('search')['value'] ?? ''));
+
+ $filters = $this->buildInceptionFiltersFromRequest();
+ $result = $this->policyTransactionModel->getInceptionTranctionListDataTable(
+ $draw,
+ $start,
+ $length,
+ $search,
+ $filters
+ );
+
+ $rows = [];
+ foreach ($result['data'] as $index => $row) {
+ $rows[] = $this->formatInceptionRowForDataTable($row, $start + $index + 1);
+ }
+
+ return $this->response->setJSON([
+ 'draw' => $result['draw'],
+ 'recordsTotal' => $result['recordsTotal'],
+ 'recordsFiltered' => $result['recordsFiltered'],
+ 'data' => $rows,
+ 'cache_expires_in_ms' => $result['cache_expires_in_ms'] ?? 300000,
+ ]);
+ }
+
+ public function clearInceptionListCache()
+ {
+ if (!$this->request->isAJAX()) {
+ return $this->response->setStatusCode(400)->setJSON([
+ 'status' => false,
+ 'message' => 'Invalid request.',
+ ]);
+ }
+
+ session()->set('inception_list_cache_version', time());
+
+ return $this->response->setJSON([
+ 'status' => true,
+ 'message' => 'Inception list cache cleared.',
+ ]);
+ }
+
+ protected function buildInceptionFiltersFromRequest(): array
+ {
+ $normalize = static function ($value) {
+ return (!isset($value) || $value === '' || $value === null) ? 0 : $value;
+ };
+
+ $ids = [];
+ if ($this->request->is('post')) {
+ $postIds = $this->request->getPost('ids') ?? '';
+ $ids = array_filter(explode(',', (string) $postIds));
+ }
+
+ return [
+ 'start_date' => $normalize($this->request->getGet('start_date') ?? $this->request->getPost('start_date')),
+ 'end_date' => $normalize($this->request->getGet('end_date') ?? $this->request->getPost('end_date')),
+ 'client_id' => $normalize($this->request->getGet('client_id') ?? $this->request->getPost('client_id')),
+ 'insurer_id' => $normalize($this->request->getGet('insurer_id') ?? $this->request->getPost('insurer_id')),
+ 'policy_type_id' => $normalize($this->request->getGet('policy_type_id') ?? $this->request->getPost('policy_type_id')),
+ 'date_type' => $normalize($this->request->getGet('date_type') ?? $this->request->getPost('date_type')),
+ 'issuer' => $normalize($this->request->getGet('issuer') ?? $this->request->getPost('issuer')),
+ 'status' => $normalize($this->request->getGet('status') ?? $this->request->getPost('status')),
+ 'ids' => $ids,
+ 'cache_version' => (int) (session()->get('inception_list_cache_version') ?? 1),
+ ];
+ }
+
+ protected function formatInceptionRowForDataTable(array $row, int $serialNo): array
+ {
+ $issuerMap = [1 => 'JIBS', 2 => 'Nhance'];
+ $issuingTypeMap = [1 => 'Fresh', 2 => 'Renewal', 3 => 'Roll Over'];
+ $clientTypeMap = [1 => 'Group', 2 => 'Individual'];
+ $policyStatusMap = [
+ 'under_process' => 'Under Process',
+ 'client_pending' => 'Client Pending',
+ 'insurer_pending' => 'Insurer Pending',
+ 'co_insurer_pending' => 'Co-Insurer Pending',
+ 'tpa_pending' => 'TPA Pending',
+ 'validated' => 'Validated',
+ 'cancelled' => 'Cancelled',
+ 'instalment_pending' => 'Instalment Pending',
+ 'completed' => 'Completed',
+ 'lost' => 'Lost',
+ ];
+
+ $clientBranch = ((int) ($row['client_type'] ?? 0) === 2)
+ ? (($row['client_name'] ?? 'N/A') . ' - ' . (!empty($row['pan']) ? $row['pan'] : 'N/A'))
+ : (($row['client_short_name'] ?? 'N/A') . ' - ' . ($row['client_branch_name'] ?? 'N/A'));
+
+ $editAction = 'Edit';
+ $deleteAction = '';
+ if ((int) get_role_id() === 5) {
+ $deleteAction = 'Delete';
+ }
+
+ $actionHtml = '
';
+
+ return [
+ 0 => $serialNo,
+ 1 => $issuerMap[$row['issuer'] ?? 2] ?? 'Nhance',
+ 2 => $issuingTypeMap[$row['issue_type'] ?? 0] ?? 'N/A',
+ 3 => $clientTypeMap[$row['client_type'] ?? 0] ?? 'N/A',
+ 4 => $clientBranch,
+ 5 => $row['insurer_short_name'] ?: 'N/A',
+ 6 => $row['policy_type'] ?: 'N/A',
+ 7 => $row['policy_no'] ?: 'N/A',
+ 8 => empty($row['policy_issue_date']) ? 'N/A' : date('d/m/Y', strtotime($row['policy_issue_date'])),
+ 9 => empty($row['policy_start_date']) ? 'N/A' : date('d/m/Y', strtotime($row['policy_start_date'])),
+ 10 => empty($row['policy_end_date']) ? 'N/A' : date('d/m/Y', strtotime($row['policy_end_date'])),
+ 11 => $row['emp_count'] ?: '0',
+ 12 => $row['dependent_count'] ?: '0',
+ 13 => $policyStatusMap[$row['status'] ?? ''] ?? 'N/A',
+ 14 => $row['user_name'] ?: 'N/A',
+ 15 => $actionHtml,
+ ];
+ }
+
public function viewInception2()
{
$bds_edit_pt_id = $this->request->getGet('pt_id') ?? null;
@@ -921,6 +1001,8 @@ class PolicyTransactionController extends BaseController
// policy Transaction Create function start
public function createInceptionPolicy()
{
+ session()->set('inception_list_cache_version', time());
+
$post_data = $this->request->getPost();
$rules = [
@@ -2391,31 +2473,8 @@ class PolicyTransactionController extends BaseController
'policy_end_date' => 'Policy End Date',
];
- //filter datas
- $start_date = $this->request->getGet('start_date');
- $end_date = $this->request->getGet('end_date');
- $client_id = $this->request->getGet('client_id');
- $insurer_id = $this->request->getGet('insurer_id');
- $policy_type_id = $this->request->getGet('policy_type_id');
- $date_type = $this->request->getGet('date_type');
- $issuer = $this->request->getGet('issuer');
- $status = $this->request->getGet('status');
-
- $start_date = (!isset($start_date) || $start_date === '' || $start_date === null) ? 0 : $start_date;
- $end_date = (!isset($end_date) || $end_date === '' || $end_date === null) ? 0 : $end_date;
-
- $client_id = (!isset($client_id) || $client_id === '' || $client_id === null) ? 0 : $client_id;
- $insurer_id = (!isset($insurer_id) || $insurer_id === '' || $insurer_id === null) ? 0 : $insurer_id;
- $policy_type_id = (!isset($policy_type_id) || $policy_type_id === '' || $policy_type_id === null) ? 0 : $policy_type_id;
- $date_type = (!isset($date_type) || $date_type === '' || $date_type === null) ? 0 : $date_type;
- $issuer = (!isset($issuer) || $issuer === '' || $issuer === null) ? 0 : $issuer;
- $status = (!isset($status) || $status === '' || $status === null) ? 0 : $status;
-
- if($bds_edit_pt_id == null){
- $data['endorsement_data_list'] = $this->policyTransactionModel->getEndorsementTranctionListData($start_date, $end_date, $client_id, $insurer_id, $policy_type_id, $date_type, $issuer, $status);
- }else{
- $data['endorsement_data_list'] = [];
- }
+ $data['endorsement_data_list'] = [];
+ $data['endorsement_filters'] = $this->buildEndorsementFiltersFromRequest();
$data['client'] = $this->clientModel->where('is_active', 1)->findAll();
$data['policy_types'] = $this->policyTypeModel->where('is_active', 1)->findAll();
@@ -2434,6 +2493,134 @@ class PolicyTransactionController extends BaseController
$this->loadLayout('policy_transaction_endorsement_list', $data);
}
+ public function endorsementListDataTable()
+ {
+ if (!$this->request->isAJAX()) {
+ return $this->response->setStatusCode(400)->setJSON([
+ 'status' => false,
+ 'message' => 'Invalid request.',
+ ]);
+ }
+
+ $draw = (int) ($this->request->getPost('draw') ?? 0);
+ $start = max(0, (int) ($this->request->getPost('start') ?? 0));
+ $length = (int) ($this->request->getPost('length') ?? 10);
+ $search = trim((string) ($this->request->getPost('search')['value'] ?? ''));
+
+ $filters = $this->buildEndorsementFiltersFromRequest();
+ $result = $this->policyTransactionModel->getEndorsementTranctionListDataTable(
+ $draw,
+ $start,
+ $length,
+ $search,
+ $filters
+ );
+
+ $rows = [];
+ foreach ($result['data'] as $index => $row) {
+ $rows[] = $this->formatEndorsementRowForDataTable($row, $start + $index + 1);
+ }
+
+ return $this->response->setJSON([
+ 'draw' => $result['draw'],
+ 'recordsTotal' => $result['recordsTotal'],
+ 'recordsFiltered' => $result['recordsFiltered'],
+ 'data' => $rows,
+ 'cache_expires_in_ms' => $result['cache_expires_in_ms'] ?? 300000,
+ ]);
+ }
+
+ public function clearEndorsementListCache()
+ {
+ if (!$this->request->isAJAX()) {
+ return $this->response->setStatusCode(400)->setJSON([
+ 'status' => false,
+ 'message' => 'Invalid request.',
+ ]);
+ }
+
+ session()->set('endorsement_list_cache_version', time());
+
+ return $this->response->setJSON([
+ 'status' => true,
+ 'message' => 'Endorsement list cache cleared.',
+ ]);
+ }
+
+ protected function buildEndorsementFiltersFromRequest(): array
+ {
+ $normalize = static function ($value) {
+ return (!isset($value) || $value === '' || $value === null) ? 0 : $value;
+ };
+
+ return [
+ 'start_date' => $normalize($this->request->getGet('start_date') ?? $this->request->getPost('start_date')),
+ 'end_date' => $normalize($this->request->getGet('end_date') ?? $this->request->getPost('end_date')),
+ 'client_id' => $normalize($this->request->getGet('client_id') ?? $this->request->getPost('client_id')),
+ 'insurer_id' => $normalize($this->request->getGet('insurer_id') ?? $this->request->getPost('insurer_id')),
+ 'policy_type_id' => $normalize($this->request->getGet('policy_type_id') ?? $this->request->getPost('policy_type_id')),
+ 'date_type' => $normalize($this->request->getGet('date_type') ?? $this->request->getPost('date_type')),
+ 'issuer' => $normalize($this->request->getGet('issuer') ?? $this->request->getPost('issuer')),
+ 'status' => $normalize($this->request->getGet('status') ?? $this->request->getPost('status')),
+ 'cache_version' => (int) (session()->get('endorsement_list_cache_version') ?? 1),
+ ];
+ }
+
+ protected function formatEndorsementRowForDataTable(array $row, int $serialNo): array
+ {
+ $issuerMap = [1 => 'JIBS', 2 => 'Nhance'];
+ $policyStatusMap = [
+ 'under_process' => 'Under Process',
+ 'client_pending' => 'Client Pending',
+ 'insurer_pending' => 'Insurer Pending',
+ 'co_insurer_pending' => 'Co-Insurer Pending',
+ 'tpa_pending' => 'TPA Pending',
+ 'validated' => 'Validated',
+ 'cancelled' => 'Cancelled',
+ 'instalment_pending' => 'Instalment Pending',
+ 'completed' => 'Completed',
+ ];
+ $actionTypeMap = [
+ 'addition' => 'Addition',
+ 'deletion' => 'Deletion',
+ 'addition_deletion' => 'Addition & Deletion',
+ 'si_enhancement' => 'SI Enhancement',
+ 'combo_a_d_si' => 'Combo A, D & SI',
+ 'correction' => 'Correction',
+ 'baby_addition' => 'Baby Addition',
+ 'policy_instalment' => 'Policy Instalment',
+ 'addition_inception' => 'Addition-Inception',
+ 'bds_correction' => 'BDS Correction',
+ 'policy_correction' => 'Policy Correction',
+ 'policy_cancellation' => 'Policy Cancellation',
+ ];
+
+ $editAction = 'Edit';
+ $deleteAction = '';
+ if ((int) get_role_id() === 5) {
+ $deleteAction = 'Delete';
+ }
+
+ $actionHtml = '';
+
+ return [
+ 0 => $serialNo,
+ 1 => $issuerMap[$row['issuer'] ?? 0] ?? 'N/A',
+ 2 => $row['client_short_name'] ?: 'N/A',
+ 3 => $row['client_branch_name'] ?: 'N/A',
+ 4 => $row['insurer_short_name'] ?: 'N/A',
+ 5 => $row['policy_type'] ?: 'N/A',
+ 6 => $actionTypeMap[$row['action_type'] ?? ''] ?? 'N/A',
+ 7 => $row['endorsement_no'] ?: 'N/A',
+ 8 => empty($row['data_received_date']) ? 'N/A' : date('d/m/Y', strtotime($row['data_received_date'])),
+ 9 => $row['emp_count'] ?: '0',
+ 10 => $row['dependent_count'] ?: '0',
+ 11 => empty($row['policy_issue_date']) ? 'N/A' : date('d/m/Y', strtotime($row['policy_issue_date'])),
+ 12 => $policyStatusMap[$row['status'] ?? ''] ?? 'N/A',
+ 13 => $actionHtml,
+ ];
+ }
+
public function viewEndorsement2()
{
// echo '';
@@ -2530,6 +2717,8 @@ class PolicyTransactionController extends BaseController
public function createEndorsementPolicy()
{
+ session()->set('endorsement_list_cache_version', time());
+
// $id = $this->request->getPost('id');
$rules = [
// ==========================================
@@ -3793,65 +3982,230 @@ class PolicyTransactionController extends BaseController
$data['users'] = $this->userModel->where('is_active', 1)->findAll();
$data['policy_count'] = $this->policyTransactionModel->where('is_active', 1)->countAllResults();
-
- //filter datas
- $start_date = $this->request->getGet('start_date');
- $end_date = $this->request->getGet('end_date');
- $client_id = $this->request->getGet('client_id');
- $insurer_id = $this->request->getGet('insurer_id');
- $policy_type_id = $this->request->getGet('policy_type_id');
- $date_type = $this->request->getGet('date_type');
- $issuer = $this->request->getGet('issuer');
- $client_branch_id = $this->request->getGet('client_branch_id');
- $insurer_branch_id = $this->request->getGet('insurer_branch_id');
- $client_policy_id = $this->request->getGet('client_policy_id');
- $user_id = $this->request->getGet('user_id');
-
- if ($date_type == 'statement_month') {
- $start_date = (string)date('Y-m-01', strtotime($start_date));
- $end_date = (string)date('Y-m-31', strtotime($end_date));
- }
-
- // dd($start_date, $end_date, $date_type);
-
- $start_date = (!isset($start_date) || $start_date === '' || $start_date === null) ? 0 : $start_date;
- $end_date = (!isset($end_date) || $end_date === '' || $end_date === null) ? 0 : $end_date;
-
- $client_id = (!isset($client_id) || $client_id === '' || $client_id === null) ? 0 : $client_id;
- $insurer_id = (!isset($insurer_id) || $insurer_id === '' || $insurer_id === null) ? 0 : $insurer_id;
- $policy_type_id = (!isset($policy_type_id) || $policy_type_id === '' || $policy_type_id === null) ? 0 : $policy_type_id;
- $date_type = (!isset($date_type) || $date_type === '' || $date_type === null) ? 0 : $date_type;
- $issuer = (!isset($issuer) || $issuer === '' || $issuer === null) ? 0 : $issuer;
- $client_branch_id = (!isset($client_branch_id) || $client_branch_id === '' || $client_branch_id === null) ? 0 : $client_branch_id;
- $insurer_branch_id = (!isset($insurer_branch_id) || $insurer_branch_id === '' || $insurer_branch_id === null) ? 0 : $insurer_branch_id;
- $client_policy_id = (!isset($client_policy_id) || $client_policy_id === '' || $client_policy_id === null) ? 0 : $client_policy_id;
- $user_id = (!isset($user_id) || $user_id === '' || $user_id === null) ? 0 : $user_id;
- if ($this->request->is('post')) {
- $request_post_data = $this->request->getPost();
- $sanitized_post_data = sanitizeInputArrayAdvanced($request_post_data);
- $isFromDashboard = $sanitized_post_data["is_dashboard"];
-
- if (isset($isFromDashboard) && !empty($isFromDashboard) && $isFromDashboard == 1) {
- $ids = $sanitized_post_data['ids'];
-
- $ids = array_filter(explode(',', $ids));
-
- if (!empty($ids)) {
- $idsStr = implode(',', array_map('intval', $ids)); // sanitize IDs to be integers
- $where = "policy_transaction.id IN ($idsStr)";
- } else {
- $where = []; // No valid IDs, return empty result
- }
- }
- // dd($ids);
- }
- //Actual data for the list
- $data['report_list'] = $this->policyTransactionModel->getBDSReportList($start_date, $end_date, $client_id, $insurer_id, $policy_type_id, $date_type, $issuer, $client_branch_id, $insurer_branch_id, $client_policy_id, $user_id, isset($where) ? $where : '');
+ // List data loaded via server-side DataTables AJAX
+ $data['report_list'] = [];
+ $data['bds_filters'] = $this->buildBDSReportFiltersFromRequest();
// dd($data);
$this->loadLayout('report_bds_filter', $data);
}
+ /**
+ * Server-side DataTables endpoint for BDS report list.
+ */
+ public function reportBDSDataTable()
+ {
+ if (!$this->request->isAJAX()) {
+ return $this->response->setStatusCode(400)->setJSON([
+ 'status' => false,
+ 'message' => 'Invalid request.',
+ ]);
+ }
+
+ $draw = (int) ($this->request->getPost('draw') ?? 0);
+ $start = max(0, (int) ($this->request->getPost('start') ?? 0));
+ $length = (int) ($this->request->getPost('length') ?? 10);
+ $search = trim((string) ($this->request->getPost('search')['value'] ?? ''));
+
+ $filters = $this->buildBDSReportFiltersFromRequest();
+
+ $result = $this->policyTransactionModel->getBDSReportListDataTable(
+ $draw,
+ $start,
+ $length,
+ $search,
+ $filters
+ );
+
+ $serialStart = $start + 1;
+ $data = [];
+
+ foreach ($result['data'] as $index => $row) {
+ $data[] = $this->formatBdsReportRowForDataTable($row, $serialStart + $index);
+ }
+
+ return $this->response->setJSON([
+ 'draw' => $result['draw'],
+ 'recordsTotal' => $result['recordsTotal'],
+ 'recordsFiltered' => $result['recordsFiltered'],
+ 'data' => $data,
+ 'totals' => $result['totals'],
+ ]);
+ }
+
+ public function clearReportBDSCache()
+ {
+ if (!$this->request->isAJAX()) {
+ return $this->response->setStatusCode(400)->setJSON([
+ 'status' => false,
+ 'message' => 'Invalid request.',
+ ]);
+ }
+
+ session()->set('bds_report_cache_version', time());
+
+ return $this->response->setJSON([
+ 'status' => true,
+ 'message' => 'BDS report cache cleared.',
+ ]);
+ }
+
+ /**
+ * Normalize BDS report filter params from the current request.
+ */
+ protected function buildBDSReportFiltersFromRequest(): array
+ {
+ $start_date = $this->request->getGet('start_date') ?? $this->request->getPost('start_date');
+ $end_date = $this->request->getGet('end_date') ?? $this->request->getPost('end_date');
+ $client_id = $this->request->getGet('client_id') ?? $this->request->getPost('client_id');
+ $insurer_id = $this->request->getGet('insurer_id') ?? $this->request->getPost('insurer_id');
+ $policy_type_id = $this->request->getGet('policy_type_id') ?? $this->request->getPost('policy_type_id');
+ $date_type = $this->request->getGet('date_type') ?? $this->request->getPost('date_type');
+ $issuer = $this->request->getGet('issuer') ?? $this->request->getPost('issuer');
+ $client_branch_id = $this->request->getGet('client_branch_id') ?? $this->request->getPost('client_branch_id');
+ $insurer_branch_id = $this->request->getGet('insurer_branch_id') ?? $this->request->getPost('insurer_branch_id');
+ $client_policy_id = $this->request->getGet('client_policy_id') ?? $this->request->getPost('client_policy_id');
+ $user_id = $this->request->getGet('user_id') ?? $this->request->getPost('user_id');
+
+ if ($date_type == 'statement_month' && $start_date && $end_date) {
+ $start_date = (string) date('Y-m-01', strtotime($start_date));
+ $end_date = (string) date('Y-m-31', strtotime($end_date));
+ }
+
+ $normalize = static function ($value) {
+ return (!isset($value) || $value === '' || $value === null) ? 0 : $value;
+ };
+
+ $where = '';
+ if ($this->request->is('post')) {
+ $request_post_data = $this->request->getPost();
+ $sanitized_post_data = sanitizeInputArrayAdvanced($request_post_data);
+ $isFromDashboard = $sanitized_post_data['is_dashboard'] ?? null;
+
+ if (isset($isFromDashboard) && !empty($isFromDashboard) && (int) $isFromDashboard === 1) {
+ $ids = array_filter(explode(',', $sanitized_post_data['ids'] ?? ''));
+
+ if (!empty($ids)) {
+ $idsStr = implode(',', array_map('intval', $ids));
+ $where = "policy_transaction.id IN ($idsStr)";
+ } else {
+ $where = [];
+ }
+ }
+ }
+
+ return [
+ 'start_date' => $normalize($start_date),
+ 'end_date' => $normalize($end_date),
+ 'client_id' => $normalize($client_id),
+ 'insurer_id' => $normalize($insurer_id),
+ 'policy_type_id' => $normalize($policy_type_id),
+ 'date_type' => $normalize($date_type),
+ 'issuer' => $normalize($issuer),
+ 'client_branch_id' => $normalize($client_branch_id),
+ 'insurer_branch_id' => $normalize($insurer_branch_id),
+ 'client_policy_id' => $normalize($client_policy_id),
+ 'user_id' => $normalize($user_id),
+ 'where' => $where,
+ 'cache_version' => (int) (session()->get('bds_report_cache_version') ?? 1),
+ ];
+ }
+
+ /**
+ * Format a single BDS report row for DataTables output.
+ */
+ protected function formatBdsReportRowForDataTable(array $row, int $serialNo): array
+ {
+ $hasIrda = ((float) ($row['total_irda_amt'] ?? 0)) != 0.0;
+ $actionType = strtolower((string) ($row['action_type'] ?? ''));
+ $editBaseUrl = $actionType === 'policy'
+ ? base_url('policy_tranction/inception/list')
+ : base_url('policy_tranction/endorsement/list');
+ $editLink = $editBaseUrl . '?pt_id=' . ($row['id'] ?? '');
+ $totalIrdaAmt = $row['total_irda_amt'] ?? '0.00';
+ $unbilled = isset($row['unbilled_amount']) ? number_format((float) $row['unbilled_amount'], 2, '.', '') : '0.00';
+
+ $fmtDate = static function ($value) {
+ return empty($value) ? 'N/A' : change_date_format($value, 'Y-m-d', 'd/m/Y');
+ };
+
+ $fmtNum = static function ($value, int $decimals = 2) {
+ return number_format((float) ($value ?? 0), $decimals, '.', '');
+ };
+
+ $na = static function ($value) {
+ return ($value !== null && $value !== '') ? $value : 'N/A';
+ };
+
+ $cells = [
+ $serialNo . ' ',
+ $na($row['user_name'] ?? null),
+ $na($row['policy_issue_month'] ?? null),
+ $na($row['revenue_type'] ?? null),
+ $na($row['client_type'] ?? null),
+ $na($row['client_name'] ?? null),
+ $na($row['action_type'] ?? null),
+ $na($row['policy_type'] ?? null),
+ $na($row['bap'] ?? null),
+ $na($row['vehicle_no'] ?? null),
+ $na($row['policy_no'] ?? null),
+ $na($row['endorsement_no'] ?? null),
+ $na($row['insurer_branch_name'] ?? null),
+ $fmtDate($row['endorse_eff_date'] ?? null),
+ $fmtDate($row['policy_start_date'] ?? null),
+ $fmtDate($row['policy_end_date'] ?? null),
+ $na($row['ref'] ?? null),
+ $na($row['remarks'] ?? null),
+ $hasIrda ? ($row['bp_amt'] ?: '0.00') : '0.00',
+ $hasIrda ? ($row['tp_or_ter'] ?: '0.00') : '0.00',
+ $hasIrda ? ($row['premium_wo_gst'] ?: '0.00') : '0.00',
+ $hasIrda ? ($row['total_premium'] ?: '0.00') : '0.00',
+ ($hasIrda ? ($row['agreed_bp_per'] ?: '0.00') : '0.00') . '%',
+ ($hasIrda ? ($row['agreed_tp_or_ter_per'] ?: '0.00') : '0.00') . '%',
+ isset($row['reward']) ? $row['reward'] : '0.00',
+ '' . $totalIrdaAmt . '',
+ '' . (empty($row['billed_amt']) ? '0.00' : $row['billed_amt']) . '',
+ '' . $unbilled . '',
+ $na($row['salse_person_name'] ?? null),
+ $na($row['service_person_name'] ?? null),
+ $na($row['nhance_branch'] ?? null),
+ $na($row['installment'] ?? null),
+ $fmtDate($row['data_received_date'] ?? null),
+ $fmtDate($row['renewal_date'] ?? null),
+ $row['co_share'] ?? 'No',
+ $row['bro_payable_by'] ?? 'No',
+ $na($row['salse_manager_name'] ?? null),
+ $na($row['service_manager_name'] ?? null),
+ $na($row['service_branch'] ?? null),
+ $fmtDate($row['rollover_date'] ?? null),
+ $na($row['policy_holder_name'] ?? null),
+ $row['same_as_proposer'] ?? 'No',
+ $na($row['follower_policy_no'] ?? null),
+ $fmtNum($row['co_share_per'] ?? 0),
+ $fmtNum($row['non_comm_per_amt'] ?? 0),
+ $fmtNum($row['bp_igst'] ?? 0),
+ $fmtNum($row['bp_sgst'] ?? 0),
+ $fmtNum($row['bp_cgst'] ?? 0),
+ $fmtNum($row['stamp_duty'] ?? 0),
+ $fmtNum($row['standerd_bp_per'] ?? 0),
+ $fmtNum($row['standerd_tp_per'] ?? 0),
+ $fmtNum($row['actual_bp_amt'] ?? 0),
+ $fmtNum($row['actual_tp_amt'] ?? 0),
+ $fmtNum($row['actual_bp_per'] ?? 0),
+ $fmtNum($row['actual_tp_per'] ?? 0),
+ $fmtNum($row['actual_tep_brokerage_amt'] ?? 0),
+ $fmtNum($row['actual_tp_brokerage_amt'] ?? 0),
+ $na($row['cd_ac_no'] ?? null),
+ ];
+
+ $rowData = ['DT_RowAttr' => ['data-id' => $row['pt_id'] ?? '']];
+ foreach ($cells as $index => $cell) {
+ $rowData[$index] = $cell;
+ }
+
+ return $rowData;
+ }
+
public function reportVarience()
{
$data['tab_name'] = 'Variance Report';
@@ -5431,7 +5785,7 @@ class PolicyTransactionController extends BaseController
}
$this->myLogger->logme("error", "Data for BDS Installment " . json_encode($bdsInstallmentData));
- // print_rr($bdsInstallmentData);die();
+ // dd($bdsInstallmentData);die();
if (empty($bdsInstallmentData)) {
$this->myLogger->logme("error", "No Client Installment is Due in the 5th Day");
@@ -5439,31 +5793,91 @@ class PolicyTransactionController extends BaseController
return ['status' => false, 'message' => 'No data found', 'response' => []];
}
+ $results = [];
+ $successCount = 0;
+ $failedCount = 0;
+ $skippedCount = 0;
+
foreach ($bdsInstallmentData as $installmentData) {
+ $installmentId = $installmentData['id'] ?? 'unknown';
+ $leadId = $installmentData['lead_id'] ?? 'unknown';
- $mailData = $this->PrepareBDSMailData($installmentData);
- $to_mail = $mailData['to_mail'];
- $message = $mailData['message'];
- $subject = $mailData['subject'];
+ try {
+ $mailData = $this->PrepareBDSMailData($installmentData);
- $this->myLogger->logme("error", "Installment Pending for" . $subject);
+ if (empty($mailData) || empty($mailData['to_mail'])) {
+ $this->myLogger->logme(
+ 'error',
+ "Installment {$installmentId} (lead {$leadId}): skipped — no valid recipient emails"
+ );
+ $skippedCount++;
+ $results[] = [
+ 'installment_id' => $installmentId,
+ 'lead_id' => $leadId,
+ 'status' => 'skipped',
+ 'message' => 'No valid recipient emails',
+ ];
+ continue;
+ }
- $common = ['mail_type' => 'installment_amount_due_remainder_mail'];
+ $to_mail = $mailData['to_mail'];
+ $message = $mailData['message'];
+ $subject = $mailData['subject'];
- $res = MailHelper::send_email(['mail' => $to_mail, 'subject' => $subject, 'message' => $message, 'common' => $common]);
+ $this->myLogger->logme("error", "Installment Pending for " . $subject);
- $res = json_decode($res);
- $this->myLogger->logme('error', 'res: ' . json_encode($res));
+ $common = ['mail_type' => 'installment_amount_due_remainder_mail'];
- if ($res->status == 'success') {
- CLI::write("Mail sent successfully to " . count($to_mail) . " recipients");
- return ['status' => true, 'message' => 'Mail sent successfully', 'response' => $res];
- } else {
- CLI::write("Mail sent failed to " . count($to_mail) . " recipients");
- return ['status' => false, 'message' => 'Mail sent failed', 'response' => $res];
+ $res = MailHelper::send_email(['mail' => $to_mail, 'subject' => $subject, 'message' => $message, 'common' => $common]);
+
+ $res = json_decode($res);
+ $this->myLogger->logme(
+ 'error',
+ "Installment {$installmentId} (lead {$leadId}) mail result: " . json_encode($res)
+ );
+
+ if ($res->status == 'success') {
+ $successCount++;
+ CLI::write("Mail sent successfully for installment {$installmentId} to " . count($to_mail) . " recipients");
+ $results[] = [
+ 'installment_id' => $installmentId,
+ 'lead_id' => $leadId,
+ 'status' => 'success',
+ ];
+ } else {
+ $failedCount++;
+ CLI::write("Mail failed for installment {$installmentId}");
+ $results[] = [
+ 'installment_id' => $installmentId,
+ 'lead_id' => $leadId,
+ 'status' => 'failed',
+ 'response' => $res,
+ ];
+ }
+ } catch (Exception $e) {
+ $failedCount++;
+ $this->myLogger->logme(
+ 'error',
+ "Installment {$installmentId} (lead {$leadId}) exception: " . $e->getMessage()
+ );
+ $results[] = [
+ 'installment_id' => $installmentId,
+ 'lead_id' => $leadId,
+ 'status' => 'failed',
+ 'message' => $e->getMessage(),
+ ];
}
}
+ $totalProcessed = count($bdsInstallmentData);
+ $summaryMessage = "Processed {$totalProcessed} installment(s): {$successCount} sent, {$failedCount} failed, {$skippedCount} skipped";
+
+ return [
+ 'status' => $successCount > 0,
+ 'message' => $summaryMessage,
+ 'response' => $results,
+ ];
+
} catch (Exception $e) {
$this->myLogger->logme('error', 'Exception: ' . $e->getMessage() . 'Page: ' . $e->getFile() . ' Line: ' . $e->getLine());
}
@@ -5474,44 +5888,63 @@ class PolicyTransactionController extends BaseController
try {
- $installment_amount = $data['installment_amount'];
- $payment_date = date('d-m-Y', strtotime($data['payment_date']));
- $client = $data['client_name'];
- $branch = $data['branch_name'];
- $sales_person_mail = $data['sales_person'];
- $heads = $data['heads'];
- $admins = $data['admins'];
- $buisness_team = $data['buisness_team'];
- $policy_no = $data['policy_no'];
- $client_short_name = isset($data['short_name']) && $data['short_name'] != null ? $data['short_name'] : $data['client_name'];
+ helper('excel_util_helper');
- $subject = "Installment Amount Due For Client - {$client_short_name} - Policy NO({$policy_no}) is Due On - {$payment_date}";
+ $installment_amount = (float) ($data['installment_amount'] ?? 0);
+ $payment_date = date('d-m-Y', strtotime($data['payment_date']));
+ $client = $data['client_name'];
+ $branch = $data['branch_name'];
+ $sales_person_mail = $data['sales_person'];
+ $policy_no = trim((string) ($data['policy_no'] ?? ''));
+ $client_short_name = isset($data['short_name']) && $data['short_name'] != null ? $data['short_name'] : $data['client_name'];
+ $formatted_amount = '₹ ' . formatIndianCurrency(number_format($installment_amount, 2, '.', ''));
+ $is_overdue = strtotime($data['payment_date']) < strtotime(date('Y-m-d'));
+ $policy_label = $policy_no !== '' ? "Policy #{$policy_no}" : 'Policy Pending';
+ $policy_period = '';
- $message = "Policy Installment for Client - {$client}, Branch - {$branch} is Due on {$payment_date}
- with amount of {$installment_amount}.
- Policy No : {$policy_no}";
+ if (!empty($data['policy_start_date']) && !empty($data['policy_end_date'])) {
+ $policy_period = date('d-m-Y', strtotime($data['policy_start_date']))
+ . ' to '
+ . date('d-m-Y', strtotime($data['policy_end_date']));
+ }
+ $subject = $is_overdue
+ ? "Overdue Installment Reminder - {$client_short_name} | {$policy_label} | Due {$payment_date}"
+ : "Installment Payment Reminder - {$client_short_name} | {$policy_label} | Due {$payment_date}";
+
+ $message = view('bds_installment_reminder_email_template', [
+ 'client_name' => $client,
+ 'branch_name' => $branch,
+ 'policy_no' => $policy_no !== '' ? $policy_no : 'Not Assigned',
+ 'policy_type' => $data['policy_type'] ?? '',
+ 'insurer_name' => $data['insurer_name'] ?? '',
+ 'policy_period' => $policy_period,
+ 'payment_date' => $payment_date,
+ 'installment_amount' => $formatted_amount,
+ 'is_overdue' => $is_overdue,
+ 'generated_on' => date('d-m-Y H:i'),
+ ]);
$contactPersonEmail = trim((string) ($data['contact_person_email'] ?? ''));
$to_mail = array_merge(
- array_column($heads, 'email'),
- array_column($admins, 'email'),
- array_column($buisness_team, 'email'),
+ [$data['acm_email']],
[$sales_person_mail],
$contactPersonEmail !== '' ? [$contactPersonEmail] : []
);
- $to_mail = array_values(array_unique(array_filter($to_mail)));
+ $to_mail = array_values(array_unique(array_filter($to_mail, static function ($email) {
+ return is_string($email) && filter_var(trim($email), FILTER_VALIDATE_EMAIL);
+ })));
$this->myLogger->logme("error", "Selected To Address : " . json_encode($to_mail));
- // dd($to_mail);
return [
'to_mail' => $to_mail,
'message' => $message,
'subject' => $subject
];
+
} catch (Exception $e) {
$this->myLogger->logme('error', 'Exception: ' . $e->getMessage() . 'Page: ' . $e->getFile() . ' Line: ' . $e->getLine());
diff --git a/app/Libraries/TPAClaimsImportServices/AbhiClaimImportService.php b/app/Libraries/TPAClaimsImportServices/AbhiClaimImportService.php
index 81a01aec..08da325e 100644
--- a/app/Libraries/TPAClaimsImportServices/AbhiClaimImportService.php
+++ b/app/Libraries/TPAClaimsImportServices/AbhiClaimImportService.php
@@ -242,20 +242,6 @@ class AbhiClaimImportService extends BaseTpaClaimImportService
$item[$value] = change_date_format($item[$value] ?? null, 'm/d/Y h:i:s A', 'Y-m-d');
}
- $params = [
- 'doa' => $item['doa'] ?? null,
- 'member_code' => $item['member_code'] ?? null,
- 'claimed_amount' => $item['claimed_amount'] ?? null,
- 'healthcard_id' => $item['healthcard_id'] ?? null
- ];
-
- $is_duplicate = $this->checkDuplicateTpaClaim('claims_dump_abhi', $params);
-
- if ($is_duplicate) {
- $item = [];
- continue;
- }
-
$item['file_id'] = $file_id ?? null;
$item['client_id'] = $file_data['client_id'] ?? null;
$item['client_policy_id'] = $file_data['client_policy_id'] ?? null;
@@ -276,7 +262,7 @@ class AbhiClaimImportService extends BaseTpaClaimImportService
$tpaClaimDumpData = $this->getTpaClaimDumpData('claims_dump_abhi', ['file_id' => $file_id]);
if (empty($tpaClaimDumpData)) {
- return ['status' => false, 'message' => "No data to insert in TICKET MASTER"];
+ return $this->emptyClaimMasterMappingResponse('claims_dump_abhi', (int) $file_id);
}
@@ -302,6 +288,7 @@ class AbhiClaimImportService extends BaseTpaClaimImportService
$mapped = [];
$rejecetd_reason = [];
+ $status_update_array = [];
foreach ($tpaClaimDumpData as $row) {
@@ -312,11 +299,16 @@ class AbhiClaimImportService extends BaseTpaClaimImportService
'tpa_no' => $row['healthcard_id'] ?? null
];
- $isduplicate = $this->checkDublicateTicketMasterClaim($params);
+ $newStatusId = $this->checkStatusMapping($this->statusMapping, $row['claim_status'] ?? '') ?? 61;
+ $existingTicket = $this->getExistingTicketMasterClaim($params);
- if ($isduplicate) {
- $reason = "This claim already exists in our system.";
- $rejecetd_reason[] = ["id" => $row['id'], "master_reject_reason" => $reason];
+ if ($this->handleExistingTicketStatusUpdate(
+ $existingTicket,
+ $newStatusId,
+ (int) $row['id'],
+ $status_update_array,
+ $rejecetd_reason
+ )) {
continue;
}
@@ -358,7 +350,7 @@ class AbhiClaimImportService extends BaseTpaClaimImportService
}
// Meta fields
- $item['claim_status_id'] = $this->checkStatusMapping($this->statusMapping, $row['claim_status']);
+ $item['claim_status_id'] = $newStatusId;
$item['file_id'] = $file_id;
$item['claim_dump_ref_id'] = $row['id'];
$item['claim_dump_date'] = $file_data['claim_dump_date'] ?? null;
@@ -372,7 +364,12 @@ class AbhiClaimImportService extends BaseTpaClaimImportService
$mapped[] = $item;
}
- return ['status' => true, 'mapped_array' => $mapped, 'rejected_reason_array' => $rejecetd_reason];
+ return [
+ 'status' => true,
+ 'mapped_array' => $mapped,
+ 'rejected_reason_array' => $rejecetd_reason,
+ 'status_update_array' => $status_update_array,
+ ];
} catch (\Throwable $th) {
$errorData = [
diff --git a/app/Libraries/TPAClaimsImportServices/BaseTpaClaimImportService.php b/app/Libraries/TPAClaimsImportServices/BaseTpaClaimImportService.php
index 467fceba..d5df02fc 100644
--- a/app/Libraries/TPAClaimsImportServices/BaseTpaClaimImportService.php
+++ b/app/Libraries/TPAClaimsImportServices/BaseTpaClaimImportService.php
@@ -116,16 +116,28 @@ abstract class BaseTpaClaimImportService
// Check if mapping failed
if (!$ticketMasterData['status']) {
+ // Already-processed dump rows (ticket_id linked) must not be deleted as a "failure".
+ if (!empty($ticketMasterData['already_processed'])) {
+ $this->db->transCommit();
+ return [
+ 'status' => true,
+ 'message' => $ticketMasterData['message'] ?? 'Claim dump already processed for this file.',
+ ];
+ }
+
$this->rollbackAndCleanupClaimDumpData($file_id);
return $ticketMasterData;
}
$message = '';
$hasExecutedTask = false;
- $status = true;
+ $hasInserts = !empty($ticketMasterData['mapped_array']);
+ $hasExistingTicketUpdates = !empty($ticketMasterData['status_update_array']);
+ $hasRejectedReasons = !empty($ticketMasterData['rejected_reason_array']);
+ $hasExistingTicketLinks = $this->hasExistingTicketLinkUpdates($ticketMasterData['rejected_reason_array'] ?? []);
// Process Mapped Data
- if (!empty($ticketMasterData['mapped_array'])) {
+ if ($hasInserts) {
$insert_res = $this->importClaimMaster($ticketMasterData['mapped_array']);
if (!$insert_res) {
return $this->failTicketMasterInsert($file_id, 'Ticket Master Claim bulk insert failed');
@@ -137,20 +149,33 @@ abstract class BaseTpaClaimImportService
$message .= 'Ticket Master Claim bulk insert success. ';
$hasExecutedTask = true;
- }else{
- $status = false;
}
- // Process Rejected Reasons
- if (!empty($ticketMasterData['rejected_reason_array'])) {
+ // Update existing tickets: status and/or missing claim_dump_ref_id
+ if ($hasExistingTicketUpdates) {
+ $update_status_res = $this->updateExistingTicketStatuses($ticketMasterData['status_update_array']);
+ if (!$update_status_res) {
+ return $this->failTicketMasterInsert($file_id, 'Updating existing tickets failed');
+ }
+
+ $message .= 'Existing ticket updated successfully. ';
+ $hasExecutedTask = true;
+ }
+
+ // Process Rejected Reasons (also writes ticket_id onto TPA dump rows for existing tickets)
+ if ($hasRejectedReasons) {
$update_res = $this->updateTicketMasterRejectedReasonInTPATable($ticketMasterData['rejected_reason_array']);
if (!$update_res) {
return $this->failTicketMasterInsert($file_id, 'Updating rejected reasons failed');
}
-
- $message .= empty($ticketMasterData['mapped_array'])
- ? 'Those employee or dependent not in our system. '
- : 'Ticket Master Claim rejected reason updated successfully. ';
+
+ if ($hasExistingTicketLinks) {
+ $message .= 'Existing claim dump ticket_id linked successfully. ';
+ } elseif (!$hasInserts && !$hasExistingTicketUpdates) {
+ $message .= 'Those employee or dependent not in our system. ';
+ } else {
+ $message .= 'Ticket Master Claim rejected reason updated successfully. ';
+ }
$hasExecutedTask = true;
}
@@ -162,6 +187,7 @@ abstract class BaseTpaClaimImportService
// 2. Commit the transaction
$this->db->transCommit();
+ $status = $hasInserts || $hasExistingTicketUpdates || $hasExistingTicketLinks;
if (!$status) {
$this->cleanupClaimDumpData($file_id);
}
@@ -323,22 +349,110 @@ abstract class BaseTpaClaimImportService
*/
protected function checkDublicateTicketMasterClaim(array $param): bool
{
- $ticketMaster = new TicketMasterModel();
- $ticket_master_data = $ticketMaster
- ->where('doa', $param['doa'])
- ->where('tpa_no', $param['tpa_no'])
- ->where('claim_amount', $param['claim_amount'])
- ->where('emp_code', $param['emp_code'])
- ->where('is_active', 1)
- ->findAll();
+ return $this->getExistingTicketMasterClaim($param) !== null;
+ }
- if(count($ticket_master_data) > 0){
+ /**
+ * Fetch existing ticket_master record matching claim identity keys.
+ */
+ protected function getExistingTicketMasterClaim(array $param): ?array
+ {
+ $ticketMaster = new TicketMasterModel();
+ $ticket = $ticketMaster
+ ->where('doa', $param['doa'])
+ ->where('tpa_no', $param['tpa_no'])
+ ->where('claim_amount', $param['claim_amount'])
+ ->where('emp_code', $param['emp_code'])
+ ->where('is_active', 1)
+ ->first();
+
+ return $ticket ?: null;
+ }
+
+ /**
+ * Update existing ticket_master rows (status and/or claim_dump_ref_id).
+ */
+ protected function updateExistingTicketStatuses(array $statusUpdates): bool
+ {
+ if (empty($statusUpdates)) {
return true;
}
+ $ticketMasterModel = new TicketMasterModel();
+ return $ticketMasterModel->updateBatch($statusUpdates, 'id') !== false;
+ }
+
+ /**
+ * True when rejected_reason rows include ticket_id links for existing tickets.
+ */
+ protected function hasExistingTicketLinkUpdates(array $rejectedReasonArray): bool
+ {
+ foreach ($rejectedReasonArray as $row) {
+ if (!empty($row['ticket_id'])) {
+ return true;
+ }
+ }
+
return false;
}
+ /**
+ * If ticket already exists:
+ * - update claim_status_id when changed
+ * - set claim_dump_ref_id on ticket_master when null
+ * - set ticket_id on TPA dump row when null (via rejected_reason_array)
+ *
+ * Returns true when the row was handled as an existing ticket (caller should continue).
+ */
+ protected function handleExistingTicketStatusUpdate(
+ ?array $existingTicket,
+ int $newStatusId,
+ int $dumpRowId,
+ array &$statusUpdateArray,
+ array &$rejectedReasonArray
+ ): bool {
+ if (empty($existingTicket)) {
+ return false;
+ }
+
+ $ticketId = $existingTicket['id'];
+ $currentStatusId = (int) ($existingTicket['claim_status_id'] ?? 0);
+ $statusChanged = $currentStatusId !== (int) $newStatusId;
+ $claimDumpRefIdMissing = empty($existingTicket['claim_dump_ref_id']);
+
+ $ticketUpdate = ['id' => $ticketId];
+ $reasons = [];
+
+ if ($statusChanged) {
+ $ticketUpdate['claim_status_id'] = $newStatusId;
+ $reasons[] = 'status updated';
+ }
+
+ if ($claimDumpRefIdMissing) {
+ $ticketUpdate['claim_dump_ref_id'] = $dumpRowId;
+ $reasons[] = 'claim_dump_ref_id linked';
+ }
+
+ if (count($ticketUpdate) > 1) {
+ $statusUpdateArray[] = $ticketUpdate;
+ }
+
+ if ($statusChanged || $claimDumpRefIdMissing) {
+ $reason = 'Existing claim ' . implode(' and ', $reasons) . '.';
+ } else {
+ $reason = 'This claim already exists in our system.';
+ }
+
+ // Dump rows reaching here already have ticket_id NULL; link them to the existing ticket.
+ $rejectedReasonArray[] = [
+ 'id' => $dumpRowId,
+ 'master_reject_reason' => $reason,
+ 'ticket_id' => $ticketId,
+ ];
+
+ return true;
+ }
+
/**
* Dublicate check in the TPA specific table records
*/
@@ -365,6 +479,32 @@ abstract class BaseTpaClaimImportService
->getResultArray();
}
+ /**
+ * Response when no pending dump rows are left for ticket_master mapping.
+ * Marks already-processed files so cleanup does not delete linked dump rows.
+ */
+ protected function emptyClaimMasterMappingResponse(string $table, int $fileId): array
+ {
+ $alreadyProcessed = $this->db->table($table)
+ ->where('file_id', $fileId)
+ ->where('is_active', 1)
+ ->groupStart()
+ ->where('ticket_id IS NOT NULL', null, false)
+ ->orWhere('master_reject_reason IS NOT NULL', null, false)
+ ->groupEnd()
+ ->countAllResults() > 0;
+
+ if ($alreadyProcessed) {
+ return [
+ 'status' => false,
+ 'already_processed' => true,
+ 'message' => 'Claim dump already processed for this file.',
+ ];
+ }
+
+ return ['status' => false, 'message' => 'No data to insert in TICKET MASTER'];
+ }
+
/**
* Dublicate check in the TPA specific table records
*/
diff --git a/app/Libraries/TPAClaimsImportServices/FhplClaimImportService.php b/app/Libraries/TPAClaimsImportServices/FhplClaimImportService.php
index 653043ef..e436be0a 100644
--- a/app/Libraries/TPAClaimsImportServices/FhplClaimImportService.php
+++ b/app/Libraries/TPAClaimsImportServices/FhplClaimImportService.php
@@ -308,20 +308,6 @@ class FhplClaimImportService extends BaseTpaClaimImportService
$item[$value] = change_date_format($item[$value] ?? null, 'd-M-y', 'Y-m-d');
}
- $params = [
- 'admission_date' => $item['admission_date'] ?? null,
- 'employee_id' => $item['employee_id'] ?? null,
- 'claim_amount' => $item['claim_amount'] ?? null,
- 'uhid_no' => $item['uhid_no'] ?? null
- ];
-
- $is_duplicate = $this->checkDuplicateTpaClaim('claims_dump_fhpl', $params);
-
- if ($is_duplicate) {
- $item = [];
- continue;
- }
-
$item['file_id'] = $file_id ?? null;
$item['client_id'] = $file_data['client_id'] ?? null;
$item['client_policy_id'] = $file_data['client_policy_id'] ?? null;
@@ -342,7 +328,7 @@ class FhplClaimImportService extends BaseTpaClaimImportService
$tpaClaimDumpData = $this->getTpaClaimDumpData('claims_dump_fhpl', ['file_id' => $file_id]);
if (empty($tpaClaimDumpData)) {
- return ['status' => false, 'message' => "No data to insert in TICKET MASTER"];
+ return $this->emptyClaimMasterMappingResponse('claims_dump_fhpl', (int) $file_id);
}
@@ -368,6 +354,7 @@ class FhplClaimImportService extends BaseTpaClaimImportService
$mapped = [];
$rejecetd_reason = [];
+ $status_update_array = [];
foreach ($tpaClaimDumpData as $row) {
@@ -378,11 +365,16 @@ class FhplClaimImportService extends BaseTpaClaimImportService
'tpa_no' => $row['uhid_no'] ?? null
];
- $isduplicate = $this->checkDublicateTicketMasterClaim($params);
+ $newStatusId = $this->checkStatusMapping($this->statusMapping, $row['current_claim_status'] ?? '') ?? 61;
+ $existingTicket = $this->getExistingTicketMasterClaim($params);
- if ($isduplicate) {
- $reason = "This claim already exists in our system.";
- $rejecetd_reason[] = ["id" => $row['id'], "master_reject_reason" => $reason];
+ if ($this->handleExistingTicketStatusUpdate(
+ $existingTicket,
+ $newStatusId,
+ (int) $row['id'],
+ $status_update_array,
+ $rejecetd_reason
+ )) {
continue;
}
@@ -424,7 +416,7 @@ class FhplClaimImportService extends BaseTpaClaimImportService
}
// Meta fields
- $item['claim_status_id'] = $this->checkStatusMapping($this->statusMapping, $row['current_claim_status']) ?? 61;
+ $item['claim_status_id'] = $newStatusId;
$item['file_id'] = $file_id;
$item['claim_dump_ref_id'] = $row['id'];
$item['claim_dump_date'] = $file_data['claim_dump_date'] ?? null;
@@ -438,7 +430,12 @@ class FhplClaimImportService extends BaseTpaClaimImportService
$mapped[] = $item;
}
- return ['status' => true, 'mapped_array' => $mapped, 'rejected_reason_array' => $rejecetd_reason];
+ return [
+ 'status' => true,
+ 'mapped_array' => $mapped,
+ 'rejected_reason_array' => $rejecetd_reason,
+ 'status_update_array' => $status_update_array,
+ ];
} catch (\Throwable $th) {
diff --git a/app/Libraries/TPAClaimsImportServices/IciciClaimImportService.php b/app/Libraries/TPAClaimsImportServices/IciciClaimImportService.php
index 15da3177..b4d61ebd 100644
--- a/app/Libraries/TPAClaimsImportServices/IciciClaimImportService.php
+++ b/app/Libraries/TPAClaimsImportServices/IciciClaimImportService.php
@@ -223,20 +223,6 @@ class IciciClaimImportService extends BaseTpaClaimImportService
$item[$value] = change_date_format($item[$value] ?? null);
}
- $params = [
- 'doa' => change_date_format($item['doa'] ?? '') ?? null,
- 'employee_member_id' => $item['employee_member_id'] ?? null,
- 'claimed_amount' => $item['claimed_amount'] ?? null,
- 'uhid' => $item['uhid'] ?? null
- ];
-
- $is_duplicate = $this->checkDuplicateTpaClaim('claims_dump_icici', $params);
-
- if ($is_duplicate) {
- $item = [];
- continue;
- }
-
$item['file_id'] = $file_id ?? null;
$item['client_id'] = $file_data['client_id'] ?? null;
$item['client_policy_id'] = $file_data['client_policy_id'] ?? null;
@@ -257,7 +243,7 @@ class IciciClaimImportService extends BaseTpaClaimImportService
$tpaClaimDumpData = $this->getTpaClaimDumpData('claims_dump_icici', ['file_id' => $file_id]);
if (empty($tpaClaimDumpData)) {
- return ['status' => false, 'message' => "No data to insert in TICKET MASTER"];
+ return $this->emptyClaimMasterMappingResponse('claims_dump_icici', (int) $file_id);
}
@@ -283,21 +269,27 @@ class IciciClaimImportService extends BaseTpaClaimImportService
$mapped = [];
$rejecetd_reason = [];
+ $status_update_array = [];
foreach ($tpaClaimDumpData as $row) {
$params = [
'doa' => change_date_format($row['doa'] ?? '') ?? null,
'emp_code' => $row['employee_member_id'] ?? null,
- 'claim_amount' => $row['claim_amount'] ?? null,
+ 'claim_amount' => $row['claimed_amount'] ?? null,
'tpa_no' => $row['uhid'] ?? null
];
- $isduplicate = $this->checkDublicateTicketMasterClaim($params);
+ $newStatusId = $this->checkStatusMapping($this->statusMapping, $row['updated_status'] ?? '') ?? 61;
+ $existingTicket = $this->getExistingTicketMasterClaim($params);
- if ($isduplicate) {
- $reason = "This claim already exists in our system.";
- $rejecetd_reason[] = ["id" => $row['id'], "master_reject_reason" => $reason];
+ if ($this->handleExistingTicketStatusUpdate(
+ $existingTicket,
+ $newStatusId,
+ (int) $row['id'],
+ $status_update_array,
+ $rejecetd_reason
+ )) {
continue;
}
@@ -339,7 +331,7 @@ class IciciClaimImportService extends BaseTpaClaimImportService
}
// Meta fields
- $item['claim_status_id'] = $this->checkStatusMapping($this->statusMapping, $row['updated_status']) ?? 61;
+ $item['claim_status_id'] = $newStatusId;
$item['claim_dump_ref_id'] = $row['id'];
$item['file_id'] = $file_id;
$item['claim_dump_date'] = $file_data['claim_dump_date'] ?? null;
@@ -353,7 +345,12 @@ class IciciClaimImportService extends BaseTpaClaimImportService
$mapped[] = $item;
}
- return ['status' => true, 'mapped_array' => $mapped, 'rejected_reason_array' => $rejecetd_reason];
+ return [
+ 'status' => true,
+ 'mapped_array' => $mapped,
+ 'rejected_reason_array' => $rejecetd_reason,
+ 'status_update_array' => $status_update_array,
+ ];
} catch (\Throwable $th) {
diff --git a/app/Libraries/TPAClaimsImportServices/MediAssistClaimImportService.php b/app/Libraries/TPAClaimsImportServices/MediAssistClaimImportService.php
index a6ea7d0c..e2533924 100644
--- a/app/Libraries/TPAClaimsImportServices/MediAssistClaimImportService.php
+++ b/app/Libraries/TPAClaimsImportServices/MediAssistClaimImportService.php
@@ -256,20 +256,6 @@ class MediAssistClaimImportService extends BaseTpaClaimImportService
$item[$dbColumn] = $value;
}
- $params = [
- 'date_of_admission' => change_date_format($item['date_of_admission'] ?? '') ?? null,
- 'pribenef_employee_code' => $item['pribenef_employee_code'] ?? null,
- 'claim_amount' => $item['claim_amount'] ?? null,
- 'event_id' => $item['event_id'] ?? null
- ];
-
- $is_duplicate = $this->checkDuplicateTpaClaim('claims_dump_medi_assist', $params);
-
- if ($is_duplicate) {
- $item = [];
- continue;
- }
-
$item['file_id'] = $file_id ?? null;
$item['client_id'] = $file_data['client_id'] ?? null;
$item['client_policy_id'] = $file_data['client_policy_id'] ?? null;
@@ -290,7 +276,7 @@ class MediAssistClaimImportService extends BaseTpaClaimImportService
$tpaClaimDumpData = $this->getTpaClaimDumpData('claims_dump_medi_assist', ['file_id' => $file_id]);
if (empty($tpaClaimDumpData)) {
- return ['status' => false, 'message' => "No data to insert in TICKET MASTER"];
+ return $this->emptyClaimMasterMappingResponse('claims_dump_medi_assist', (int) $file_id);
}
@@ -316,6 +302,7 @@ class MediAssistClaimImportService extends BaseTpaClaimImportService
$mapped = [];
$rejecetd_reason = [];
+ $status_update_array = [];
foreach ($tpaClaimDumpData as $row) {
@@ -326,11 +313,16 @@ class MediAssistClaimImportService extends BaseTpaClaimImportService
'tpa_no' => $row['event_id'] ?? null
];
- $isduplicate = $this->checkDublicateTicketMasterClaim($params);
+ $newStatusId = $this->checkStatusMapping($this->statusMapping, $row['claim_status'] ?? '') ?? 61;
+ $existingTicket = $this->getExistingTicketMasterClaim($params);
- if ($isduplicate) {
- $reason = "This claim already exists in our system.";
- $rejecetd_reason[] = ["id" => $row['id'], "master_reject_reason" => $reason];
+ if ($this->handleExistingTicketStatusUpdate(
+ $existingTicket,
+ $newStatusId,
+ (int) $row['id'],
+ $status_update_array,
+ $rejecetd_reason
+ )) {
continue;
}
@@ -374,7 +366,7 @@ class MediAssistClaimImportService extends BaseTpaClaimImportService
// Meta fields
$item['claim_dump_ref_id'] = $row['id'];
$item['file_id'] = $file_id;
- $item['claim_status_id'] = $this->checkStatusMapping($this->statusMapping, $row['claim_status']) ?? 61;
+ $item['claim_status_id'] = $newStatusId;
$item['claim_dump_date'] = $file_data['claim_dump_date'] ?? null;
$item['created_by'] = $file_data['created_by'] ?? null;
$item['claim_type'] = 1;
@@ -386,7 +378,12 @@ class MediAssistClaimImportService extends BaseTpaClaimImportService
$mapped[] = $item;
}
- return ['status' => true, 'mapped_array' => $mapped, 'rejected_reason_array' => $rejecetd_reason];
+ return [
+ 'status' => true,
+ 'mapped_array' => $mapped,
+ 'rejected_reason_array' => $rejecetd_reason,
+ 'status_update_array' => $status_update_array,
+ ];
} catch (\Throwable $th) {
diff --git a/app/Libraries/TPAClaimsImportServices/RcareClaimImportService.php b/app/Libraries/TPAClaimsImportServices/RcareClaimImportService.php
index 0b93f149..646a63e9 100644
--- a/app/Libraries/TPAClaimsImportServices/RcareClaimImportService.php
+++ b/app/Libraries/TPAClaimsImportServices/RcareClaimImportService.php
@@ -208,20 +208,6 @@ class RcareClaimImportService extends BaseTpaClaimImportService
$item[$value] = change_date_format($item[$value] ?? null, 'd-M-y', 'Y-m-d');
}
- $params = [
- 'doa_opd_treatment_from' => $item['doa_opd_treatment_from'] ?? null,
- 'employee_member_id' => $item['employee_member_id'] ?? null,
- 'claimed_amount' => $item['claimed_amount'] ?? null,
- 'uhid' => $item['uhid'] ?? null
- ];
-
- $is_duplicate = $this->checkDuplicateTpaClaim('claims_dump_reliance', $params);
-
- if ($is_duplicate) {
- $item = [];
- continue;
- }
-
$item['file_id'] = $file_id ?? null;
$item['client_id'] = $file_data['client_id'] ?? null;
$item['client_policy_id'] = $file_data['client_policy_id'] ?? null;
@@ -242,7 +228,7 @@ class RcareClaimImportService extends BaseTpaClaimImportService
$tpaClaimDumpData = $this->getTpaClaimDumpData('claims_dump_reliance', ['file_id' => $file_id]);
if (empty($tpaClaimDumpData)) {
- return ['status' => false, 'message' => "No data to insert in TICKET MASTER"];
+ return $this->emptyClaimMasterMappingResponse('claims_dump_reliance', (int) $file_id);
}
@@ -268,6 +254,7 @@ class RcareClaimImportService extends BaseTpaClaimImportService
$mapped = [];
$rejecetd_reason = [];
+ $status_update_array = [];
foreach ($tpaClaimDumpData as $row) {
@@ -278,11 +265,16 @@ class RcareClaimImportService extends BaseTpaClaimImportService
'tpa_no' => $row['uhid'] ?? null
];
- $isduplicate = $this->checkDublicateTicketMasterClaim($params);
+ $newStatusId = $this->checkStatusMapping($this->statusMapping, $row['final_status'] ?? '') ?? 61;
+ $existingTicket = $this->getExistingTicketMasterClaim($params);
- if ($isduplicate) {
- $reason = "This claim already exists in our system.";
- $rejecetd_reason[] = ["id" => $row['id'], "master_reject_reason" => $reason];
+ if ($this->handleExistingTicketStatusUpdate(
+ $existingTicket,
+ $newStatusId,
+ (int) $row['id'],
+ $status_update_array,
+ $rejecetd_reason
+ )) {
continue;
}
@@ -324,7 +316,7 @@ class RcareClaimImportService extends BaseTpaClaimImportService
}
// Meta fields
- $item['claim_status_id'] = $this->checkStatusMapping($this->statusMapping, $row['final_status']) ?? 61;
+ $item['claim_status_id'] = $newStatusId;
$item['file_id'] = $file_id;
$item['created_by'] = $file_data['created_by'] ?? null;
$item['claim_dump_ref_id'] = $row['id'];
@@ -338,7 +330,12 @@ class RcareClaimImportService extends BaseTpaClaimImportService
$mapped[] = $item;
}
- return ['status' => true, 'mapped_array' => $mapped, 'rejected_reason_array' => $rejecetd_reason];
+ return [
+ 'status' => true,
+ 'mapped_array' => $mapped,
+ 'rejected_reason_array' => $rejecetd_reason,
+ 'status_update_array' => $status_update_array,
+ ];
} catch (\Throwable $th) {
diff --git a/app/Libraries/TPAClaimsImportServices/VidalClaimImportService.php b/app/Libraries/TPAClaimsImportServices/VidalClaimImportService.php
index a0876b92..fd628cc9 100644
--- a/app/Libraries/TPAClaimsImportServices/VidalClaimImportService.php
+++ b/app/Libraries/TPAClaimsImportServices/VidalClaimImportService.php
@@ -455,20 +455,6 @@ class VidalClaimImportService extends BaseTpaClaimImportService
$item[$dbColumn] = $value;
}
- $params = [
- 'date_of_admission' => change_date_format($item['date_of_admission'] ?? '') ?? null,
- 'employee_number' => $item['employee_number'] ?? null,
- 'claim_amount' => $item['claim_amount'] ?? null,
- 'primary_policy_holder_card_id' => $item['primary_policy_holder_card_id'] ?? null
- ];
-
- $is_duplicate = $this->checkDuplicateTpaClaim('claims_dump_vidal', $params);
-
- if ($is_duplicate) {
- $item = [];
- continue;
- }
-
$item['file_id'] = $file_id ?? null;
$item['client_id'] = $file_data['client_id'] ?? null;
$item['client_policy_id'] = $file_data['client_policy_id'] ?? null;
@@ -489,7 +475,7 @@ class VidalClaimImportService extends BaseTpaClaimImportService
$tpaClaimDumpData = $this->getTpaClaimDumpData('claims_dump_vidal', ['file_id' => $file_id]);
if (empty($tpaClaimDumpData)) {
- return ['status' => false, 'message' => "No data to insert in TICKET MASTER"];
+ return $this->emptyClaimMasterMappingResponse('claims_dump_vidal', (int) $file_id);
}
@@ -515,6 +501,7 @@ class VidalClaimImportService extends BaseTpaClaimImportService
$mapped = [];
$rejecetd_reason = [];
+ $status_update_array = [];
foreach ($tpaClaimDumpData as $row) {
@@ -525,11 +512,16 @@ class VidalClaimImportService extends BaseTpaClaimImportService
'tpa_no' => $row['primary_policy_holder_card_id'] ?? null
];
- $isduplicate = $this->checkDublicateTicketMasterClaim($params);
+ $newStatusId = $this->checkStatusMapping($this->statusMapping, $row['claim_status'] ?? '') ?? 61;
+ $existingTicket = $this->getExistingTicketMasterClaim($params);
- if ($isduplicate) {
- $reason = "This claim already exists in our system.";
- $rejecetd_reason[] = ["id" => $row['id'], "master_reject_reason" => $reason];
+ if ($this->handleExistingTicketStatusUpdate(
+ $existingTicket,
+ $newStatusId,
+ (int) $row['id'],
+ $status_update_array,
+ $rejecetd_reason
+ )) {
continue;
}
@@ -565,7 +557,7 @@ class VidalClaimImportService extends BaseTpaClaimImportService
}
// Meta fields
- $item['claim_status_id'] = $this->checkStatusMapping($this->statusMapping, $row['claim_status']) ?? 61;
+ $item['claim_status_id'] = $newStatusId;
$item['file_id'] = $file_id;
$item['claim_dump_ref_id'] = $row['id'];
$item['claim_dump_date'] = $file_data['claim_dump_date'] ?? null;
@@ -579,7 +571,12 @@ class VidalClaimImportService extends BaseTpaClaimImportService
$mapped[] = $item;
}
- return ['status' => true, 'mapped_array' => $mapped, 'rejected_reason_array' => $rejecetd_reason];
+ return [
+ 'status' => true,
+ 'mapped_array' => $mapped,
+ 'rejected_reason_array' => $rejecetd_reason,
+ 'status_update_array' => $status_update_array,
+ ];
} catch (\Throwable $th) {
diff --git a/app/Models/BdsPlacementModel.php b/app/Models/BdsPlacementModel.php
index 341e16a2..ff1fbc61 100644
--- a/app/Models/BdsPlacementModel.php
+++ b/app/Models/BdsPlacementModel.php
@@ -135,37 +135,56 @@ class BdsPlacementModel extends Model
{
/** @var BdsConfig $config */
$config = config(BdsConfig::class);
- // print_r($config);die();
if (!$config->shouldFetchInstallmentRemindersToday()) {
return [];
}
- $heads = $this->db->table('user_profiles')
- ->select('email')->where(['role' => 5, 'is_active' => 1])
- ->get()->getResultArray();
+ // $heads = $this->db->table('user_profiles')
+ // ->select('email')->where(['role' => 5, 'is_active' => 1])
+ // ->get()->getResultArray();
- $admins = $this->db->table('user_profiles')
- ->select('email')->where(['role' => 1, 'is_active' => 1])
- ->get()->getResultArray();
+ // $admins = $this->db->table('user_profiles')
+ // ->select('email')->where(['role' => 1, 'is_active' => 1])
+ // ->get()->getResultArray();
- $businessTeam = $this->db->table("user_teams ut")
- ->select("up.email")
- ->join('user_profiles up', 'up.id = ut.user_id AND up.is_active = 1')
- ->where(["ut.team_id" => 7, "ut.is_active" => 1])
- ->get()->getResultArray();
+ // $businessTeam = $this->db->table("user_teams ut")
+ // ->select("up.email")
+ // ->join('user_profiles up', 'up.id = ut.user_id AND up.is_active = 1')
+ // ->where(["ut.team_id" => 7, "ut.is_active" => 1])
+ // ->get()->getResultArray();
$builder = $this->db->table("lead_installment_payment_details lipd")
- ->select("lipd.*, COALESCE(ct.client_name, leads.client_name) as client_name, COALESCE(ct.short_name, leads.client_short_name) as short_name, COALESCE(cb.branch_name, leads.branch_name) as branch_name, leads.salse_person_id, leads.contact_person_email, cp.policy_no")
+ ->select("
+ lipd.*,
+ COALESCE(ct.client_name, leads.client_name) as client_name,
+ COALESCE(ct.short_name, leads.client_short_name) as short_name,
+ COALESCE(cb.branch_name, leads.branch_name) as branch_name,
+ leads.salse_person_id,
+ leads.contact_person_email,
+ leads.contact_person_name,
+ leads.contact_person_mobile,
+ COALESCE(cp.policy_no, cp_src.policy_no) as policy_no,
+ COALESCE(cp.policy_start_date, cp_src.policy_start_date) as policy_start_date,
+ COALESCE(cp.policy_end_date, cp_src.policy_end_date) as policy_end_date,
+ COALESCE(ins.name, ins_src.name) as insurer_name,
+ COALESCE(pt.policy_type, pt_src.policy_type) as policy_type,
+ leads.acm_id,
+ leads.is_policy_created
+ ")
->join("leads", "leads.id = lipd.lead_id")
->join("clients ct", "ct.id = leads.client_id", "left")
->join("client_branch cb", "cb.id = leads.client_branch_id", "left")
- ->join("client_policy cp", "cp.id = leads.source_policy_id", "left")
+ ->join("client_policy cp", "cp.id = leads.is_policy_created", "left")
+ ->join("client_policy cp_src", "cp_src.id = leads.source_policy_id", "left")
+ ->join("insurers ins", "ins.id = cp.insurer_id", "left")
+ ->join("insurers ins_src", "ins_src.id = cp_src.insurer_id", "left")
+ ->join("policy_type pt", "pt.id = cp.policy_type_id", "left")
+ ->join("policy_type pt_src", "pt_src.id = cp_src.policy_type_id", "left")
->where("lipd.is_active", 1)
->where("lipd.utr_no IS NULL OR lipd.utr_no = ''");
$targetPaymentDate = $this->addBusinessDays($config->installmentReminderBusinessDays);
- // print_r($targetPaymentDate);die();
if ($config->installmentReminderFetchOverduePendingUtr) {
$builder->groupStart()
@@ -178,27 +197,46 @@ class BdsPlacementModel extends Model
$data = $builder->get()->getResultArray();
- // print_r($this->db->getLastQuery()->getQuery());die();
-
foreach ($data as &$row) {
$sales_person_ids = json_decode($row['salse_person_id'], true);
$sales_person_id = $sales_person_ids[0] ?? null;
+ $acm_id = $row['acm_id'] ?? null;
+
+ if ($acm_id) {
+ $acm_user = $this->db->table('user_profiles')
+ ->select('email, first_name, last_name')
+ ->where('id', (int) $acm_id)
+ ->get()
+ ->getRowArray();
+
+ $row['acm_email'] = $acm_user['email'] ?? 'N/A';
+ $row['acm_name'] = trim(
+ ($acm_user['first_name'] ?? '') . ' ' . ($acm_user['last_name'] ?? '')
+ ) ?: 'Not Assigned';
+ } else {
+ $row['acm_email'] = 'N/A';
+ $row['acm_name'] = 'Not Assigned';
+ }
if ($sales_person_id) {
$user = $this->db->table('user_profiles')
- ->select('email')
+ ->select('email, first_name, last_name')
->where('id', (int) $sales_person_id)
->get()
->getRowArray();
$row['sales_person'] = $user['email'] ?? 'N/A';
+ $row['sales_person_name'] = trim(
+ ($user['first_name'] ?? '') . ' ' . ($user['last_name'] ?? '')
+ ) ?: 'Not Assigned';
} else {
$row['sales_person'] = 'Not Assigned';
+ $row['sales_person_name'] = 'Not Assigned';
}
- $row['heads'] = $heads;
- $row['admins'] = $admins;
- $row['buisness_team'] = $businessTeam;
+ // $row['heads'] = $heads;
+ // $row['admins'] = $admins;
+ // $row['buisness_team'] = $businessTeam;
}
return $data;
diff --git a/app/Models/PolicyTransactionModel.php b/app/Models/PolicyTransactionModel.php
index 2e520918..4f051a66 100644
--- a/app/Models/PolicyTransactionModel.php
+++ b/app/Models/PolicyTransactionModel.php
@@ -1136,6 +1136,136 @@
return $data;
}
+ public function getCachedInceptionTranctionListData(array $filters): array
+ {
+ $cacheKey = 'inception_list_v1_' . md5(json_encode($filters));
+ $cache = \Config\Services::cache();
+ $cached = $cache->get($cacheKey);
+
+ if (is_array($cached) && isset($cached['rows'], $cached['expires_at'])) {
+ return $cached;
+ }
+
+ $ttl = 300;
+ $rows = $this->getInceptionTranctionListData(
+ $filters['start_date'] ?? 0,
+ $filters['end_date'] ?? 0,
+ $filters['client_id'] ?? 0,
+ $filters['insurer_id'] ?? 0,
+ $filters['policy_type_id'] ?? 0,
+ $filters['date_type'] ?? 0,
+ $filters['issuer'] ?? 0,
+ $filters['status'] ?? 0,
+ $filters['ids'] ?? null
+ );
+
+ $payload = [
+ 'rows' => $rows,
+ 'expires_at' => time() + $ttl,
+ ];
+ $cache->save($cacheKey, $payload, $ttl);
+
+ return $payload;
+ }
+
+ public function filterInceptionTranctionRowsBySearch(array $rows, string $searchValue): array
+ {
+ $needle = mb_strtolower(trim($searchValue));
+ if ($needle === '') {
+ return $rows;
+ }
+
+ $issuerMap = [1 => 'jibs', 2 => 'nhance'];
+ $issueTypeMap = [1 => 'fresh', 2 => 'renewal', 3 => 'roll over'];
+ $clientTypeMap = [1 => 'group', 2 => 'individual'];
+ $statusMap = [
+ 'under_process' => 'under process',
+ 'client_pending' => 'client pending',
+ 'insurer_pending' => 'insurer pending',
+ 'co_insurer_pending' => 'co-insurer pending',
+ 'tpa_pending' => 'tpa pending',
+ 'validated' => 'validated',
+ 'cancelled' => 'cancelled',
+ 'instalment_pending' => 'instalment pending',
+ 'completed' => 'completed',
+ 'lost' => 'lost',
+ ];
+
+ $fields = [
+ 'client_name',
+ 'client_short_name',
+ 'client_branch_name',
+ 'insurer_short_name',
+ 'policy_type',
+ 'policy_no',
+ 'user_name',
+ 'status',
+ 'pan',
+ ];
+
+ return array_values(array_filter($rows, static function (array $row) use ($needle, $fields, $issuerMap, $issueTypeMap, $clientTypeMap, $statusMap) {
+ foreach ($fields as $field) {
+ $value = $row[$field] ?? '';
+ if ($value !== '' && mb_strpos(mb_strtolower((string) $value), $needle) !== false) {
+ return true;
+ }
+ }
+
+ // Search by rendered labels shown in list columns.
+ $issuerText = $issuerMap[(int) ($row['issuer'] ?? 0)] ?? '';
+ if ($issuerText !== '' && mb_strpos($issuerText, $needle) !== false) {
+ return true;
+ }
+
+ $issueTypeText = $issueTypeMap[(int) ($row['issue_type'] ?? 0)] ?? '';
+ if ($issueTypeText !== '' && mb_strpos($issueTypeText, $needle) !== false) {
+ return true;
+ }
+
+ $clientTypeText = $clientTypeMap[(int) ($row['client_type'] ?? 0)] ?? '';
+ if ($clientTypeText !== '' && mb_strpos($clientTypeText, $needle) !== false) {
+ return true;
+ }
+
+ $statusCode = (string) ($row['status'] ?? '');
+ $statusText = $statusMap[$statusCode] ?? '';
+ if ($statusText !== '' && mb_strpos($statusText, $needle) !== false) {
+ return true;
+ }
+
+ return false;
+ }));
+ }
+
+ public function getInceptionTranctionListDataTable(int $draw, int $start, int $length, string $searchValue, array $filters): array
+ {
+ $cached = $this->getCachedInceptionTranctionListData($filters);
+ $allRows = $cached['rows'] ?? [];
+ $recordsTotal = count($allRows);
+
+ if ($searchValue !== '') {
+ $allRows = $this->filterInceptionTranctionRowsBySearch($allRows, $searchValue);
+ }
+
+ $recordsFiltered = count($allRows);
+
+ if ($length < 0) {
+ $length = $recordsFiltered;
+ }
+
+ $pageRows = $length > 0
+ ? array_slice(array_values($allRows), $start, $length)
+ : array_values($allRows);
+
+ return [
+ 'draw' => $draw,
+ 'recordsTotal' => $recordsTotal,
+ 'recordsFiltered' => $recordsFiltered,
+ 'data' => $pageRows,
+ 'cache_expires_in_ms' => max(0, (($cached['expires_at'] ?? time()) - time()) * 1000),
+ ];
+ }
+
public function getEndorsementTranctionListData($start_date = 0, $end_date = 0, $client_id = 0, $insurer_id = 0, $policy_type_id = 0, $date_type = 0, $issuer = 0, $status = 0)
{
@@ -1248,6 +1378,136 @@
return $builder->get()->getResultArray();
}
+ public function getCachedEndorsementTranctionListData(array $filters): array
+ {
+ $cacheKey = 'endorsement_list_v1_' . md5(json_encode($filters));
+ $cache = \Config\Services::cache();
+ $cached = $cache->get($cacheKey);
+
+ if (is_array($cached) && isset($cached['rows'], $cached['expires_at'])) {
+ return $cached;
+ }
+
+ $ttl = 300;
+ $rows = $this->getEndorsementTranctionListData(
+ $filters['start_date'] ?? 0,
+ $filters['end_date'] ?? 0,
+ $filters['client_id'] ?? 0,
+ $filters['insurer_id'] ?? 0,
+ $filters['policy_type_id'] ?? 0,
+ $filters['date_type'] ?? 0,
+ $filters['issuer'] ?? 0,
+ $filters['status'] ?? 0
+ );
+
+ $payload = [
+ 'rows' => $rows,
+ 'expires_at' => time() + $ttl,
+ ];
+ $cache->save($cacheKey, $payload, $ttl);
+
+ return $payload;
+ }
+
+ public function filterEndorsementTranctionRowsBySearch(array $rows, string $searchValue): array
+ {
+ $needle = mb_strtolower(trim($searchValue));
+ if ($needle === '') {
+ return $rows;
+ }
+
+ $issuerMap = [1 => 'jibs', 2 => 'nhance'];
+ $statusMap = [
+ 'under_process' => 'under process',
+ 'client_pending' => 'client pending',
+ 'insurer_pending' => 'insurer pending',
+ 'co_insurer_pending' => 'co-insurer pending',
+ 'tpa_pending' => 'tpa pending',
+ 'validated' => 'validated',
+ 'cancelled' => 'cancelled',
+ 'instalment_pending' => 'instalment pending',
+ 'completed' => 'completed',
+ ];
+ $actionTypeMap = [
+ 'addition' => 'addition',
+ 'deletion' => 'deletion',
+ 'addition_deletion' => 'addition & deletion',
+ 'si_enhancement' => 'si enhancement',
+ 'combo_a_d_si' => 'combo a, d & si',
+ 'correction' => 'correction',
+ 'baby_addition' => 'baby addition',
+ 'policy_instalment' => 'policy instalment',
+ 'addition_inception' => 'addition-inception',
+ 'bds_correction' => 'bds correction',
+ 'policy_correction' => 'policy correction',
+ 'policy_cancellation' => 'policy cancellation',
+ ];
+
+ $fields = [
+ 'client_short_name',
+ 'client_branch_name',
+ 'insurer_short_name',
+ 'policy_type',
+ 'endorsement_no',
+ 'policy_no',
+ ];
+
+ return array_values(array_filter($rows, static function (array $row) use ($needle, $fields, $issuerMap, $statusMap, $actionTypeMap) {
+ foreach ($fields as $field) {
+ $value = $row[$field] ?? '';
+ if ($value !== '' && mb_strpos(mb_strtolower((string) $value), $needle) !== false) {
+ return true;
+ }
+ }
+
+ $issuerText = $issuerMap[(int) ($row['issuer'] ?? 0)] ?? '';
+ if ($issuerText !== '' && mb_strpos($issuerText, $needle) !== false) {
+ return true;
+ }
+
+ $statusText = $statusMap[(string) ($row['status'] ?? '')] ?? '';
+ if ($statusText !== '' && mb_strpos($statusText, $needle) !== false) {
+ return true;
+ }
+
+ $actionTypeText = $actionTypeMap[(string) ($row['action_type'] ?? '')] ?? '';
+ if ($actionTypeText !== '' && mb_strpos($actionTypeText, $needle) !== false) {
+ return true;
+ }
+
+ return false;
+ }));
+ }
+
+ public function getEndorsementTranctionListDataTable(int $draw, int $start, int $length, string $searchValue, array $filters): array
+ {
+ $cached = $this->getCachedEndorsementTranctionListData($filters);
+ $allRows = $cached['rows'] ?? [];
+ $recordsTotal = count($allRows);
+
+ if ($searchValue !== '') {
+ $allRows = $this->filterEndorsementTranctionRowsBySearch($allRows, $searchValue);
+ }
+
+ $recordsFiltered = count($allRows);
+
+ if ($length < 0) {
+ $length = $recordsFiltered;
+ }
+
+ $pageRows = $length > 0
+ ? array_slice(array_values($allRows), $start, $length)
+ : array_values($allRows);
+
+ return [
+ 'draw' => $draw,
+ 'recordsTotal' => $recordsTotal,
+ 'recordsFiltered' => $recordsFiltered,
+ 'data' => $pageRows,
+ 'cache_expires_in_ms' => max(0, (($cached['expires_at'] ?? time()) - time()) * 1000),
+ ];
+ }
+
public function getVarienceReportLIst($start_date = 0, $end_date = 0, $client_id = 0, $insurer_id = 0, $policy_type_id = 0, $date_type = 0, $issuer = 0, $client_branch_id = 0, $insurer_branch_id = 0, $client_policy_id = 0)
{
$builder = $this->db->table('policy_transaction')
@@ -3099,11 +3359,15 @@
}
}
- // 2. Dynamic $where array
+ // 2. Dynamic $where (string SQL fragment or column => value map)
if (!empty($where)) {
- foreach ($where as $column => $value) {
- $value = addslashes($value);
- $conditions .= " AND `$column` = '$value' ";
+ if (is_string($where)) {
+ $conditions .= ' AND ' . $where . ' ';
+ } else {
+ foreach ($where as $column => $value) {
+ $value = addslashes($value);
+ $conditions .= " AND `$column` = '$value' ";
+ }
}
}
@@ -3739,119 +4003,245 @@
$query = $this->db->query($sql);
$result = $query->getResultArray();
+ return $this->processBDSReportResults($result);
+ }
- // $countofalldata = count($result);
- // Kint::dump($result);
- // dd($this->db->getLastQuery()->getQuery());
-
+ /**
+ * Post-process raw BDS report rows (dedup, rewards, unbilled amounts).
+ */
+ public function processBDSReportResults(array $result): array
+ {
$keys = [];
$filtered = [];
foreach ($result as $row) {
-
- // Normalize endorsement number
$endorsement_number = !empty($row['endorsement_no']) ? $row['endorsement_no'] : '-';
$reward = (float) ($row['reward'] ?? 0);
$billed_amt = (float) ($row['billed_amt'] ?? 0);
- if($reward == 0.00 && $billed_amt == 0.00 && $row['statement_uploaded'] === 'statement uploaded'){
+ if ($reward == 0.00 && $billed_amt == 0.00 && $row['statement_uploaded'] === 'statement uploaded') {
continue;
}
- if ($reward > 0 && ($row['billed_amt'] ?? 0) == 0.00) {
- $row['total_irda_amt'] = '0.00';
- $row['billed_amt'] = $reward;
- $rewardFlag = 'R'; // Reward row
- } else {
- $rewardFlag = 'N'; // Normal row
+ if ($reward > 0 && ($row['billed_amt'] ?? 0) == 0.00) {
+ $row['total_irda_amt'] = '0.00';
+ $row['billed_amt'] = $reward;
+ $rewardFlag = 'R';
+ } else {
+ $rewardFlag = 'N';
}
- // ✅ Stable key (NO reward flag)
$key = implode('|', [
$row['statement_year_month'],
$row['insurer_name'],
$row['policy_no'],
$endorsement_number,
- $rewardFlag
+ $rewardFlag,
]);
- // Prefer "statement uploaded"
if ($row['statement_uploaded'] === 'statement uploaded') {
$filtered[$key] = $row;
- $keys[$key] = true;
- }
- // Keep no-statement only if uploaded not present
- elseif (!isset($keys[$key])) {
+ $keys[$key] = true;
+ } elseif (!isset($keys[$key])) {
$filtered[$key] = $row;
}
}
- // Reindex final output
$result = array_values($filtered);
- // dd($result);
-
- // --------------------------------------------------------------------------------------------------------
-
$totalBilled = [];
$totalIrdaMap = [];
foreach ($result as $row) {
- $key = $row['pt_id'].'-'.$row['insurer_id'];
+ $key = $row['pt_id'] . '-' . $row['insurer_id'];
- // Sum billed amount
$totalBilled[$key] = ($totalBilled[$key] ?? 0) + (float) ($row['billed_amt'] ?? 0);
- // Store total_irda_amt once
if (!isset($totalIrdaMap[$key])) {
$totalIrdaMap[$key] = (float) $row['total_irda_amt'];
}
- if(($row['reward'] ?? 0) > 0){
- $totalIrdaMap[$key] = ($totalIrdaMap[$key] ?? 0) + (float) $row['reward'];
+ if (($row['reward'] ?? 0) > 0) {
+ $totalIrdaMap[$key] = ($totalIrdaMap[$key] ?? 0) + (float) $row['reward'];
}
}
- // dd($totalBilled, $totalIrdaMap);
-
$ptSeen = [];
$final = [];
foreach ($result as $row) {
- $ptId = $row['pt_id'].'-'.$row['insurer_id'];
+ $ptId = $row['pt_id'] . '-' . $row['insurer_id'];
if (!isset($ptSeen[$ptId])) {
-
- $totalIrdaVal = $totalIrdaMap[$ptId] ?? 0;
+ $totalIrdaVal = $totalIrdaMap[$ptId] ?? 0;
$totalBilledVal = $totalBilled[$ptId] ?? 0;
- $addMinus = false;
+ $addMinus = false;
- if($totalIrdaVal < 0){
- $totalIrdaVal = abs($totalIrdaVal);
+ if ($totalIrdaVal < 0) {
+ $totalIrdaVal = abs($totalIrdaVal);
$totalBilledVal = abs($totalBilledVal);
- $addMinus = true;
+ $addMinus = true;
}
- // First entry → set unbilled amount
- $row['unbilled_amount'] = round((float) ($totalIrdaVal - $totalBilledVal),2 );
+ $row['unbilled_amount'] = round((float) ($totalIrdaVal - $totalBilledVal), 2);
- if($addMinus){
+ if ($addMinus) {
$row['unbilled_amount'] = ($row['unbilled_amount'] * -1);
}
$ptSeen[$ptId] = true;
} else {
- // Other entries → zero
$row['unbilled_amount'] = '0.00';
}
$final[] = $row;
}
- $result = $final;
+ return $final;
+ }
- // dd($result); die;
- return $result;
+ /**
+ * Cached processed BDS report list for a given filter set.
+ */
+ public function getCachedBDSReportList(array $filters): array
+ {
+ $cacheKey = 'bds_report_v1_' . md5(json_encode($filters));
+ $cache = \Config\Services::cache();
+ $cached = $cache->get($cacheKey);
+
+ if (is_array($cached)) {
+ return $cached;
+ }
+
+ $processed = $this->getBDSReportList(
+ $filters['start_date'] ?? 0,
+ $filters['end_date'] ?? 0,
+ $filters['client_id'] ?? 0,
+ $filters['insurer_id'] ?? 0,
+ $filters['policy_type_id'] ?? 0,
+ $filters['date_type'] ?? 0,
+ $filters['issuer'] ?? 0,
+ $filters['client_branch_id'] ?? 0,
+ $filters['insurer_branch_id'] ?? 0,
+ $filters['client_policy_id'] ?? 0,
+ $filters['user_id'] ?? 0,
+ $filters['where'] ?? []
+ );
+
+ $cache->save($cacheKey, $processed, 300);
+
+ return $processed;
+ }
+
+ /**
+ * Server-side DataTables payload for BDS report.
+ */
+ public function getBDSReportListDataTable(int $draw, int $start, int $length, string $searchValue, array $filters): array
+ {
+ $allRows = $this->getCachedBDSReportList($filters);
+ $recordsTotal = count($allRows);
+
+ if ($searchValue !== '') {
+ $allRows = $this->filterBDSReportRowsBySearch($allRows, $searchValue);
+ }
+
+ $recordsFiltered = count($allRows);
+
+ if ($length < 0) {
+ $length = $recordsFiltered;
+ }
+
+ $pageRows = $length > 0
+ ? array_slice(array_values($allRows), $start, $length)
+ : array_values($allRows);
+
+ return [
+ 'draw' => $draw,
+ 'recordsTotal' => $recordsTotal,
+ 'recordsFiltered' => $recordsFiltered,
+ 'data' => $pageRows,
+ 'totals' => $this->calculateBDSReportTotals($allRows),
+ ];
+ }
+
+ /**
+ * Global search across BDS report row fields.
+ */
+ public function filterBDSReportRowsBySearch(array $rows, string $searchValue): array
+ {
+ $needle = mb_strtolower(trim($searchValue));
+ if ($needle === '') {
+ return $rows;
+ }
+
+ // Match DataTables "common search" behavior against primary visible columns.
+ $searchFields = [
+ 'user_name',
+ 'policy_issue_month',
+ 'client_name',
+ 'action_type',
+ 'policy_type',
+ 'policy_no',
+ 'endorsement_no',
+ 'insurer_branch_name',
+ ];
+
+ return array_values(array_filter($rows, static function (array $row) use ($needle, $searchFields) {
+ foreach ($searchFields as $field) {
+ $value = $row[$field] ?? '';
+ if ($value !== '' && mb_strpos(mb_strtolower((string) $value), $needle) !== false) {
+ return true;
+ }
+ }
+
+ $numericFields = [
+ 'bp_amt', 'tp_or_ter', 'premium_wo_gst', 'total_premium', 'agreed_bp_per',
+ 'agreed_tp_or_ter_per', 'reward', 'total_irda_amt', 'billed_amt', 'unbilled_amount',
+ ];
+ foreach ($numericFields as $field) {
+ $value = $row[$field] ?? '';
+ if ($value !== '' && $value !== null && mb_strpos((string) $value, $needle) !== false) {
+ return true;
+ }
+ }
+
+ return false;
+ }));
+ }
+
+ /**
+ * Summary totals for BDS report badges (matches client-side footerCallback logic).
+ */
+ public function calculateBDSReportTotals(array $rows): array
+ {
+ $totalPremium = 0.0;
+ $totalRewards = 0.0;
+ $totalIrda = 0.0;
+ $totalBilled = 0.0;
+ $totalUnbilled = 0.0;
+
+ foreach ($rows as $row) {
+ $hasIrda = ((float) ($row['total_irda_amt'] ?? 0)) != 0.0;
+
+ $totalPremium += $hasIrda ? (float) ($row['premium_wo_gst'] ?? 0) : 0.0;
+ $totalRewards += (float) ($row['reward'] ?? 0);
+ $totalIrda += (float) ($row['total_irda_amt'] ?? 0);
+ $totalBilled += (float) ($row['billed_amt'] ?? 0);
+ $totalUnbilled += (float) ($row['unbilled_amount'] ?? 0);
+ }
+
+ $totalIrdaAmt = $totalBilled - $totalRewards;
+ $totalRevenue = $totalIrdaAmt + $totalRewards;
+
+ return [
+ 'total_premium' => number_format($totalPremium, 2, '.', ''),
+ 'total_rewards' => number_format($totalRewards, 2, '.', ''),
+ 'total_irda' => number_format($totalIrdaAmt, 2, '.', ''),
+ 'total_revenue' => number_format($totalRevenue, 2, '.', ''),
+ 'total_billed' => number_format($totalBilled, 2, '.', ''),
+ 'total_unbilled' => number_format($totalUnbilled, 2, '.', ''),
+ 'policy_count' => count($rows),
+ ];
}
diff --git a/app/Views/bds_installment_reminder_email_template.php b/app/Views/bds_installment_reminder_email_template.php
new file mode 100644
index 00000000..edf9a406
--- /dev/null
+++ b/app/Views/bds_installment_reminder_email_template.php
@@ -0,0 +1,260 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Payment Overdue: The installment for = esc($client_name ?? '') ?> was due on = esc($payment_date ?? '') ?>. Kindly arrange the payment at the earliest to keep the policy active.
+
+
+
+ Payment Reminder: An installment payment for = esc($client_name ?? '') ?> is due on = esc($payment_date ?? '') ?>. Please review the details below.
+
+
+
+
+ This is a reminder that a policy installment payment is = !empty($is_overdue) ? 'overdue' : 'upcoming' ?> for
+ = esc($client_name ?? '') ?> (= esc($branch_name ?? '-') ?> branch).
+ Kindly process the payment on or before the due date to ensure uninterrupted policy coverage.
+
+
+
+ Payment Details
+
+
+
+
+ | Organization |
+ = esc($client_name ?? '-') ?> |
+
+
+ | Branch |
+ = esc($branch_name ?? '-') ?> |
+
+
+ | Policy Number |
+ = esc($policy_no ?? 'Not Assigned') ?> |
+
+
+
+ | Policy Type |
+ = esc($policy_type) ?> |
+
+
+
+
+ | Insurance Company |
+ = esc($insurer_name) ?> |
+
+
+
+
+ | Policy Period |
+ = esc($policy_period) ?> |
+
+
+
+ | Due Date |
+ = esc($payment_date ?? '-') ?> |
+
+
+ | Amount Payable |
+ = esc($installment_amount ?? '-') ?> |
+
+
+ | Status |
+
+
+ = !empty($is_overdue) ? 'Payment Overdue' : 'Payment Pending' ?>
+
+ |
+
+
+
+
+
Important Instructions
+
+ - Please arrange the installment payment of = esc($installment_amount ?? '') ?> on or before = esc($payment_date ?? '') ?>.
+ - After making the payment, kindly share the payment reference / UTR details for confirmation and record update.
+ - If the payment has already been made, please share the transaction details at the earliest.
+ - For any clarification regarding the amount or due date, please coordinate with the concerned team.
+
+
+
+
+ Timely payment helps ensure continuous insurance coverage. Thank you for your cooperation.
+
+
+
+
+
+
+
diff --git a/app/Views/layout/header.php b/app/Views/layout/header.php
index 25c51f36..2eed7f7f 100755
--- a/app/Views/layout/header.php
+++ b/app/Views/layout/header.php
@@ -2150,7 +2150,7 @@ body[data-sidebar-size="condensed"] .footer {
-
+
diff --git a/app/Views/policy_transaction_endorsement_list.php b/app/Views/policy_transaction_endorsement_list.php
index 0f2555fa..5dc37652 100644
--- a/app/Views/policy_transaction_endorsement_list.php
+++ b/app/Views/policy_transaction_endorsement_list.php
@@ -293,40 +293,7 @@
Action |
-
- $row) { ?>
-
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
-
-
- |
-
-
-
+
@@ -388,32 +355,122 @@
})
+ var endorsementTableFilters = = json_encode($endorsement_filters ?? []) ?>;
+ var endorsementListDataTableUrl = '= base_url('policy_tranction/endorsement/list/datatable') ?>';
+ var endorsementClearCacheUrl = '= base_url('policy_tranction/endorsement/list/clear-cache') ?>';
+ var endorsementAutoReloadTimer = null;
+
+ function scheduleEndorsementAutoReload(ms) {
+ if (endorsementAutoReloadTimer) {
+ clearTimeout(endorsementAutoReloadTimer);
+ }
+ if (ms > 0) {
+ endorsementAutoReloadTimer = setTimeout(function() {
+ window.location.reload();
+ }, ms);
+ }
+ }
+
+ function exportServerSideFilteredEndorsementData(e, dt, button, config, buttonType) {
+ var self = this;
+ var oldStart = dt.page.info().start;
+
+ dt.one('preXhr', function (x, s, data) {
+ data.start = 0;
+ data.length = -1;
+ });
+
+ dt.one('draw', function () {
+ $.fn.dataTable.ext.buttons[buttonType].action.call(self, e, dt, button, config);
+
+ dt.one('preXhr', function (x, s, data) {
+ data.start = oldStart;
+ data.length = dt.page.len();
+ });
+
+ setTimeout(function () {
+ dt.ajax.reload(null, false);
+ }, 0);
+ });
+
+ dt.ajax.reload();
+ }
+
+ function clearEndorsementCacheAndReloadTable(dt) {
+ $.ajax({
+ url: endorsementClearCacheUrl,
+ type: 'POST',
+ success: function(response) {
+ if (response && response.status) {
+ endorsementTableFilters.cache_version = new Date().getTime();
+ dt.ajax.reload(null, true);
+ toastr.success(response.message || 'Cache cleared and list reloaded.', 'Success');
+ } else {
+ toastr.warning((response && response.message) ? response.message : 'Unable to clear cache.', 'Warning');
+ }
+ },
+ error: function() {
+ toastr.error('Failed to clear cache.', 'Error');
+ }
+ });
+ }
+
//DataTable document ready
$(document).ready(function() {
var ticketsTable = $('#tickets-table');
if (ticketsTable.length) {
- var table = ticketsTable.DataTable({
- scrollX: true,
- dom: "<'row'<'col-sm-7'f><'col-sm-5 text-right'B>>" + // Filter left, buttons right
- "<'row'<'col-sm-12'tr>>" +
- "<'row align-items-center'<'col-5 text-start'i><'col-7 d-flex justify-content-end align-items-center'<'me-2'l>p>>",
- lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
- buttons: [
+ nhanceListDataTableBeforeInit();
+ var table = ticketsTable.DataTable(nhanceMergeListDataTableOptions({
+ autoWidth: false,
+ processing: true,
+ serverSide: true,
+ deferRender: true,
+ searchDelay: 400,
+ columns: (function() {
+ var cols = [];
+ for (var i = 0; i < 14; i++) {
+ cols.push({ data: String(i), orderable: false });
+ }
+ return cols;
+ })(),
+ ajax: {
+ url: endorsementListDataTableUrl,
+ type: 'POST',
+ data: function(d) {
+ return $.extend({}, d, endorsementTableFilters);
+ },
+ dataSrc: function(json) {
+ scheduleEndorsementAutoReload(json.cache_expires_in_ms || 300000);
+ return json.data;
+ }
+ },
+ dom: "<'row'<'col-sm-7'f><'col-sm-5 text-right'B>>" +
+ "<'row'<'col-sm-12'tr>>" +
+ "<'row align-items-center'<'col-5 text-start'i><'col-7 d-flex justify-content-end align-items-center'<'me-2'l>p>>",
+ lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
+ buttons: [
+ {
+ text: ' Reload ',
+ className: 'btn app-btn-secondary mr-2',
+ action: function(e, dt) {
+ clearEndorsementCacheAndReloadTable(dt);
+ }
+ },
{
text: ' Filter ',
className: 'btn app-btn-primary mr-2',
- action: function (e, dt, node, config) {
+ action: function () {
openEndorsementFilterNav();
}
},
- {
+ {
text: ' Add ',
className: 'btn app-btn-primary mr-2',
- action: function (e, dt, node, config) {
+ action: function () {
hide_list_show_add();
addHTMLInput(null, 'policy_docs_div');
- $('#policy_docs').show()
+ $('#policy_docs').show();
},
attr: { id: 'btnAdd' }
},
@@ -422,14 +479,30 @@
text: ' Export ',
className: 'btn app-btn-secondary ',
buttons: [
- {
- extend: 'csv',
- text: ' CSV ',
- title: 'Policy-Tranction-Endorsement-List',
- exportOptions: {
- columns: ':not(:last-child)'
- },
- }
+ {
+ extend: 'csv',
+ text: ' CSV ',
+ title: 'Policy-Tranction-Endorsement-List',
+ action: function (e, dt, button, config) {
+ exportServerSideFilteredEndorsementData.call(this, e, dt, button, config, 'csvHtml5');
+ },
+ exportOptions: {
+ modifier: { search: 'applied', page: 'all' },
+ columns: ':not(:last-child)'
+ },
+ },
+ {
+ extend: 'excel',
+ text: ' EXCEL ',
+ title: 'Policy-Tranction-Endorsement-List',
+ action: function (e, dt, button, config) {
+ exportServerSideFilteredEndorsementData.call(this, e, dt, button, config, 'excelHtml5');
+ },
+ exportOptions: {
+ modifier: { search: 'applied', page: 'all' },
+ columns: ':not(:last-child)'
+ },
+ }
]
}
],
@@ -444,33 +517,14 @@
`,
searchPlaceholder: "Search",
emptyTable: 'No Data found
',
- paginate: {
- previous: '◄',
- next: '►'
- }
+ paginate: { previous: '◄', next: '►' }
},
- paging: true, // Enable pagination
- pageLength: 10, // Set default number of rows per page (optional)
+ paging: true,
+ pageLength: 10,
ordering: false,
- });
-
- function applyBottomRowDropup() {
- if (!table) return;
-
- const currentRows = table.rows({ page: 'current' }).nodes().toArray();
- $('#tickets-table tbody tr').removeClass('nh-force-dropup');
- $('#tickets-table tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup');
-
- const targetCount = Math.min(2, currentRows.length);
- for (let i = 0; i < targetCount; i++) {
- const row = currentRows[currentRows.length - 1 - i];
- if (!row) continue;
- $(row).addClass('nh-force-dropup');
- $(row).find('td.table-action-cell .btn-group.dropdown').addClass('dropup');
- }
- }
- applyBottomRowDropup();
- ticketsTable.on('draw.dt', applyBottomRowDropup);
+ }));
+ nhanceListDataTableAfterInit();
+ nhanceListDataTableBindAdjust(table);
} else {
console.error("Table not found.");
}
diff --git a/app/Views/policy_transaction_inception_list.php b/app/Views/policy_transaction_inception_list.php
index 9a48f2d2..a86effe9 100644
--- a/app/Views/policy_transaction_inception_list.php
+++ b/app/Views/policy_transaction_inception_list.php
@@ -321,43 +321,7 @@ table.dataTable tbody td {
-
- $row){ ?>
-
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
-
-
- |
-
-
-
+
@@ -673,6 +637,66 @@ function getAddPage(){
}
}
+var inceptionTableFilters = = json_encode($inception_filters ?? []) ?>;
+var inceptionListDataTableUrl = '= base_url('policy_tranction/inception/list/datatable') ?>';
+var inceptionClearCacheUrl = '= base_url('policy_tranction/inception/list/clear-cache') ?>';
+var inceptionAutoReloadTimer = null;
+
+function scheduleInceptionAutoReload(ms) {
+ if (inceptionAutoReloadTimer) {
+ clearTimeout(inceptionAutoReloadTimer);
+ }
+ if (ms > 0) {
+ inceptionAutoReloadTimer = setTimeout(function() {
+ window.location.reload();
+ }, ms);
+ }
+}
+
+function exportServerSideFilteredInceptionData(e, dt, button, config, buttonType) {
+ var self = this;
+ var oldStart = dt.page.info().start;
+
+ dt.one('preXhr', function (x, s, data) {
+ data.start = 0;
+ data.length = -1;
+ });
+
+ dt.one('draw', function () {
+ $.fn.dataTable.ext.buttons[buttonType].action.call(self, e, dt, button, config);
+
+ dt.one('preXhr', function (x, s, data) {
+ data.start = oldStart;
+ data.length = dt.page.len();
+ });
+
+ setTimeout(function () {
+ dt.ajax.reload(null, false);
+ }, 0);
+ });
+
+ dt.ajax.reload();
+}
+
+function clearInceptionCacheAndReloadTable(dt) {
+ $.ajax({
+ url: inceptionClearCacheUrl,
+ type: 'POST',
+ success: function(response) {
+ if (response && response.status) {
+ inceptionTableFilters.cache_version = new Date().getTime();
+ dt.ajax.reload(null, true);
+ toastr.success(response.message || 'Cache cleared and list reloaded.', 'Success');
+ } else {
+ toastr.warning((response && response.message) ? response.message : 'Unable to clear cache.', 'Warning');
+ }
+ },
+ error: function() {
+ toastr.error('Failed to clear cache.', 'Error');
+ }
+ });
+}
+
// Datatable document ready
$(document).ready(function() {
@@ -692,64 +716,109 @@ $(document).ready(function() {
var ticketsTable = $('#tickets-table');
if (ticketsTable.length) {
- ticketsTable.DataTable({
- scrollX: true,
- // dom: "<'row'<'col-12'f><'col-sm-11 text-right'B>>" + // Filter left, buttons right
- // dom: "<'row'<'col-12 d-flex justify-content-between'<'datatable-search dataTables_filter'f><'datatable-buttons dt-buttons'B>>>" +
- // "<'row'<'col-sm-12'tr>>" +
- // "<'row'<'col-sm-5'i><'col-sm-7'p>>", // Pagination at the bottom, without page length selector
- dom: "<'row'<'col-sm-7'f><'col-sm-5 text-right'B>>" + // Filter left, buttons right
+ nhanceListDataTableBeforeInit();
+ var inceptionTable = ticketsTable.DataTable(nhanceMergeListDataTableOptions({
+ autoWidth: false,
+ processing: true,
+ serverSide: true,
+ deferRender: true,
+ searchDelay: 400,
+ columns: (function() {
+ var cols = [];
+ for (var i = 0; i < 16; i++) {
+ cols.push({ data: String(i), orderable: false });
+ }
+ return cols;
+ })(),
+ ajax: {
+ url: inceptionListDataTableUrl,
+ type: 'POST',
+ data: function(d) {
+ return $.extend({}, d, inceptionTableFilters);
+ },
+ dataSrc: function(json) {
+ scheduleInceptionAutoReload(json.cache_expires_in_ms || 300000);
+ return json.data;
+ }
+ },
+ dom: "<'row'<'col-sm-7'f><'col-sm-5 text-right'B>>" +
"<'row'<'col-sm-12'tr>>" +
"<'row align-items-center'<'col-5 text-start'i><'col-7 d-flex justify-content-end align-items-center'<'me-2'l>p>>",
lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
- buttons: [
- {
- text: ' Filter ',
- className: 'btn app-btn-primary mr-2',
- action: function(e, dt, node, config) {
- openPolicyFilterNav();
- }
- },
- {
- text: ' Add ',
- className: 'btn app-btn-primary mr-2',
- action: function (e, dt, node, config) {
- openPolicyNoAddModal();
- }
- },
- {
- extend: 'collection',
- text: ' Export ',
- className: 'btn app-btn-secondary ',
- buttons: [
- {
- extend: 'csv',
- text: ' CSV ',
- className: 'app-btn-primary ',
- title: 'Policy-Tranction-Inception-List',
- exportOptions: {
- columns: ':not(:last-child)'
- },
- }
- ]
+ buttons: [
+ {
+ text: ' Reload ',
+ className: 'btn app-btn-secondary mr-2',
+ action: function(e, dt) {
+ clearInceptionCacheAndReloadTable(dt);
}
- ],
+ },
+ {
+ text: ' Filter ',
+ className: 'btn app-btn-primary mr-2',
+ action: function() {
+ openPolicyFilterNav();
+ }
+ },
+ {
+ text: ' Add ',
+ className: 'btn app-btn-primary mr-2',
+ action: function () {
+ openPolicyNoAddModal();
+ }
+ },
+ {
+ extend: 'collection',
+ text: ' Export ',
+ className: 'btn app-btn-secondary ',
+ buttons: [
+ {
+ extend: 'csv',
+ text: ' CSV ',
+ className: 'app-btn-primary ',
+ title: 'Policy-Tranction-Inception-List',
+ action: function (e, dt, button, config) {
+ exportServerSideFilteredInceptionData.call(this, e, dt, button, config, 'csvHtml5');
+ },
+ exportOptions: {
+ modifier: { search: 'applied', page: 'all' },
+ columns: ':not(:last-child)'
+ }
+ },
+ {
+ extend: 'excel',
+ text: ' EXCEL ',
+ className: 'app-btn-primary ',
+ title: 'Policy-Tranction-Inception-List',
+ action: function (e, dt, button, config) {
+ exportServerSideFilteredInceptionData.call(this, e, dt, button, config, 'excelHtml5');
+ },
+ exportOptions: {
+ modifier: { search: 'applied', page: 'all' },
+ columns: ':not(:last-child)'
+ }
+ }
+ ]
+ }
+ ],
language: {
- search: `
-
- _INPUT_
-
-
-
`,
- searchPlaceholder: "Search",
- emptyTable: 'No Data found
'
+ search: `
+
+ _INPUT_
+
+
+
`,
+ searchPlaceholder: "Search",
+ emptyTable: 'No Data found
'
},
- paging: true, // Enable pagination
- pageLength: 10, // Set default number of rows per page (optional)
- // ordering: false,
- });
+ paging: true,
+ pageLength: 10,
+ ordering: false,
+ }));
+ nhanceListDataTableAfterInit();
+ nhanceListDataTableBindAdjust(inceptionTable);
} else {
console.error("Table not found.");
}
diff --git a/app/Views/report_bds.php b/app/Views/report_bds.php
index 80246a6d..fb2c1c90 100644
--- a/app/Views/report_bds.php
+++ b/app/Views/report_bds.php
@@ -165,130 +165,6 @@
-
- $row){ ?>
-
- | = $index + 1 ?> " class="mdi mdi-pencil" > |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
-
- |
-
- |
- |
- |
- |
- |
-
- |
- |
- |
-
- |
- % |
- % |
- |
-
- i am print 0.00.
- // REF : Velmurugan but he told handle in query
- // Date : 6/11/25 12:50
- $irda_amt = isset($row['total_irda_amt']) && $row['total_irda_amt'] !== '' ? (float)$row['total_irda_amt'] : 0;
- $exp_amt = isset($row['exp_amt']) && $row['exp_amt'] !== '' ? (float)$row['exp_amt'] : 0;
- // $max_amount = max($irda_amt, $exp_amt);
- // $total_irda_amt = number_format($max_amount, 2, '.', '');
- // $total_irda_amt = empty($row['total_irda_amt']) ? $row['exp_amt'] : $row['total_irda_amt'];
- $total_irda_amt = $row['total_irda_amt'] ?? '0.00';
- ?>
- |
- |
-
-
-
-
- |
- |
- |
- |
- |
- |
- |
-
- |
- |
-
- |
- |
- |
-
- |
-
- |
- |
-
- |
-
- |
-
- |
-
- |
- |
- |
-
- |
-
- |
- |
-
- |
- |
-
- |
- |
-
- |
- |
-
- |
-
-
-
@@ -332,6 +208,68 @@