nhance/app/Commands/BackfillClaimReport.php
2026-07-28 15:52:47 +05:30

201 lines
8.0 KiB
PHP

<?php
namespace App\Commands;
use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;
/**
* Seed claim_report from existing dump-sourced ticket_master rows.
*
* Usage:
* php spark claim:backfill-report
* php spark claim:backfill-report --policy=4687
* php spark claim:backfill-report --limit=5000
*/
class BackfillClaimReport extends BaseCommand
{
protected $group = 'Claims';
protected $name = 'claim:backfill-report';
protected $description = 'Backfill claim_report from ticket_master dump claims';
protected $usage = 'claim:backfill-report [--policy=ID] [--limit=N]';
protected $options = [
'--policy' => 'Optional client_policy_id to limit backfill',
'--limit' => 'Batch size (default 1000)',
];
public function run(array $params)
{
$db = db_connect();
if (!$db->tableExists('claim_report')) {
CLI::error('Table claim_report does not exist. Run migrations first.');
return EXIT_ERROR;
}
if (!$db->tableExists('ticket_master')) {
CLI::error('Table ticket_master does not exist.');
return EXIT_ERROR;
}
$policyId = (int) (CLI::getOption('policy') ?? 0);
$limit = (int) (CLI::getOption('limit') ?? 1000);
if ($limit <= 0) {
$limit = 1000;
}
$offset = 0;
$totalInserted = 0;
$totalUpdated = 0;
$totalSkipped = 0;
$now = date('Y-m-d H:i:s');
CLI::write('Backfilling claim_report from ticket_master (dump-sourced claims)...', 'yellow');
while (true) {
$builder = $db->table('ticket_master')
->where('is_active', 1)
->groupStart()
->where('claim_dump_ref_id IS NOT NULL', null, false)
->orWhere('file_id IS NOT NULL', null, false)
->groupEnd()
->where("claim_number IS NOT NULL AND TRIM(claim_number) != ''", null, false)
->orderBy('id', 'ASC')
->limit($limit, $offset);
if ($policyId > 0) {
$builder->where('client_policy_id', $policyId);
}
$tickets = $builder->get()->getResultArray();
if ($tickets === []) {
break;
}
$rows = [];
foreach ($tickets as $tm) {
$claimNumber = trim((string) ($tm['claim_number'] ?? ''));
$clientPolicyId = (int) ($tm['client_policy_id'] ?? 0);
if ($claimNumber === '' || $clientPolicyId <= 0) {
$totalSkipped++;
continue;
}
$rows[] = [
'tpa_id' => $tm['tpa_id'] ?? null,
'client_id' => $tm['client_id'] ?? null,
'client_policy_id' => $clientPolicyId,
'file_id' => $tm['file_id'] ?? null,
'ticket_id' => $tm['id'] ?? null,
'source_table' => null,
'source_row_id' => $tm['claim_dump_ref_id'] ?? null,
'claim_number' => $claimNumber,
'emp_code' => $tm['emp_code'] ?? null,
'tpa_no' => $tm['tpa_no'] ?? null,
'emp_id' => $tm['emp_id'] ?? null,
'insured_emp_id' => $tm['insured_emp_id'] ?? null,
'claim_amount' => $tm['claim_amount'] ?? null,
'approved_amount' => $tm['approved_amount'] ?? null,
'incurred_amount' => $tm['approved_amount'] ?? $tm['claim_amount'] ?? null,
'si_amt' => $tm['si_amt'] ?? null,
'tpa_claim_status' => $tm['tpa_claim_status'] ?? null,
'claim_status_id' => $tm['claim_status_id'] ?? null,
'tpa_claim_type' => $tm['tpa_claim_type'] ?? null,
'tpa_ailments' => $tm['tpa_ailments'] ?? null,
'doa' => $tm['doa'] ?? null,
'dod' => $tm['dod'] ?? null,
'date_of_intimat' => $tm['date_of_intimat'] ?? null,
'settled_date' => $tm['settled_date'] ?? null,
'approved_date' => $tm['approved_date'] ?? null,
'claim_dump_date' => $tm['claim_dump_date'] ?? null,
'hospital_name' => $tm['hospital_name'] ?? null,
'hospital_city' => $tm['hospital_city'] ?? null,
'hospital_state' => $tm['hospital_state'] ?? null,
'hospital_pin_code'=> $tm['hospital_pin_code'] ?? null,
'hospital_address' => $tm['hospital_address'] ?? null,
'gender' => null,
'age' => null,
'relation' => $tm['relationship'] ?? null,
'is_active' => 1,
'created_at' => $now,
'updated_at' => $now,
];
}
if ($rows !== []) {
$result = $this->upsertRows($db, $rows);
if ($result === false) {
CLI::error('Upsert failed at offset ' . $offset);
return EXIT_ERROR;
}
$totalInserted += $result['inserted'];
$totalUpdated += $result['updated'];
}
$offset += count($tickets);
CLI::write("Processed {$offset} ticket_master rows...", 'green');
if (count($tickets) < $limit) {
break;
}
}
CLI::write("Done. inserted≈{$totalInserted}, updated≈{$totalUpdated}, skipped={$totalSkipped}", 'green');
return EXIT_SUCCESS;
}
/**
* @param list<array<string, mixed>> $rows
* @return array{inserted:int,updated:int}|false
*/
private function upsertRows($db, array $rows)
{
$columns = [
'tpa_id', 'client_id', 'client_policy_id', 'file_id', 'ticket_id',
'source_table', 'source_row_id', 'claim_number', 'emp_code', 'tpa_no',
'emp_id', 'insured_emp_id', 'claim_amount', 'approved_amount', 'incurred_amount',
'si_amt', 'tpa_claim_status', 'claim_status_id', 'tpa_claim_type', 'tpa_ailments',
'doa', 'dod', 'date_of_intimat', 'settled_date', 'approved_date', 'claim_dump_date',
'hospital_name', 'hospital_city', 'hospital_state', 'hospital_pin_code', 'hospital_address',
'gender', 'age', 'relation', 'is_active', 'created_at', 'updated_at',
];
$updateCols = array_values(array_diff($columns, ['client_policy_id', 'claim_number', 'created_at']));
$inserted = 0;
$updated = 0;
foreach (array_chunk($rows, 100) as $chunk) {
$placeholders = [];
$binds = [];
foreach ($chunk as $row) {
$rowPlaceholders = [];
foreach ($columns as $col) {
$rowPlaceholders[] = '?';
$binds[] = $row[$col] ?? null;
}
$placeholders[] = '(' . implode(', ', $rowPlaceholders) . ')';
}
$updates = [];
foreach ($updateCols as $col) {
$updates[] = '`' . $col . '` = VALUES(`' . $col . '`)';
}
$sql = 'INSERT INTO `claim_report` (`' . implode('`, `', $columns) . '`) VALUES '
. implode(', ', $placeholders)
. ' ON DUPLICATE KEY UPDATE ' . implode(', ', $updates);
if ($db->query($sql, $binds) === false) {
return false;
}
$affected = $db->affectedRows();
// MySQL: 1 = insert, 2 = update existing
$updated += (int) floor($affected / 2);
$inserted += max(0, $affected - (2 * (int) floor($affected / 2)));
}
return ['inserted' => $inserted, 'updated' => $updated];
}
}