MERGE_TEST_TPA_RECON&DELETION&FE_VALIDATIONS
This commit is contained in:
commit
0164fea8af
@ -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();
|
||||||
|
|
||||||
|
|||||||
@ -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(),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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>
|
||||||
|
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
BIN
public/assets/images/agent.jpg
Normal file
BIN
public/assets/images/agent.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
BIN
public/assets/images/user.jpg
Normal file
BIN
public/assets/images/user.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
Loading…
Reference in New Issue
Block a user