MERGE_TEST_TPA_RECON&DELETION&FE_VALIDATIONS

This commit is contained in:
Ubuntu 2026-04-29 10:58:27 +05:30
commit 0164fea8af
10 changed files with 670 additions and 55 deletions

View File

@ -476,6 +476,7 @@ class ApiServiceController extends BaseController
->where('ep.status', 'active') ->where('ep.status', 'active')
->where('e.is_active', 1) ->where('e.is_active', 1)
->where('ep.is_active', 1) ->where('ep.is_active', 1)
->where('ep.wellness_onboard != 0')
->get() ->get()
->getResultArray(); ->getResultArray();

View File

@ -47,6 +47,7 @@ use CodeIgniter\API\ResponseTrait;
use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx; use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Writer\Xls;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate; use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Style\Fill; use PhpOffice\PhpSpreadsheet\Style\Fill;
@ -657,7 +658,7 @@ class EmployeeController extends AdminController
if ($actionType == 'inception') { if ($actionType == 'inception') {
$filePath = ROOTPATH . 'public/sample_excel/sample_inception.xls'; $filePath = ROOTPATH . 'public/sample_excel/sample_inception.xls';
} else if ($actionType == 'correction') { } else if ($actionType == 'correction') {
$filePath = ROOTPATH . 'public/sample_excel/sample_correction .xls'; $filePath = ROOTPATH . 'public/sample_excel/sample_correction.xls';
} else if ($actionType == 'si_enhancement') { } else if ($actionType == 'si_enhancement') {
$filePath = ROOTPATH . 'public/sample_excel/sample_si_enhancement.xls'; $filePath = ROOTPATH . 'public/sample_excel/sample_si_enhancement.xls';
} else if ($actionType == 'dependent_addition') { } else if ($actionType == 'dependent_addition') {
@ -3629,17 +3630,17 @@ class EmployeeController extends AdminController
->where('employee_polices.is_active', 1) ->where('employee_polices.is_active', 1)
->where('employee_polices.status', 'active') ->where('employee_polices.status', 'active')
->where('employee_polices.client_policy_id', $client_policy_id) ->where('employee_polices.client_policy_id', $client_policy_id)
->where('employee_polices.tpa_id is not null') // ->where('employee_polices.tpa_id is not null')
->where('employee_polices.wellness_onboard', '0') ->where('employee_polices.wellness_onboard', '0')
->where('emp.emp_status', 'active') ->where('emp.emp_status', 'active')
->where('emp.is_active', 1) ->where('emp.is_active', 1)
->groupStart() ->groupStart()
->where('cp.wellness_plan_id IS NOT NULL', null, false) ->orwhere('cp.wellness_plan_id IS NOT NULL', null, false)
->orWhere('cp.wellness_plan_id !=', '') ->orWhere('cp.wellness_plan_id !=', '')
->orWhere('cp.wellness_plan_id !=', 0) ->orWhere('cp.wellness_plan_id !=', 0)
->groupEnd() ->groupEnd()
->groupStart() ->groupStart()
->where('cp.wellness_vendor_id IS NULL', null, false) ->orwhere('cp.wellness_vendor_id IS NULL', null, false)
->orWhere('cp.wellness_vendor_id =', '') ->orWhere('cp.wellness_vendor_id =', '')
->orWhere('cp.wellness_vendor_id =', 0) ->orWhere('cp.wellness_vendor_id =', 0)
->groupEnd() ->groupEnd()
@ -3661,31 +3662,38 @@ class EmployeeController extends AdminController
return $this->respond(['status' => true, 'code' => 200, 'message' => 'Process started'], 200); return $this->respond(['status' => true, 'code' => 200, 'message' => 'Process started'], 200);
} }
public function initiateWellnessOnboardJob($arr) public function initiateWellnessOnboardJobOLD($arr)
{ {
$client_policy_id = $arr['client_policy_id']; $client_policy_id = $arr['client_policy_id'];
// $this->updateWellnessOnboardResponseToDB();die();
// echo $client_policy_id;die(); $page = max(1, (int)($arr['page'] ?? 1));
$data = $this->employeePolicyModel->select('employee_polices.*,emp.name,emp.relationship,emp.emp_code,emp.name,emp.gender,emp.email_corporate,emp.mobile,emp.dob,cp.policy_no,cp.wellness_plan_id,cp.wellness_vendor_id,cp.policy_start_date as cp_policy_start_date,cp.policy_end_date,cls.short_name') $perPage = max(1, (int)($arr['per_page'] ?? 50));
$offset = ($page - 1) * $perPage;
$data = $this->employeePolicyModel->select('employee_polices.*,emp.name,emp.relationship,emp.emp_code,emp.name,emp.email_corporate,emp.mobile,emp.dob,cp.policy_no,cp.wellness_plan_id,cp.wellness_vendor_id,cp.policy_start_date as cp_policy_start_date,cp.policy_end_date,cls.short_name,emp.gender')
->join('client_policy cp', 'cp.id = employee_polices.client_policy_id') ->join('client_policy cp', 'cp.id = employee_polices.client_policy_id')
->join('clients cls', "cp.client_id = cls.id") ->join('clients cls', "cp.client_id = cls.id")
->join('employees emp', "emp.id = employee_polices.employee_id") ->join('employees emp', "emp.id = employee_polices.employee_id")
->where('employee_polices.is_active', 1) ->where('employee_polices.is_active', 1)
->where('employee_polices.status', 'active') ->where('employee_polices.status', 'active')
->where('employee_polices.client_policy_id', $client_policy_id) ->where('employee_polices.client_policy_id', $client_policy_id)
->where('employee_polices.tpa_id is not null') // ->where('employee_polices.tpa_id is not null')
->where('employee_polices.wellness_onboard', '0') ->where('employee_polices.wellness_onboard', '0')
->where('emp.emp_status', 'active') ->where('emp.emp_status', 'active')
->where('emp.is_active', 1) ->where('emp.is_active', 1)
->where('cp.wellness_plan_id is not null') ->groupStart()
->where('cp.wellness_vendor_id is null') ->where('cp.wellness_plan_id IS NOT NULL', null, false)
// ->where('cp.policy_status',1) ->orWhere('cp.wellness_plan_id !=', '')
// ->where('cp.is_active',1) ->orWhere('cp.wellness_plan_id !=', 0)
->findAll(); ->groupEnd()
// print_r($this->employeePolicyModel->getLastQuery()); ->groupStart()
// print_r($data); ->where('cp.wellness_vendor_id IS NULL', null, false)
// echo '==============================';die(); ->orWhere('cp.wellness_vendor_id =', '')
->orWhere('cp.wellness_vendor_id =', 0)
->groupEnd()
->where('cp.policy_status',1)
->where('cp.is_active',1)
->findAll($perPage, $offset);
// $data = '[{"id":12847,"employee_id":"TEST_EMP_001","client_policy_id":null,"tpa_id":null,"uhid":null,"batch_code":null,"status":"active","pre_existing_alignments":null,"age_band":null,"basic_cover_si":"0","date_coverage":"2025-01-01","policy_end_date":"2025-12-31","days":"0","premium":"0","rata_premimum":"0","gst":"0","si_enhancement_date":null,"date_of_exit":null,"reason_for_exit":null,"claim_status":"0","created_by":null,"created_at":null,"updated_by":null,"updated_at":null,"is_active":"1","rand_string":null,"ecard_sent_status":"0","payable_employee":"0","file_id":null,"wellness_onboard":"0","name":"test name","relationship":"SELF","emp_code":"TEST_EMP_001","email_corporate":"test@gmail.com","mobile":"9797976565","dob":"1975-08-09"},{"id":12846,"employee_id":"TEST_EMP_001","client_policy_id":null,"tpa_id":null,"uhid":null,"batch_code":null,"status":"active","pre_existing_alignments":null,"age_band":null,"basic_cover_si":"0","date_coverage":"2025-01-01","policy_end_date":"2025-12-31","days":"0","premium":"0","rata_premimum":"0","gst":"0","si_enhancement_date":null,"date_of_exit":null,"reason_for_exit":null,"claim_status":"0","created_by":null,"created_at":null,"updated_by":null,"updated_at":null,"is_active":"1","rand_string":null,"ecard_sent_status":"0","payable_employee":"0","file_id":null,"wellness_onboard":"0","name":"dependent 1","relationship":"SON","emp_code":"TEST_EMP_001","email_corporate":"dependent1@gmail.com","mobile":"9898989898","dob":"2001-08-09"}]'; // $data = '[{"id":12847,"employee_id":"TEST_EMP_001","client_policy_id":null,"tpa_id":null,"uhid":null,"batch_code":null,"status":"active","pre_existing_alignments":null,"age_band":null,"basic_cover_si":"0","date_coverage":"2025-01-01","policy_end_date":"2025-12-31","days":"0","premium":"0","rata_premimum":"0","gst":"0","si_enhancement_date":null,"date_of_exit":null,"reason_for_exit":null,"claim_status":"0","created_by":null,"created_at":null,"updated_by":null,"updated_at":null,"is_active":"1","rand_string":null,"ecard_sent_status":"0","payable_employee":"0","file_id":null,"wellness_onboard":"0","name":"test name","relationship":"SELF","emp_code":"TEST_EMP_001","email_corporate":"test@gmail.com","mobile":"9797976565","dob":"1975-08-09"},{"id":12846,"employee_id":"TEST_EMP_001","client_policy_id":null,"tpa_id":null,"uhid":null,"batch_code":null,"status":"active","pre_existing_alignments":null,"age_band":null,"basic_cover_si":"0","date_coverage":"2025-01-01","policy_end_date":"2025-12-31","days":"0","premium":"0","rata_premimum":"0","gst":"0","si_enhancement_date":null,"date_of_exit":null,"reason_for_exit":null,"claim_status":"0","created_by":null,"created_at":null,"updated_by":null,"updated_at":null,"is_active":"1","rand_string":null,"ecard_sent_status":"0","payable_employee":"0","file_id":null,"wellness_onboard":"0","name":"dependent 1","relationship":"SON","emp_code":"TEST_EMP_001","email_corporate":"dependent1@gmail.com","mobile":"9898989898","dob":"2001-08-09"}]';
// $data = (array)json_decode($data,true); // $data = (array)json_decode($data,true);
// print_r(count($data)); // print_r(count($data));
@ -3710,6 +3718,8 @@ class EmployeeController extends AdminController
$families[$empCode][] = $row; $families[$empCode][] = $row;
} }
// print_rr($families);die();
// ------------------ BUILD PAYLOAD FOR ALL FAMILIES ------------------ // ------------------ BUILD PAYLOAD FOR ALL FAMILIES ------------------
$familiesPayload = []; $familiesPayload = [];
@ -3722,6 +3732,26 @@ class EmployeeController extends AdminController
// print_r($apiResponse); // print_r($apiResponse);
$updatedData = $this->updateWellnessOnboardResponseToDB($apiResponse); $updatedData = $this->updateWellnessOnboardResponseToDB($apiResponse);
// print_r($updatedData);die(); // print_r($updatedData);die();
if (count($data) > 0) {
$delaySeconds = max(1, (int)($arr['recursive_delay_seconds'] ?? 2));
sleep($delaySeconds);
$r = Jobs::addJob(['job_name' => 'initiateWellnessOnboardJob','payload' => [
'client_policy_id' => $client_policy_id,
'page' => $page + 1,
'per_page' => $perPage,
'recursive_delay_seconds' => $delaySeconds,
]]);
// $this->initiateWellnessOnboardJob([
// 'client_policy_id' => $client_policy_id,
// 'page' => $page + 1,
// 'per_page' => $perPage,
// 'recursive_delay_seconds' => $delaySeconds,
// ]);
}
return true; return true;
@ -3730,6 +3760,9 @@ class EmployeeController extends AdminController
} }
else else
{ {
if ($page > 1) {
return true;
}
return $this->respond(['status' => false, 'code' => 200, 'message' => 'No employees found for wellness onboard!'], 200); return $this->respond(['status' => false, 'code' => 200, 'message' => 'No employees found for wellness onboard!'], 200);
} }
@ -3737,6 +3770,121 @@ class EmployeeController extends AdminController
} }
public function initiateWellnessOnboardJob($arr)
{
$client_policy_id = $arr['client_policy_id'] ?? null;
if (!$client_policy_id) {
log_message('error', '[WellnessOnboard] Missing client_policy_id in payload');
return true;
}
$page = max(1, (int)($arr['page'] ?? 1));
$perPage = max(1, (int)($arr['per_page'] ?? 50));
$offset = ($page - 1) * $perPage;
log_message('error', "[WellnessOnboard] Processing page {$page} | perPage {$perPage} | offset {$offset} | client_policy_id {$client_policy_id}");
// ----------------------------------------------------------------
// 1. FETCH DATA
// ----------------------------------------------------------------
$data = $this->employeePolicyModel
->select('employee_polices.*,
emp.name, emp.relationship, emp.emp_code, emp.email_corporate,
emp.mobile, emp.dob, emp.gender,
cp.policy_no, cp.wellness_plan_id, cp.wellness_vendor_id,
cp.policy_start_date as cp_policy_start_date, cp.policy_end_date,
cls.short_name')
->join('client_policy cp', 'cp.id = employee_polices.client_policy_id')
->join('clients cls', 'cp.client_id = cls.id')
->join('employees emp', 'emp.id = employee_polices.employee_id')
->where('employee_polices.is_active', 1)
->where('employee_polices.status', 'active')
->where('employee_polices.client_policy_id', $client_policy_id)
// ->where('employee_polices.tpa_id is not null')
->where('employee_polices.wellness_onboard', '0')
->where('emp.emp_status', 'active')
->where('emp.is_active', 1)
->groupStart()
->where('cp.wellness_plan_id IS NOT NULL', null, false)
->orWhere('cp.wellness_plan_id !=', '')
->orWhere('cp.wellness_plan_id !=', 0)
->groupEnd()
->groupStart()
->where('cp.wellness_vendor_id IS NULL', null, false)
->orWhere('cp.wellness_vendor_id =', '')
->orWhere('cp.wellness_vendor_id =', 0)
->groupEnd()
->where('cp.policy_status', 1)
->where('cp.is_active', 1)
->findAll($perPage, $offset);
// ----------------------------------------------------------------
// 2. NO DATA FOUND
// ----------------------------------------------------------------
if (empty($data)) {
log_message('error', "[WellnessOnboard] No data found on page {$page}. Batch complete.");
return true; // always return true in job context, never $this->respond()
}
// ----------------------------------------------------------------
// 3. GROUP BY FAMILY (emp_code)
// ----------------------------------------------------------------
$families = [];
foreach ($data as $row) {
if (empty($row['emp_code'])) {
log_message('warning', '[WellnessOnboard] Skipping row with missing emp_code: ' . json_encode($row));
continue;
}
$families[$row['emp_code']][] = $row;
}
if (empty($families)) {
log_message('warning', "[WellnessOnboard] All rows on page {$page} had missing emp_code. Skipping.");
return true;
}
// ----------------------------------------------------------------
// 4. BUILD PAYLOAD
// ----------------------------------------------------------------
$familiesPayload = [];
foreach ($families as $empCode => $members) {
$familiesPayload[$empCode] = $this->buildFamilyPayload($empCode, $members);
}
// ----------------------------------------------------------------
// 5. SEND TO WELLNESS API
// ----------------------------------------------------------------
$apiResponse = $this->sendFamiliesToWellnessApi($familiesPayload);
log_message('error', "[WellnessOnboard] Page {$page} API calls done. Families processed: " . count($apiResponse));
// ----------------------------------------------------------------
// 6. PERSIST RESPONSE TO DB
// ----------------------------------------------------------------
$updatedData = $this->updateWellnessOnboardResponseToDB($apiResponse);
log_message('error', "[WellnessOnboard] Page {$page} DB update done.");
// ----------------------------------------------------------------
// 7. SPAWN NEXT PAGE JOB (only if this page was full)
// ----------------------------------------------------------------
if (count($data) === $perPage) {
log_message('error', "[WellnessOnboard] Full page detected. Spawning job for page " . ($page + 1));
Jobs::addJob([
'job_name' => 'initiateWellnessOnboardJob',
'payload' => [
'client_policy_id' => $client_policy_id,
'page' => $page + 1,
'per_page' => $perPage,
]
]);
} else {
log_message('error', "[WellnessOnboard] Partial page ({$page}). This is the last page. Batch complete.");
}
return true;
}
# ------------------ FUNCTION TO BUILD FAMILY PAYLOAD ------------------ # ------------------ FUNCTION TO BUILD FAMILY PAYLOAD ------------------
/** /**
@ -4033,6 +4181,8 @@ class EmployeeController extends AdminController
public function getTPADataVariationReport($file_id, $type = 'download') public function getTPADataVariationReport($file_id, $type = 'download')
{ {
// print_rr($this->initializeDeletionProcessForTpaApiData($file_id));
// die;
$fileInfo = $this->batchFileModel->find((int) $file_id); $fileInfo = $this->batchFileModel->find((int) $file_id);
if (empty($fileInfo)) { if (empty($fileInfo)) {
if ($type === 'view') { if ($type === 'view') {
@ -4153,6 +4303,9 @@ class EmployeeController extends AdminController
$tpaApiDataModel->updateBatch($updateRows, 'id'); $tpaApiDataModel->updateBatch($updateRows, 'id');
$db->transComplete(); $db->transComplete();
} }
// this will match tpa api data with emp/emp policy table and update ref in tpa api data once
$this->reconTpaApiDataWithEmployeepolicies($file_id);
} else { } else {
// echo 'else';die; // echo 'else';die;
// Cached mode: // Cached mode:
@ -4294,8 +4447,13 @@ class EmployeeController extends AdminController
{ {
if($generationResult['data']['file_id']) if($generationResult['data']['file_id'])
{ {
//initiate update references b/w tpa_api_data and employess sleep(1);
//initiate update references b/w tpa_api_data and employess (pk update)
$this->reconTpaApiDataWithEmployeepolicies($file_id);
sleep(1);
//initiate deleteion if any //initiate deleteion if any
$this->initializeDeletionProcessForTpaApiData($file_id);
} }
else else
{ {
@ -4311,6 +4469,8 @@ class EmployeeController extends AdminController
// For the "Need to Review" tab, generate a Correction Excel // For the "Need to Review" tab, generate a Correction Excel
// using the same overall pipeline as the Not in Nhance implementation. // using the same overall pipeline as the Not in Nhance implementation.
// $generationResult = $this->generateCorrectionUploadFromNeedToReview((int) $file_id, $file); // $generationResult = $this->generateCorrectionUploadFromNeedToReview((int) $file_id, $file);
//once correction file uploaded success fully update ref id b/w employeetable and tpaapi data
$generationResult = $this->updateEmployeeDataFromTpa([$file_id]); $generationResult = $this->updateEmployeeDataFromTpa([$file_id]);
if (!$generationResult['status']) { if (!$generationResult['status']) {
@ -6416,6 +6576,7 @@ class EmployeeController extends AdminController
]; ];
} }
// return $tpaRows;
// Build Nhance-side candidate pool once, keyed by emp_code. // Build Nhance-side candidate pool once, keyed by emp_code.
// Each candidate represents an active employee policy member. // Each candidate represents an active employee policy member.
$dbMembers = $db->table('employee_polices ep') $dbMembers = $db->table('employee_polices ep')
@ -6435,7 +6596,8 @@ class EmployeeController extends AdminController
->where('emp.is_active', 1) ->where('emp.is_active', 1)
->get() ->get()
->getResultArray(); ->getResultArray();
// return $dbMembers;
$membersByEmpCode = []; $membersByEmpCode = [];
foreach ($dbMembers as $member) { foreach ($dbMembers as $member) {
$membersByEmpCode[$member['emp_code']][] = $member; $membersByEmpCode[$member['emp_code']][] = $member;
@ -6495,7 +6657,7 @@ class EmployeeController extends AdminController
]; ];
$matched++; $matched++;
} }
// return $updates;
if (!empty($updates)) { if (!empty($updates)) {
$db->transStart(); $db->transStart();
$db->table('tpa_api_data')->updateBatch($updates, 'id'); $db->table('tpa_api_data')->updateBatch($updates, 'id');
@ -6535,4 +6697,393 @@ class EmployeeController extends AdminController
} }
} }
/**
* Build and queue a Deletion import file from TPA reconciled data.
*
* The logic uses `tpa_api_data.ref` rows with `rec_type = matched` as the
* "currently present in TPA" snapshot. Any active Nhance member in the same
* client/policy scope not present in that ref set is prepared as a deletion row.
*
* @param int|string $file_id Source batch_file id of the TPA variation flow.
*
* @return array{
* status: bool,
* message: string,
* data: array
* }
*/
public function initializeDeletionProcessForTpaApiData($file_id): array
{
// echo 'DELETION';
try {
$fileId = (int) $file_id;
if ($fileId <= 0) {
return [
'status' => false,
'message' => 'Invalid file id provided.',
'data' => [],
];
}
$fileInfo = $this->batchFileModel->find($fileId);
if (empty($fileInfo)) {
return [
'status' => false,
'message' => 'Batch file not found.',
'data' => ['file_id' => $fileId],
];
}
$clientId = (int) ($fileInfo['client_id'] ?? 0);
$clientPolicyId = (int) ($fileInfo['client_policy_id'] ?? 0);
$clientBranchId = (int) ($fileInfo['client_branch_id'] ?? 0);
if ($clientId <= 0 || $clientPolicyId <= 0 || $clientBranchId <= 0) {
return [
'status' => false,
'message' => 'Client/policy/branch context missing for provided file id.',
'data' => ['file_id' => $fileId],
];
}
$db = \Config\Database::connect();
// Take only mapped rows for this file where reconciliation is stable.
$mappedRows = $db->table('tpa_api_data tad')
->select('tad.ref')
->where('tad.file_id', $fileId)
->where('tad.is_active', 1)
->where('tad.action_flag_status', 'D')
// ->where('tad.rec_type', 'matched')
->where('tad.ref IS NOT NULL', null, false)
->where('tad.ref !=', '')
->groupBy('tad.ref')
->get()
->getResultArray();
// return $mappedRows;
$mappedPolicyIds = array_values(array_filter(array_map(
static fn($row) => (int) ($row['ref'] ?? 0),
$mappedRows
)));
if (empty($mappedPolicyIds)) {
return [
'status' => true,
'message' => 'No reconciled TPA mapped rows found. Deletion initialization skipped.',
'data' => ['file_id' => $fileId, 'candidate_count' => 0],
];
}
// Candidate deletions = active Nhance members in scope not present in mapped refs.
$candidateBuilder = $db->table('employee_polices ep')
->select("
ep.id AS employee_policy_id,
emp.emp_code,
emp.name,
emp.dob,
emp.gender,
emp.relationship,
ep.basic_cover_si,
ep.policy_end_date,
ep.premium,
ep.claim_status
")
->join('employees emp', 'ep.employee_id = emp.id')
->where('ep.is_active', 1)
->where('ep.status', 'active')
->where('ep.client_policy_id', $clientPolicyId)
->where('emp.client_id', $clientId)
->where('emp.is_active', 1)
->where('emp.emp_status', 'active');
$candidateBuilder->whereIn('ep.id', $mappedPolicyIds);
$candidateMembers = $candidateBuilder->get()->getResultArray();
// return $candidateMembers;
if (empty($candidateMembers)) {
return [
'status' => true,
'message' => 'No deletion candidates found from TPA reconciliation.',
'data' => ['file_id' => $fileId, 'candidate_count' => 0],
];
}
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setTitle('Deletion');
$headers = [
'S.No',
'Emp ID',
'Name of Emp/Dep',
'change event ',
'date of exit',
'reason for exit',
'Claim status',
];
foreach ($headers as $idx => $header) {
$col = Coordinate::stringFromColumnIndex($idx + 1);
$sheet->setCellValue($col . '1', $header);
}
$rowNo = 2;
$serial = 1;
$dateOfExit = date('d-M-Y');
foreach ($candidateMembers as $member) {
$sheet->setCellValue('A' . $rowNo, $serial);
$sheet->setCellValue('B' . $rowNo, (string) ($member['emp_code'] ?? ''));
$sheet->setCellValue('C' . $rowNo, (string) ($member['name'] ?? ''));
$sheet->setCellValue('D' . $rowNo, 'deletion');
$sheet->setCellValue('E' . $rowNo, $dateOfExit);
$sheet->setCellValue('F' . $rowNo, 'tpa deletion');
$sheet->setCellValue('G' . $rowNo, '0');
$rowNo++;
$serial++;
}
for ($c = 1; $c <= count($headers); $c++) {
$col = Coordinate::stringFromColumnIndex($c);
$sheet->getColumnDimension($col)->setAutoSize(true);
}
$generatedFileName = sprintf(
'tpa_auto_deletion_%d_%s.xls',
$fileId,
date('Ymd_His')
);
$generatedExcelPath = WRITEPATH . 'uploads/excel/' . $generatedFileName;
$writer = new Xls($spreadsheet);
$writer->save($generatedExcelPath);
// return "HI";
// 1) Create files-table entry for EmployeeServiceController::employeeDisembark.
$newFileId = $this->fileModel->insert([
'file_name' => $generatedFileName,
'client_id' => $clientId,
'policy_id' => $clientPolicyId,
'created_by' => (int) ($fileInfo['created_by'] ?? get_session_userid()),
'status' => 'inprogress',
'action' => 'deletion',
'client_branch_id' => $clientBranchId,
'uploaded_by' => 1,
'hr_file_id' => null,
'hr_id' => null,
]);
if (!$newFileId) {
return [
'status' => false,
'message' => 'Unable to create file entry for generated deletion file.',
'data' => ['file_id' => $fileId, 'generated_file_name' => $generatedFileName],
];
}
// 2) Trigger existing disembark processing and proceed only on success.
$empServiceController = new EmployeeServiceController();
$disembarkResult = $empServiceController->employeeDisembark(['file_id' => (int) $newFileId]);
if (!is_array($disembarkResult)) {
return [
'status' => false,
'message' => 'employeeDisembark failed for generated deletion file.',
'data' => [
'file_id' => $fileId,
'generated_file_id' => (int) $newFileId,
'generated_file_name' => $generatedFileName,
],
];
}
//call existing function to get deletion export data
$batch_data = [
'client_id' => $clientId,
'client_policy_id' => $clientPolicyId,
'client_branch_id' => $clientBranchId,
'insurer_or_tpa' => 'tpa',
'event_type' => 'deletion',
'actions' => 'export',
'file_name' => '',
];
$endorsementTs = date('YmdHis');
$objects = $this->employeePolicyModel->getDeletionEmployeeDataForExportExcel($batch_data);
// print_rr($objects);die;
foreach ($objects as $obj) {
$obj->endorsement_id = $endorsementTs;
}
$excel_header_columns = [
['column_index' => 0, 'column_name' => 'S.No', 'db_column_name' => 'index'],
['column_index' => 1, 'column_name' => 'EMP ID', 'db_column_name' => 'emp_code'],
['column_index' => 2, 'column_name' => 'EMP NAME', 'db_column_name' => 'emp_name'],
['column_index' => 3, 'column_name' => 'DOB', 'db_column_name' => 'emp_dob'],
['column_index' => 4, 'column_name' => 'GENDER', 'db_column_name' => 'emp_gender'],
['column_index' => 5, 'column_name' => 'RELATIONSHIP', 'db_column_name' => 'emp_relationship'],
['column_index' => 6, 'column_name' => 'SUM INSURED', 'db_column_name' => 'basic_cover_si'],
['column_index' => 7, 'column_name' => 'Date of Leaving', 'db_column_name' => 'dateofexit'],
['column_index' => 8, 'column_name' => 'Policy End Date', 'db_column_name' => 'policy_end_date'],
['column_index' => 9, 'column_name' => 'No Of Days', 'db_column_name' => 'no_of_days'],
['column_index' => 10, 'column_name' => 'Premium', 'db_column_name' => 'premium'],
['column_index' => 11, 'column_name' => 'Pro Rata Premium', 'db_column_name' => 'pro_rata_premium'],
['column_index' => 12, 'column_name' => 'GST', 'db_column_name' => 'gst'],
['column_index' => 13, 'column_name' => 'Total', 'db_column_name' => 'total'],
['column_index' => 14, 'column_name' => 'Claim Status', 'db_column_name' => 'claim_status'],
['column_index' => 15, 'column_name' => 'ENDORSEMENT_ID', 'db_column_name' => 'endorsement_id']
];
$excel_data_info = generate_insurer_based_excel($excel_header_columns, $objects);
// $tempFile = tmpfile();
$generatedImportFileName = sprintf(
'tpa_auto_deletion_import_%d_%s.xlsx',
$fileId,
date('Ymd_His')
);
$generatedImportPath = WRITEPATH . 'uploads/import_excel/' . $generatedImportFileName;
$success = generate_excel($excel_data_info['header'], $excel_data_info['data'], $generatedImportPath);
// print_rr($success);
// die;
// 3) Build a separate import-format file from sample_import_Deletion.xlsx
// for batch_file import validation pipeline.
// $importTemplatePath = ROOTPATH . 'public/sample_import_excel/sample_import_Deletion.xlsx';
// if (!file_exists($importTemplatePath)) {
// return [
// 'status' => false,
// 'message' => 'Import template file not found for deletion batch file format.',
// 'data' => [
// 'file_id' => $fileId,
// 'generated_file_id' => (int) $newFileId,
// 'template_path' => $importTemplatePath,
// ],
// ];
// }
// $importSpreadsheet = IOFactory::load($importTemplatePath);
// $importSheet = $importSpreadsheet->getActiveSheet();
// $importRowNo = 2;
// $importSerial = 1;
// $endorsementTs = date('YmdHis');
// $formatDate = static function ($value): string {
// if (empty($value)) {
// return '';
// }
// $ts = strtotime((string) $value);
// if ($ts === false) {
// return (string) $value;
// }
// return date('d-M-Y', $ts);
// };
// foreach ($candidateMembers as $memberKey => $member) {
// $policyEndDateRaw = (string) ($member['policy_end_date'] ?? '');
// $policyEndTs = strtotime($policyEndDateRaw);
// $exitTs = strtotime($dateOfExit);
// $noOfDays = 0;
// if ($policyEndTs !== false && $exitTs !== false && $policyEndTs >= $exitTs) {
// $noOfDays = (int) floor(($policyEndTs - $exitTs) / 86400);
// }
// $premium = (float) ($member['premium'] ?? 0);
// $proRata = $noOfDays > 0 ? round(($premium * $noOfDays) / 365, 2) : 0.00;
// $gst = round($proRata * 0.18, 2);
// $total = round($proRata + $gst, 2);
// $claimStatus = ((string) ($member['claim_status'] ?? '0') === '1') ? '1' : '0';
// $importSheet->setCellValue('A' . $importRowNo, $importSerial);
// $importSheet->setCellValue('B' . $importRowNo, (string) ($member['emp_code'] ?? ''));
// $importSheet->setCellValue('C' . $importRowNo, (string) ($member['name'] ?? ''));
// $importSheet->setCellValue('D' . $importRowNo, $formatDate($member['dob'] ?? ''));
// $importSheet->setCellValue('E' . $importRowNo, (string) ($member['gender'] ?? ''));
// $importSheet->setCellValue('F' . $importRowNo, (string) ($member['relationship'] ?? ''));
// $importSheet->setCellValue('G' . $importRowNo, (string) ($member['basic_cover_si'] ?? ''));
// $importSheet->setCellValue('H' . $importRowNo, $dateOfExit);
// $importSheet->setCellValue('I' . $importRowNo, $formatDate($policyEndDateRaw));
// $importSheet->setCellValue('J' . $importRowNo, (string) $noOfDays);
// $importSheet->setCellValue('K' . $importRowNo, (string) round($premium, 2));
// $importSheet->setCellValue('L' . $importRowNo, (string) $proRata);
// $importSheet->setCellValue('M' . $importRowNo, (string) $gst);
// $importSheet->setCellValue('N' . $importRowNo, (string) $total);
// $importSheet->setCellValue('O' . $importRowNo, $claimStatus);
// $endorsementNo = 'TPA_ENDO_' . $endorsementTs . '_' . $memberKey;
// $importSheet->setCellValue('P' . $importRowNo, $endorsementNo);
// $importRowNo++;
// $importSerial++;
// }
// $generatedImportFileName = sprintf(
// 'tpa_auto_deletion_import_%d_%s.xlsx',
// $fileId,
// date('Ymd_His')
// );
// $generatedImportPath = WRITEPATH . 'uploads/import_excel/' . $generatedImportFileName;
// $importWriter = new Xlsx($importSpreadsheet);
// $importWriter->save($generatedImportPath);
$newBatchData = [
'client_id' => $clientId,
'client_policy_id' => $clientPolicyId,
'client_branch_id' => $clientBranchId,
'event_type' => 'deletion',
'actions' => 'import',
'insurer_or_tpa' => 'insurer',
'batch_code' => generate_random_string(4),
'created_by' => (int) ($fileInfo['created_by'] ?? get_session_userid()),
'status' => 'pending',
'file_name' => $generatedImportFileName,
'count' => count($candidateMembers),
];
$newBatchFileId = $this->batchFileModel->insert($newBatchData);
if (!$newBatchFileId) {
return [
'status' => false,
'message' => 'Unable to create batch file entry for generated deletion file.',
'data' => ['file_id' => $fileId, 'generated_file_name' => $generatedImportFileName],
];
}
$empDataServiceController = new EmpDataServiceController();
$importValidationResult = $empDataServiceController->importDeletionValidation(['file_id' => (int) $newBatchFileId]);
$resultPayload = [
'source_file_id' => $fileId,
'generated_file_id' => (int) $newFileId,
'generated_batch_file_id' => (int) $newBatchFileId,
'generated_file_name' => $generatedFileName,
'generated_import_file_name' => $generatedImportFileName,
'candidate_count' => count($candidateMembers),
'endorsement_count' => count($disembarkResult),
'import_validation_result' => $importValidationResult,
];
$this->myLogger->logme('error', 'TPA auto deletion file initialized: ' . json_encode($resultPayload));
return [
'status' => true,
'message' => 'Deletion file generated and queued for validation.',
'data' => $resultPayload,
];
} catch (\Throwable $e) {
$this->myLogger->logme(
'error',
'Error in initializeDeletionProcessForTpaApiData: ' . $e->getMessage(),
['file_id' => (int) $file_id]
);
return [
'status' => false,
'message' => 'Unable to initialize deletion process from TPA data.',
'data' => [
'file_id' => (int) $file_id,
'error' => $e->getMessage(),
],
];
}
}
} }

View File

@ -7,6 +7,7 @@ use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface; use CodeIgniter\HTTP\ResponseInterface;
use App\Filters\Cors;
/** /**
* AuthApiFilter * AuthApiFilter
* *
@ -26,10 +27,12 @@ use CodeIgniter\HTTP\ResponseInterface;
class AuthApiRateLimitFilter implements FilterInterface class AuthApiRateLimitFilter implements FilterInterface
{ {
protected RateLimiterService $limiter; protected RateLimiterService $limiter;
protected Cors $corsFilter;
public function __construct() public function __construct()
{ {
$this->limiter = new RateLimiterService(); $this->limiter = new RateLimiterService();
$this->corsFilter = new Cors();
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
@ -138,6 +141,7 @@ class AuthApiRateLimitFilter implements FilterInterface
'type' => $result['type'] ?? 'request', 'type' => $result['type'] ?? 'request',
], ],
])); ]));
$this->corsFilter->after($request, $response);
return $response; return $response;
} }
} }

View File

@ -172,7 +172,7 @@ input:checked + .slider-branch-contact:before {
<label for="branch_name">Branch Name<span class="text-danger">*</span></label> <label for="branch_name">Branch Name<span class="text-danger">*</span></label>
<input type="text" class="form-control" id="branch_name" placeholder="Enter Branch Name" <input type="text" class="form-control" id="branch_name" placeholder="Enter Branch Name"
name="branch_name" required data-parsley-minlength="3" name="branch_name" required data-parsley-minlength="3"
data-parsley-pattern="^[a-zA-Z0-9\\s_-]+$" data-parsley-pattern="^[a-zA-Z0-9\s_-]+$"
data-parsley-pattern-message="Branch Name can contain letters, numbers, spaces, underscore (_) and hyphen (-)."> data-parsley-pattern-message="Branch Name can contain letters, numbers, spaces, underscore (_) and hyphen (-).">
</div> </div>
<div class="form-group col-md-6"> <div class="form-group col-md-6">
@ -180,7 +180,9 @@ input:checked + .slider-branch-contact:before {
<input type="text" class="form-control" id="branch_code" placeholder="Enter Branch Code" <input type="text" class="form-control" id="branch_code" placeholder="Enter Branch Code"
name="branch_code" onchange="setDefaultUnitValue(this)" required name="branch_code" onchange="setDefaultUnitValue(this)" required
data-parsley-pattern="^[a-zA-Z0-9_-]+$" data-parsley-pattern="^[a-zA-Z0-9_-]+$"
data-parsley-pattern-message="Branch Code can contain letters, numbers, underscore (_) and hyphen (-)."> data-parsley-pattern-message="Branch Code can contain letters, numbers, underscore (_) and hyphen (-)."
oninput="this.value = this.value.replace(/[^A-Za-z0-9_-]/g, '')"
onblur="this.value = this.value.trim();">
</div> </div>
</div> </div>
@ -209,14 +211,14 @@ input:checked + .slider-branch-contact:before {
<label for="district">District<span class="text-danger">*</span></label> <label for="district">District<span class="text-danger">*</span></label>
<input type="text" class="form-control" id="district" placeholder="Enter District" <input type="text" class="form-control" id="district" placeholder="Enter District"
name="district" required name="district" required
data-parsley-pattern="^[a-zA-Z0-9\\s-]+$" data-parsley-pattern="^[a-zA-Z0-9\s-]+$"
data-parsley-pattern-message="District can contain letters, numbers, spaces, and hyphens."> data-parsley-pattern-message="District can contain letters, numbers, spaces, and hyphens.">
</div> </div>
<div class="form-group col-md-3"> <div class="form-group col-md-3">
<label for="city">City<span class="text-danger">*</span></label> <label for="city">City<span class="text-danger">*</span></label>
<input type="text" class="form-control" id="branch_city" placeholder="Enter City" <input type="text" class="form-control" id="branch_city" placeholder="Enter City"
name="city" required name="city" required
data-parsley-pattern="^[a-zA-Z0-9\\s-]+$" data-parsley-pattern="^[a-zA-Z0-9\s-]+$"
data-parsley-pattern-message="City can contain letters, numbers, spaces, and hyphens."> data-parsley-pattern-message="City can contain letters, numbers, spaces, and hyphens.">
</div> </div>
<div class="form-group col-md-3"> <div class="form-group col-md-3">
@ -771,7 +773,7 @@ function appendContactHtml(contact = false, reset = false) {
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="${uniqueId}_first_name">Name<span class="text-danger">*</span></label> <label for="${uniqueId}_first_name">Name<span class="text-danger">*</span></label>
<input value="${contact !== undefined && contact !== false ? contact.name : ''}" type="text" class="form-control" placeholder="Enter Contact Name" name="name[]" id="${uniqueId}_name" required <input value="${contact !== undefined && contact !== false ? contact.name : ''}" type="text" class="form-control" placeholder="Enter Contact Name" name="name[]" id="${uniqueId}_name" required
data-parsley-pattern="^[A-Za-z\\s]+$" data-parsley-pattern="^[A-Za-z\s]+$"
data-parsley-pattern-message="Contact name may contain only letters and spaces."> data-parsley-pattern-message="Contact name may contain only letters and spaces.">
</div> </div>
<div class="form-group col-md-6"> <div class="form-group col-md-6">
@ -1364,7 +1366,8 @@ function setDefaultUnitValue()
{ {
var client_id = $('#client_id_branch').val(); var client_id = $('#client_id_branch').val();
var branch_code = $('#branch_code').val(); var branch_code = ($('#branch_code').val() || '').trim();
$('#branch_code').val(branch_code);
var units = $('#selected').val(); var units = $('#selected').val();
console.log('client_id', client_id) console.log('client_id', client_id)

View File

@ -108,15 +108,17 @@
<input type="text" class="form-control" id="branch_name" <input type="text" class="form-control" id="branch_name"
placeholder="Enter Branch Name" name="branch_name" required placeholder="Enter Branch Name" name="branch_name" required
data-parsley-minlength="3" data-parsley-minlength="3"
data-parsley-pattern="^[a-zA-Z0-9\\s_-]+$" data-parsley-pattern="^[a-zA-Z0-9\s_-]+$"
data-parsley-pattern-message="Branch Name can contain letters, numbers, spaces, underscore (_) and hyphen (-)."> data-parsley-pattern-message="Branch Name can contain letters, numbers, spaces, underscore (_) and hyphen (-).">
</div> </div>
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="branch_code">Branch Code <span class="text-danger">*</span></label> <label for="branch_code">Branch Code <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="branch_code" <input type="text" class="form-control" id="branch_code"
placeholder="Enter Branch Code" name="branch_code" required placeholder="Enter Branch Code" name="branch_code" required
data-parsley-pattern="^[a-zA-Z0-9_-]+$" data-parsley-pattern="^[a-zA-Z0-9\s_-]+$"
data-parsley-pattern-message="Branch Code can contain letters, numbers, underscore (_) and hyphen (-)."> data-parsley-pattern-message="Branch Code can contain letters, numbers, spaces, underscore (_) and hyphen (-)."
oninput="this.value = this.value.replace(/[^A-Za-z0-9_\- ]/g, '')"
onblur="this.value = this.value.trim();">
</div> </div>
</div> </div>
@ -147,7 +149,7 @@
<label for="district">District <span class="text-danger">*</span></label> <label for="district">District <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="district" <input type="text" class="form-control" id="district"
placeholder="Enter District" name="district" required placeholder="Enter District" name="district" required
data-parsley-pattern="^[a-zA-Z0-9\\s-]+$" data-parsley-pattern="^[a-zA-Z0-9\s-]+$"
data-parsley-pattern-message="District can contain letters, numbers, spaces, and hyphens."> data-parsley-pattern-message="District can contain letters, numbers, spaces, and hyphens.">
</div> </div>
</div> </div>
@ -158,7 +160,7 @@
<label for="branch_city">City <span class="text-danger">*</span></label> <label for="branch_city">City <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="branch_city" <input type="text" class="form-control" id="branch_city"
placeholder="Enter City" name="city" required placeholder="Enter City" name="city" required
data-parsley-pattern="^[a-zA-Z0-9\\s-]+$" data-parsley-pattern="^[a-zA-Z0-9\s-]+$"
data-parsley-pattern-message="City can contain letters, numbers, spaces, and hyphens."> data-parsley-pattern-message="City can contain letters, numbers, spaces, and hyphens.">
</div> </div>
<div class="form-group col-md-6"> <div class="form-group col-md-6">
@ -197,8 +199,8 @@
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label for="name">Name <span class="text-danger">*</span></label> <label for="name">Name <span class="text-danger">*</span></label>
<input value="" type="text" class="form-control" placeholder="Enter Contact Name" name="name[]" id="name" required <input value="" type="text" class="form-control" placeholder="Enter Contact Name" name="name[]" id="name" required
data-parsley-pattern="^[A-Za-z\\s]+$" data-parsley-pattern="^[a-zA-Z0-9\s_-]+$"
data-parsley-pattern-message="Contact name may contain only letters and spaces."> data-parsley-pattern-message="Contact name can contain letters, numbers, spaces, underscore (_) and hyphen (-).">
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row">
@ -213,7 +215,7 @@
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label for="email">Email <span class="text-danger">*</span></label> <label for="email">Email <span class="text-danger">*</span></label>
<input value="" type="email" data-parsley-trigger="change" class="form-control" placeholder="Enter Contact Email" name="email[]" id="email" required <input value="" type="email" data-parsley-trigger="change" class="form-control" placeholder="Enter Contact Email" name="email[]" id="email" required
data-parsley-pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" data-parsley-pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
data-parsley-pattern-message="Please enter a valid email format (e.g., name@domain.com)."> data-parsley-pattern-message="Please enter a valid email format (e.g., name@domain.com).">
</div> </div>
</div> </div>
@ -456,7 +458,7 @@
if (!/^[a-zA-Z0-9\s_-]+$/.test(v)) return 'Branch Name can contain letters, numbers, spaces, underscore (_) and hyphen (-).'; if (!/^[a-zA-Z0-9\s_-]+$/.test(v)) return 'Branch Name can contain letters, numbers, spaces, underscore (_) and hyphen (-).';
return ''; return '';
case 'branch_code': case 'branch_code':
if (!/^[a-zA-Z0-9_-]+$/.test(v)) return 'Branch Code can contain letters, numbers, underscore (_) and hyphen (-).'; if (!/^[a-zA-Z0-9\s_-]+$/.test(v)) return 'Branch Code can contain letters, numbers, spaces, underscore (_) and hyphen (-).';
return ''; return '';
case 'address1': case 'address1':
return ''; return '';
@ -968,8 +970,8 @@
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label>Name<span class="text-danger">*</span></label> <label>Name<span class="text-danger">*</span></label>
<input value="${contact ? contact.name : ''}" type="text" class="form-control" placeholder="Enter Contact Name" name="name[]" required <input value="${contact ? contact.name : ''}" type="text" class="form-control" placeholder="Enter Contact Name" name="name[]" required
data-parsley-pattern="^[A-Za-z\\s]+$" data-parsley-pattern="^[a-zA-Z0-9\s_-]+$"
data-parsley-pattern-message="Contact name may contain only letters and spaces."> data-parsley-pattern-message="Contact name can contain letters, numbers, spaces, underscore (_) and hyphen (-).">
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row">
@ -984,7 +986,7 @@
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label>Email<span class="text-danger">*</span></label> <label>Email<span class="text-danger">*</span></label>
<input value="${contact ? contact.email : ''}" type="email" data-parsley-trigger="change" class="form-control" placeholder="Enter Contact Email" name="email[]" required <input value="${contact ? contact.email : ''}" type="email" data-parsley-trigger="change" class="form-control" placeholder="Enter Contact Email" name="email[]" required
data-parsley-pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" data-parsley-pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
data-parsley-pattern-message="Please enter a valid email format (e.g., name@domain.com)."> data-parsley-pattern-message="Please enter a valid email format (e.g., name@domain.com).">
</div> </div>
</div> </div>

View File

@ -277,6 +277,7 @@
<script> <script>
(function (window, document) { (function (window, document) {
var MAX_GLOBAL_UPLOAD_BYTES = 25 * 1024 * 1024; // 25 MB var MAX_GLOBAL_UPLOAD_BYTES = 25 * 1024 * 1024; // 25 MB
var textEncoder = typeof TextEncoder !== 'undefined' ? new TextEncoder() : null;
function formatBytesToMb(bytes) { function formatBytesToMb(bytes) {
return (bytes / (1024 * 1024)).toFixed(2); return (bytes / (1024 * 1024)).toFixed(2);
@ -336,6 +337,51 @@
return true; return true;
} }
function formatPayloadSize(bytes) {
return {
bytes: bytes,
kb: (bytes / 1024).toFixed(2),
mb: (bytes / (1024 * 1024)).toFixed(2)
};
}
function getTextBytes(value) {
var textValue = String(value == null ? '' : value);
if (textEncoder) {
return textEncoder.encode(textValue).length;
}
return unescape(encodeURIComponent(textValue)).length;
}
function calculateFormPayloadBytes(form) {
if (!form || typeof FormData === 'undefined') {
return 0;
}
var total = 0;
var formData = new FormData(form);
formData.forEach(function (value) {
if (value instanceof File) {
total += value.size || 0;
} else {
total += getTextBytes(value);
}
});
return total;
}
function getFormIdentity(form) {
if (!form) {
return 'unknown-form';
}
if (form.id) {
return '#' + form.id;
}
if (form.name) {
return 'name="' + form.name + '"';
}
return form.getAttribute('action') || 'anonymous-form';
}
window.validateGlobalUploadPayload = validateGlobalUploadPayload; window.validateGlobalUploadPayload = validateGlobalUploadPayload;
document.addEventListener('change', function (event) { document.addEventListener('change', function (event) {
@ -355,10 +401,16 @@
if (!form || !form.matches || !form.matches('form')) { if (!form || !form.matches || !form.matches('form')) {
return; return;
} }
if (!form.querySelector('input[type="file"]')) {
return; var payloadBytes = calculateFormPayloadBytes(form);
} var payloadMeta = formatPayloadSize(payloadBytes);
if (!validateGlobalUploadPayload(form)) { console.log(
'[Form Payload] ' + getFormIdentity(form) +
' => ' + payloadMeta.bytes + ' bytes (' +
payloadMeta.kb + ' KB, ' + payloadMeta.mb + ' MB)'
);
if (form.querySelector('input[type="file"]') && !validateGlobalUploadPayload(form)) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
} }

View File

@ -10,7 +10,7 @@
<div class="text-center"> <div class="text-center">
<div style="padding-left: 10px;" class="mb-3"> <div style="padding-left: 10px;" class="mb-3">
<div class="row"> <div class="row">
<img src="https://venbait.in/nhance/helpdesk/dev/assets/helpdeskz/images/user.jpg" <img src="<?= base_url('public/assets/images/user.jpg') ?>"
class="user-avatar rounded-circle img-fluid col-mb-6" style="max-width: 70px"> class="user-avatar rounded-circle img-fluid col-mb-6" style="max-width: 70px">
<div style="padding-left: 10px;padding-top: 15px;" class="col-mb-6"><?= $message_data['emp_name'] ?></div> <div style="padding-left: 10px;padding-top: 15px;" class="col-mb-6"><?= $message_data['emp_name'] ?></div>
</div> </div>
@ -58,7 +58,7 @@
<div class="text-center"> <div class="text-center">
<div style="padding-left: 10px;" class="mb-3"> <div style="padding-left: 10px;" class="mb-3">
<div class="row"> <div class="row">
<img src="https://venbait.in/nhance/helpdesk/dev/assets/helpdeskz/images/agent.jpg" <img src="<?= base_url('public/assets/images/agent.jpg') ?>"
class="user-avatar rounded-circle img-fluid col-mb-6" style="max-width: 70px"> class="user-avatar rounded-circle img-fluid col-mb-6" style="max-width: 70px">
<div style="padding-left: 10px;padding-top: 15px;" class="col-mb-6"><?= $message['user_name'] ?? "Auto Mail" ?></div> <div style="padding-left: 10px;padding-top: 15px;" class="col-mb-6"><?= $message['user_name'] ?? "Auto Mail" ?></div>

View File

@ -242,14 +242,16 @@
<label for="branch_name">Branch Name <span class="text-danger">*</span></label> <label for="branch_name">Branch Name <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="branch_name" placeholder="Enter Branch Name" name="branch_name" required maxlength="255" data-parsley-maxlength="255" <input type="text" class="form-control" id="branch_name" placeholder="Enter Branch Name" name="branch_name" required maxlength="255" data-parsley-maxlength="255"
data-parsley-minlength="3" data-parsley-minlength="3"
data-parsley-pattern="^[a-zA-Z0-9\\s_-]+$" data-parsley-pattern="^[a-zA-Z0-9\s_-]+$"
data-parsley-pattern-message="Branch Name can contain letters, numbers, spaces, underscore (_) and hyphen (-)."> data-parsley-pattern-message="Branch Name can contain letters, numbers, spaces, underscore (_) and hyphen (-).">
</div> </div>
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="branch_code">Branch Code <span class="text-danger">*</span></label> <label for="branch_code">Branch Code <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="branch_code" placeholder="Enter Branch Code" name="branch_code" required maxlength="100" data-parsley-maxlength="100" <input type="text" class="form-control" id="branch_code" placeholder="Enter Branch Code" name="branch_code" required maxlength="100" data-parsley-maxlength="100"
data-parsley-pattern="^[a-zA-Z0-9_-]+$" data-parsley-pattern="^[a-zA-Z0-9\s_-]+$"
data-parsley-pattern-message="Branch Code can contain letters, numbers, underscore (_) and hyphen (-)."> data-parsley-pattern-message="Branch Code can contain letters, numbers, spaces, underscore (_) and hyphen (-)."
oninput="this.value = this.value.replace(/[^A-Za-z0-9_\- ]/g, '')"
onblur="this.value = this.value.trim();">
</div> </div>
</div> </div>
@ -280,7 +282,7 @@
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="district">District <span class="text-danger">*</span></label> <label for="district">District <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="district" placeholder="Enter District" name="district" required maxlength="100" data-parsley-maxlength="100" <input type="text" class="form-control" id="district" placeholder="Enter District" name="district" required maxlength="100" data-parsley-maxlength="100"
data-parsley-pattern="^[a-zA-Z0-9\\s-]+$" data-parsley-pattern="^[a-zA-Z0-9\s-]+$"
data-parsley-pattern-message="District can contain letters, numbers, spaces, and hyphens."> data-parsley-pattern-message="District can contain letters, numbers, spaces, and hyphens.">
</div> </div>
</div> </div>
@ -290,7 +292,7 @@
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="branch_city">City <span class="text-danger">*</span></label> <label for="branch_city">City <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="branch_city" placeholder="Enter City" name="city" required maxlength="100" data-parsley-maxlength="100" <input type="text" class="form-control" id="branch_city" placeholder="Enter City" name="city" required maxlength="100" data-parsley-maxlength="100"
data-parsley-pattern="^[a-zA-Z0-9\\s-]+$" data-parsley-pattern="^[a-zA-Z0-9\s-]+$"
data-parsley-pattern-message="City can contain letters, numbers, spaces, and hyphens."> data-parsley-pattern-message="City can contain letters, numbers, spaces, and hyphens.">
</div> </div>
<div class="form-group col-md-6"> <div class="form-group col-md-6">
@ -325,8 +327,8 @@
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label for="name">Name <span class="text-danger">*</span></label> <label for="name">Name <span class="text-danger">*</span></label>
<input value="" type="text" class="form-control" placeholder="Enter Contact Name" name="name[]" id="name" required maxlength="100" data-parsley-maxlength="100" <input value="" type="text" class="form-control" placeholder="Enter Contact Name" name="name[]" id="name" required maxlength="100" data-parsley-maxlength="100"
data-parsley-pattern="^[A-Za-z\\s]+$" data-parsley-pattern="^[a-zA-Z0-9\s_-]+$"
data-parsley-pattern-message="Contact name may contain only letters and spaces."> data-parsley-pattern-message="Contact name can contain letters, numbers, spaces, underscore (_) and hyphen (-).">
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row">
@ -341,7 +343,7 @@
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label for="email">Email <span class="text-danger">*</span></label> <label for="email">Email <span class="text-danger">*</span></label>
<input value="" type="email" data-parsley-trigger="change" class="form-control" placeholder="Enter Contact Email" name="email[]" id="email" required <input value="" type="email" data-parsley-trigger="change" class="form-control" placeholder="Enter Contact Email" name="email[]" id="email" required
data-parsley-pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" data-parsley-pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
data-parsley-pattern-message="Please enter a valid email format (e.g., name@domain.com)."> data-parsley-pattern-message="Please enter a valid email format (e.g., name@domain.com).">
</div> </div>
</div> </div>
@ -970,8 +972,8 @@ function renumberContacts() {
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label>Name<span class="text-danger">*</span></label> <label>Name<span class="text-danger">*</span></label>
<input value="${contact ? contact.name : ''}" type="text" class="form-control" placeholder="Enter Contact Name" name="name[]" required maxlength="100" data-parsley-maxlength="100" <input value="${contact ? contact.name : ''}" type="text" class="form-control" placeholder="Enter Contact Name" name="name[]" required maxlength="100" data-parsley-maxlength="100"
data-parsley-pattern="^[A-Za-z\\s]+$" data-parsley-pattern="^[a-zA-Z0-9\s_-]+$"
data-parsley-pattern-message="Contact name may contain only letters and spaces."> data-parsley-pattern-message="Contact name can contain letters, numbers, spaces, underscore (_) and hyphen (-).">
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row">
@ -986,7 +988,7 @@ function renumberContacts() {
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label>Email<span class="text-danger">*</span></label> <label>Email<span class="text-danger">*</span></label>
<input value="${contact ? contact.email : ''}" type="email" data-parsley-trigger="change" class="form-control" placeholder="Enter Contact Email" name="email[]" required <input value="${contact ? contact.email : ''}" type="email" data-parsley-trigger="change" class="form-control" placeholder="Enter Contact Email" name="email[]" required
data-parsley-pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" data-parsley-pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
data-parsley-pattern-message="Please enter a valid email format (e.g., name@domain.com)."> data-parsley-pattern-message="Please enter a valid email format (e.g., name@domain.com).">
</div> </div>
</div> </div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB