GWM : VAPT Scan Vulnerabilities

This commit is contained in:
Gowtham M 2026-01-08 17:00:17 +05:30
commit a1e8e8b7d4
28 changed files with 1946 additions and 427 deletions

185
.env.sample Normal file
View File

@ -0,0 +1,185 @@
#--------------------------------------------------------------------
# ENVIRONMENT
#--------------------------------------------------------------------
CI_ENVIRONMENT = development
#--------------------------------------------------------------------
# APP
#--------------------------------------------------------------------
app.baseURL =
app.appTimezone = 'Asia/Kolkata'
# If you have trouble with `.`, you could also use `_`.
# app_baseURL = ''
# app.forceGlobalSecureRequests = false
# app.CSPEnabled = false
#--------------------------------------------------------------------
# DATABASE
#--------------------------------------------------------------------
DB_SSL_ENABLE = false
database.default.hostname =
database.default.database =
database.default.username =
database.default.password =
# database.default.DBDriver = MySQLi
# database.default.DBPrefix =
# database.default.port = 3306
#--------------------------------------------------------------------
# CONTENT SECURITY POLICY
#--------------------------------------------------------------------
# contentsecuritypolicy.reportOnly = false
# contentsecuritypolicy.defaultSrc = 'none'
# contentsecuritypolicy.scriptSrc = 'self'
# contentsecuritypolicy.styleSrc = 'self'
# contentsecuritypolicy.imageSrc = 'self'
# contentsecuritypolicy.baseURI = null
# contentsecuritypolicy.childSrc = null
# contentsecuritypolicy.connectSrc = 'self'
# contentsecuritypolicy.fontSrc = null
# contentsecuritypolicy.formAction = null
# contentsecuritypolicy.frameAncestors = null
# contentsecuritypolicy.frameSrc = null
# contentsecuritypolicy.mediaSrc = null
# contentsecuritypolicy.objectSrc = null
# contentsecuritypolicy.pluginTypes = null
# contentsecuritypolicy.reportURI = null
# contentsecuritypolicy.sandbox = false
# contentsecuritypolicy.upgradeInsecureRequests = false
# contentsecuritypolicy.styleNonceTag = '{csp-style-nonce}'
# contentsecuritypolicy.scriptNonceTag = '{csp-script-nonce}'
# contentsecuritypolicy.autoNonce = true
#--------------------------------------------------------------------
# COOKIE
#--------------------------------------------------------------------
# cookie.prefix = ''
# cookie.expires = 0
# cookie.path = '/'
# cookie.domain = ''
# cookie.secure = false
# cookie.httponly = false
# cookie.samesite = 'Lax'
# cookie.raw = false
#--------------------------------------------------------------------
# ENCRYPTION
#--------------------------------------------------------------------
# encryption.key =
# encryption.driver = OpenSSL
# encryption.blockSize = 16
# encryption.digest = SHA512
#--------------------------------------------------------------------
# HONEYPOT
#--------------------------------------------------------------------
# honeypot.hidden = 'true'
# honeypot.label = 'Fill This Field'
# honeypot.name = 'honeypot'
# honeypot.template = '<label>{label}</label><input type="text" name="{name}" value=""/>'
# honeypot.container = '<div style="display:none">{template}</div>'
#--------------------------------------------------------------------
# SECURITY
#--------------------------------------------------------------------
# security.csrfProtection = 'cookie'
# security.tokenRandomize = false
# security.tokenName = 'csrf_token_name'
# security.headerName = 'X-CSRF-TOKEN'
# security.cookieName = 'csrf_cookie_name'
# security.expires = 7200
# security.regenerate = true
# security.redirect = false
# security.samesite = 'Lax'
#--------------------------------------------------------------------
# SESSION
#--------------------------------------------------------------------
# session.driver = 'CodeIgniter\Session\Handlers\FileHandler'
# session.cookieName = 'ci_session'
session.expiration = 28800
# session.savePath = null
# session.matchIP = false
# session.timeToUpdate = 300
# session.regenerateDestroy = false
#--------------------------------------------------------------------
# LOGGER
#--------------------------------------------------------------------
logger.threshold = 4
#--------------------------------------------------------------------
# CURLRequest
#--------------------------------------------------------------------
# curlrequest.shareOptions = true
GOOGLE_OAUTH_APP_NAME =
#GOOGLE_OAUTH_CLIENT_ID =
#GOOGLE_OAUTH_CLIENT_SECRET =
GOOGLE_OAUTH_CLIENT_ID =
GOOGLE_OAUTH_CLIENT_SECRET =
GOOGLE_OAUTH_REDIRECT_URI =
GOOGLE_OAUTH_SCOPES =
App_Url =
NHANCE_LOGO =
helpdeskURL =
TOKENTIMEOUT =
POST_ENROLLMENT_APP_LINK =
GDRIVE_ROOT_FOLDER_ID =
email.fromEmail =
email.fromName =
ZEPTO_API_KEY =
email.SMTPPass =
#--------------------------------------------------------------------
# SET COOKIE DATA
#--------------------------------------------------------------------
cookie.Path = '/';
cookie.Domain = '.nhanceindia.in'; //Enter Domain Name with preceding .(dot) -> .nhanceindia.in
cookie.secure = 'true';// if https set as true or if http set as false
unlayer.projectID =
email.enquiryMail =
POST_ENROLLMENT_BASEURL =
database.postDB.hostname =
database.postDB.database =
database.postDB.username =
database.postDB.password =
database.postDB.DBDriver =
database.postDB.DBPrefix =
database.postDB.port =
POST_ENROLLMENT_BASEURL =
#SMS
SMS_API_KEY =
SMS_SENDER_ID =
SMS_TEMPLATE_ID =
SMS_SERVICE_NAME =
SMS_APP_NAME =
# CORS Configuration
CORS_ALLOWED_ORIGINS=
CORS_ALLOW_CREDENTIALS=true
CORS_ALLOWED_METHODS=GET,POST,PUT,PATCH,DELETE,OPTIONS
CORS_ALLOWED_HEADERS=Content-Type,Authorization,X-Requested-With,Accept,Origin,App-Signature
CORS_EXPOSE_HEADERS=X-Total-Count,X-Page-Count,X-RateLimit-Remaining
CORS_MAX_AGE=7200
CORS_DEBUG=true
APP_SIGNATURE =

View File

@ -5,6 +5,28 @@ Options -Indexes
# Rewrite engine
# ----------------------------------------------------------------------
## ADDED for - block any script execution inside folder of public
<If "%{REQUEST_URI} =~ m#/(logo|add_image_upload|e_card_imgs|assets|claim_sample_forms|sample_import_excel|writable)/#">
Deny from all
# Disable PHP engine
<IfModule mod_php.c>
php_flag engine off
</IfModule>
# Disable CGI and other executable handlers
Options -ExecCGI
AddHandler cgi-script .php .pl .py .jsp .asp .sh .cgi
# Block access to any script-like files entirely
<FilesMatch "\.(php|php5|php7|phtml|pl|py|cgi|asp|aspx|sh|rb)$">
ForceType text/plain
#Order allow,deny
Deny from all
</FilesMatch>
</If>
# Turning on the rewrite engine is necessary for the following rules and features.
# FollowSymLinks must be enabled for this to work.
<IfModule mod_rewrite.c>

View File

@ -20,6 +20,7 @@ class Database extends Config
* use if no other is specified.
*/
public string $defaultGroup = 'default';
public string $enableSSL;
/**
* The default database connection.
@ -38,6 +39,7 @@ class Database extends Config
'DBCollat' => 'utf8_general_ci',
'swapPre' => '',
'encrypt' => false,
// 'encrypt' => ['ssl_verify' => true,'ssl_ca' => ROOTPATH .'ca.pem'],
'compress' => false,
'strictOn' => false,
'failover' => [],
@ -95,5 +97,21 @@ class Database extends Config
if (ENVIRONMENT === 'testing') {
$this->defaultGroup = 'tests';
}
$this->enableSSL = env('DB_SSL_ENABLE') ?? false;
if ($this->enableSSL === true || $this->enableSSL === 'true' || $this->enableSSL === 1 || $this->enableSSL === '1') {
// Enable SSL authentication
$this->default['encrypt'] = [
'ssl_ca' => ROOTPATH . 'ca.pem',
'ssl_verify' => true,
];
$this->postDB['encrypt'] = [
'ssl_ca' => ROOTPATH . 'ca.pem',
'ssl_verify' => true,
];
}
}
}

View File

@ -16,6 +16,8 @@ use App\Filters\VerifyAppSignature;
use App\Filters\AuthJWT;
use App\Filters\Cors;
use App\Filters\GlobalPostFileUploadGuard;
use App\Filters\SecurityInputFilter;
class Filters extends BaseConfig
{
@ -39,6 +41,8 @@ class Filters extends BaseConfig
'CloseDbConnection' => CloseDbConnection::class,
'Cors' => Cors::class,
'appSignature' => VerifyAppSignature::class,
'GlobalPostFileUploadGuard' => GlobalPostFileUploadGuard::class,
'SecurityInputFilter' => SecurityInputFilter::class,
];
@ -53,7 +57,8 @@ class Filters extends BaseConfig
'before' => [
'HttpRequestLog' => ['except' => 'cli/*'],
'Cors',
// 'csrf',
'SecurityInputFilter',
'GlobalPostFileUploadGuard',
// 'invalidchars',
],
'after' => [

View File

@ -438,6 +438,7 @@ $routes->cli('cli/sendZeptoMail', 'MasterController::testZeptoSMTP');
$routes->cli('cli/check_bounce_mail_cli', 'MasterController::testCheckBounceMails');
$routes->cli('cli/app_check_list', 'MasterController::appCheckList');
$routes->cli('cli/new_gdrive_token', 'GoogleDriveController::generateNewGoogleDriveAccessToken');
$routes->cli('cli/check_env', 'MasterController::checkEnv');
@ -534,10 +535,12 @@ $routes->group("employeeRest", ['filter' => ['appSignature'] ], function ($route
$routes->post("verifyOtp", "RestAuthenticationController::verifyOtp");
$routes->post("checkPassword", "RestAuthenticationController::checkPassword");
$routes->get("downloadSampleExcel", "EmployeeRestController::downloadSampleExcel");
// $routes->post("getPreEmployeePolicyCount", "EmployeeRestController::getPreEmployeePolicyCount");
});
$routes->post("getPreEmployeePolicyCount","EmployeeRestController::getPreEmployeePolicyCount", ['filter' => ['appSignature']]);
$routes->get("getEmployeeActiveOrInactivePolicy", "EmployeeRestController::getEmployeeActiveOrInactivePolicy");
$routes->get("sendPushNotification", "EmployeeRestController::sendPushNotification");
$routes->post("sendEmail", "EmployeeRestController::send_email");
@ -554,7 +557,7 @@ $routes->get("sendCroneRemainderMail", "DashboardController::sendCroneRemainderM
// $routes->get("getEmployeePolicy", "EmployeeRestController::getEmployeePolicy");
$routes->get("getAddOnPolicy", "EmployeeRestController::getAddOnPolicy");
$routes->post("addEmployeeAndDependence", "EmployeeRestController::addEmployeeAndDependence");
$routes->post("getPreEmployeePolicyCount", "EmployeeRestController::getPreEmployeePolicyCount");

View File

@ -507,7 +507,7 @@ class ClientController extends AdminController
// echo "<pre>";
// print_r($data); die;
$data['placeHolders'] = ['member_name', 'nhance_logo', 'tpa_id', 'ecard_download_link', 'client_logo', 'policy_no', 'member_summary', 'app_link', 'post_enrollment_app_link', 'client_name'];
$data['placeHolders'] = ['member_name', 'nhance_logo', 'tpa_id', 'ecard_download_link', 'client_logo', 'policy_no', 'member_summary', 'app_link', 'post_enrollment_app_link', 'client_name', 'enrollment_open_date', 'enrollment_close_date'];
// dd($data['placeHolders']);
@ -653,7 +653,7 @@ class ClientController extends AdminController
$editData['client_policy'] = $clientPoliceData;
$editData['client_policy']['role'] = get_role_id();
$editData['notification'] = $this->notificationModel->select('template_name,enabled')->where('client_id', $id)->findAll();
$editData['placeHolders'] = ['member_name', 'member_mobile', 'nhance_logo', 'tpa_id', 'ecard_download_link', 'client_logo', 'policy_no', 'member_summary', 'app_link', 'post_enrollment_app_link', 'client_name'];
$editData['placeHolders'] = ['member_name', 'member_mobile', 'nhance_logo', 'tpa_id', 'ecard_download_link', 'client_logo', 'policy_no', 'member_summary', 'app_link', 'post_enrollment_app_link', 'client_name', 'enrollment_open_date', 'enrollment_close_date'];
$editData['auto_fetch_client_list'] = $this->getClientListFromPost();
@ -4623,7 +4623,7 @@ class ClientController extends AdminController
// $res = $employeeRestController->getExcelErrorData(['file_id' => 897]);
// $employeeRestController->employeesOnboardPreprocess(['file_id' => 644]);
// $employeeRestController->employeesOnboardProcess(['file_id' => 835]);
// $employeeRestController->employeesEnrollmentInsert(['file_id' => 836]);
// $res = $employeeRestController->employeesEnrollmentInsert(['file_id' => 1138]);
// $r = Jobs::addJob(['job_name' => 'employeesEnrollmentInsert','payload' => ['file_id' => 721]]);
// dd($res);

View File

@ -179,7 +179,7 @@ class EmployeeController extends AdminController
}
//handles employee & dependent bulk upload with events like inception,addition,deletion, correction and SI enhancements
public function employeesUplodWithEvents()
public function employeesUplodWithEvents($post_data = [])
{
// $empDataServiceController = new EmpDataServiceController();
@ -233,77 +233,184 @@ class EmployeeController extends AdminController
// $this->truncateFileData(747, 5) ;
// print_rr($this->cloneWorksheet());
// die();
if ($this->request->getMethod() == 'post') {
// old
// if ($this->request->getMethod() == 'post') {
// //validate uploaded file
// $filename = '';
// $fileSize = '';
// $validated = $this->validate([
// 'emplist' => [
// 'uploaded[emplist]',
// 'mime_in[emplist,application/vnd.ms-excel,application/vnd,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.oasis.opendocument.spreadsheet]',
// 'max_size[emplist,16384]',
// ],
// ]);
// if ($validated)
// {
// $avatar = $this->request->getFile('emplist');
// if (!$avatar) {
// $this->myLogger->logme("error", 'File not found');
// return $this->respond(['dataStatus' => false, 'code' => 400, 'message' => 'File not found'], 400);
// }
// $is_moved = $avatar->move(WRITEPATH . 'uploads/excel/');
// if ($is_moved) {
// $filename = $avatar->getName();
// $fileSize = $avatar->getSize(); // File size in bytes
// $fileSize = $fileSize / (1024 * 1024); // Convert to MB
// // Handle successful upload, e.g., log success or further processing
// $this->myLogger->logme("error", 'File move successful');
// } else {
// $this->myLogger->logme("error", 'File move failed');
// return $this->respond(['dataStatus' => false, 'code' => 500, 'message' => 'File move failed'], 500);
// }
// } else {
// $this->myLogger->logme("error", 'Upload failed Invalid file');
// return $this->respond(['dataStatus' => false, 'code' => 404, 'message' => 'Invalid file'], 404);
// }
// //process post variable entry in file table
// $loggedInUserID = get_session_userid();
// // dd($loggedInUserID);
// // $loggedInUserID = 8;
// $client_id = $this->request->getPost('client_id');
// $policy_id = $this->request->getPost('policy_id');
// $branch_id = $this->request->getPost('branch_id');
// $enrollment_open_date = $this->request->getPost('enrollment_open_date');
// $enrollment_close_date = $this->request->getPost('enrollment_close_date');
// $action = $this->request->getPost('upload-action-type');
// $status = 'inprogress';
// $enrollment_open_date = change_date_format($enrollment_open_date, 'd/m/Y', 'Y-m-d');
// $enrollment_close_date = change_date_format($enrollment_close_date, 'd/m/Y', 'Y-m-d');
// $file_id = $this->fileModel->insert(['file_name' => $filename, 'client_id' => $client_id, 'policy_id' => $policy_id, 'created_by' => $loggedInUserID, 'status' => $status, 'action' => $action, 'client_branch_id' => $branch_id,'uploaded_by' => 1, 'enrollment_open_date' => $enrollment_open_date, 'enrollment_close_date' => $enrollment_close_date]); //here field policy_id have client_policy_id and not policy id from policy master
// $this->myLogger->logme("error", '{file_id} uploaded success', ['file_id' => $file_id]);
// //start validation process
// if($fileSize < 1) // if file size less than 1
// {
// $empServiceController = new EmployeeServiceController();
// $result = $empServiceController->excelFileFormatValidation(['file_id' => $file_id]);
// $this->myLogger->logme("error", '{file_id} is less than 1MB, validating on the fly', ['file_id' => $file_id]);
// //endof validation process
// if (isset($result['error_summary']) && count($result['error_summary'])) {
// return $this->respond(['dataStatus' => false, 'code' => 404, 'message' => 'file rejected with errors'], 200);
// }
// }
// else //if file size greater than 1 add the file as job
// {
// $job_details = new Jobs();
// $r = Jobs::addJob(['job_name' => 'excelFileFormatValidation','payload' => ['file_id' => $file_id]]);
// $this->myLogger->logme("error", '{file_id} is greather than 1MB, validating with job queue', ['file_id' => $file_id]);
// }
// return $this->respond(['dataStatus' => true, 'code' => 200, 'data' => 'file upload success'], 200);
// }
if (!empty($post_data) || $this->request->is('post') == 'post') {
//validate uploaded file
$filename = '';
$fileSize = '';
$validated = $this->validate([
'emplist' => [
'uploaded[emplist]',
'mime_in[emplist,application/vnd.ms-excel,application/vnd,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.oasis.opendocument.spreadsheet]',
'max_size[emplist,16384]',
],
]);
if ($validated)
{
$avatar = $this->request->getFile('emplist');
if (!$avatar) {
$this->myLogger->logme("error", 'File not found');
if (empty($post_data)) {
$validated = $this->validate([
'emplist' => [
'uploaded[emplist]',
'mime_in[emplist,application/vnd.ms-excel,application/vnd,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.oasis.opendocument.spreadsheet]',
'max_size[emplist,16384]',
],
]);
} else {
$validated = validateExcelFile($post_data['emplist']);
}
if ($validated) {
$avatar = isset($post_data['emplist']) ? $post_data['emplist'] : $this->request->getFile('emplist');
if (!$avatar) {
$this->myLogger->logme("error", 'File not found');
if (!empty($post_data)) {
return ['status' => false, 'message' => 'File not found'];
} else {
return $this->respond(['dataStatus' => false, 'code' => 400, 'message' => 'File not found'], 400);
}
}
$is_moved = $avatar->move(WRITEPATH . 'uploads/excel/');
if ($is_moved) {
$filename = $avatar->getName();
$fileSize = $avatar->getSize(); // File size in bytes
$fileSize = $fileSize / (1024 * 1024); // Convert to MB
// Handle successful upload, e.g., log success or further processing
$this->myLogger->logme("error", 'File move successful');
$is_moved = $avatar->move(WRITEPATH . 'uploads/excel/');
if ($is_moved) {
$filename = $avatar->getName();
$fileSize = $avatar->getSize(); // File size in bytes
$fileSize = $fileSize / (1024 * 1024); // Convert to MB
// Handle successful upload, e.g., log success or further processing
$this->myLogger->logme("error", 'File move successful');
} else {
$this->myLogger->logme("error", 'File move failed');
if (!empty($post_data)) {
return ['status' => false, 'message' => 'File move failed'];
} else {
$this->myLogger->logme("error", 'File move failed');
return $this->respond(['dataStatus' => false, 'code' => 500, 'message' => 'File move failed'], 500);
}
}
} else {
$this->myLogger->logme("error", 'Upload failed Invalid file');
return $this->respond(['dataStatus' => false, 'code' => 404, 'message' => 'Invalid file'], 404);
if (!empty($post_data)) {
return ['status' => false, 'message' => 'Invalid file'];
} else {
return $this->respond(['dataStatus' => false, 'code' => 404, 'message' => 'Invalid file'], 404);
}
}
//process post variable entry in file table
$loggedInUserID = get_session_userid();
// dd($loggedInUserID);
// $loggedInUserID = 8;
$loggedInUserID = $post_data['created_by'] ?? get_session_userid();
$client_id = $this->request->getPost('client_id');
$policy_id = $this->request->getPost('policy_id');
$branch_id = $this->request->getPost('branch_id');
$action = $this->request->getPost('upload-action-type');
$status = 'inprogress';
$client_id = isset($post_data['client_id']) ? $post_data['client_id'] : $this->request->getPost('client_id');
$policy_id = isset($post_data['policy_id']) ? $post_data['policy_id'] : $this->request->getPost('policy_id');
$branch_id = isset($post_data['client_branch_id']) ? $post_data['client_branch_id'] : $this->request->getPost('branch_id');
$action = isset($post_data['file_action']) ? $post_data['file_action'] : $this->request->getPost('upload-action-type');
$enrollment_open_date = isset($post_data['enrollment_open_date']) ? $post_data['enrollment_open_date'] : $this->request->getPost('enrollment_open_date') ?? null;
$enrollment_close_date = isset($post_data['enrollment_close_date']) ? $post_data['enrollment_close_date'] : $this->request->getPost('enrollment_close_date') ?? null;
$status = 'inprogress';
$hr_id = $post_data['created_by'] ?? null;
$file_id = $this->fileModel->insert(['file_name' => $filename, 'client_id' => $client_id, 'policy_id' => $policy_id, 'created_by' => $loggedInUserID, 'status' => $status, 'action' => $action, 'client_branch_id' => $branch_id,'uploaded_by' => 1]); //here field policy_id have client_policy_id and not policy id from policy master
$enrollment_open_date = change_date_format($enrollment_open_date, 'd/m/Y', 'Y-m-d');
$enrollment_close_date = change_date_format($enrollment_close_date, 'd/m/Y', 'Y-m-d');
$file_id = $this->fileModel->insert(['file_name' => $filename, 'client_id' => $client_id, 'policy_id' => $policy_id, 'created_by' => $loggedInUserID, 'status' => $status, 'action' => $action, 'client_branch_id' => $branch_id, 'uploaded_by' => 1, 'enrollment_open_date' => $enrollment_open_date, 'enrollment_close_date' => $enrollment_close_date, 'hr_id' => $hr_id]); //here field policy_id have client_policy_id and not policy id from policy master
$this->myLogger->logme("error", '{file_id} uploaded success', ['file_id' => $file_id]);
//start validation process
if($fileSize < 1) // if file size less than 1
if ($fileSize < 1) // if file size less than 1
{
$empServiceController = new EmployeeServiceController();
$result = $empServiceController->excelFileFormatValidation(['file_id' => $file_id]);
$this->myLogger->logme("error", '{file_id} is less than 1MB, validating on the fly', ['file_id' => $file_id]);
//endof validation process
if (isset($result['error_summary']) && count($result['error_summary'])) {
return $this->respond(['dataStatus' => false, 'code' => 404, 'message' => 'file rejected with errors'], 200);
if(!empty($post_data)){
return ['status' => true, 'message' => 'file rejected with errors', 'file_id' => $file_id];
}else{
return $this->respond(['dataStatus' => false, 'code' => 404, 'message' => 'file rejected with errors'], 200);
}
}
}
else //if file size greater than 1 add the file as job
} else //if file size greater than 1 add the file as job
{
$job_details = new Jobs();
$r = Jobs::addJob(['job_name' => 'excelFileFormatValidation','payload' => ['file_id' => $file_id]]);
$r = Jobs::addJob(['job_name' => 'excelFileFormatValidation', 'payload' => ['file_id' => $file_id]]);
$this->myLogger->logme("error", '{file_id} is greather than 1MB, validating with job queue', ['file_id' => $file_id]);
}
return $this->respond(['dataStatus' => true, 'code' => 200, 'data' => 'file upload success'], 200);
if (!empty($post_data)) {
return ['status' => true, 'message' => 'File upload successs, Data validation is in-progress', 'file_id' => $file_id];
} else {
return $this->respond(['dataStatus' => true, 'code' => 200, 'data' => 'file upload success'], 200);
}
}
$data['page_name'] = 'View Inception';
@ -328,9 +435,9 @@ class EmployeeController extends AdminController
$data['fileList'] = $this->fileModel
->select([
'files.id','files.file_name','files.created_by','files.created_at','files.is_active','files.status','files.client_id','files.policy_id','files.client_branch_id','files.action','files.uploaded_by',
'files.id','files.file_name','files.created_by','files.created_at','files.is_active','files.status','files.client_id','files.policy_id','files.client_branch_id','files.action','files.uploaded_by', 'enrollment_open_date', 'enrollment_close_date',
'up.emp_code',
'up.first_name',
// 'up.first_name',
'c.short_name',
'cb.branch_name',
'cp.id as client_policy_id',
@ -344,8 +451,23 @@ class EmployeeController extends AdminController
WHERE e.file_id = files.id AND ep.client_policy_id = files.policy_id) as total',
'policy_type.policy_type' ,
'cp.policy_no' ,
"CASE
WHEN files.hr_id IS NOT NULL THEN
CONCAT(
(
SELECT lc.name
FROM level_contacts lc
WHERE lc.id = files.hr_id
LIMIT 1
),
' (HR)'
)
ELSE up.first_name
END AS first_name
",
'files.hr_id'
])
->join('user_profiles up', 'files.created_by = up.id')
->join('user_profiles up', 'files.created_by = up.id', 'left')
->join('client_policy cp', 'files.policy_id = cp.id', 'left')
->join('client_branch cb', 'files.client_branch_id = cb.id', 'left')
->join('policy_type', 'policy_type.id = cp.policy_type_id')
@ -378,14 +500,22 @@ class EmployeeController extends AdminController
}
}
public function getExcelFileErrors()
public function getExcelFileErrors($file_id, $retun_type)
{
$file_id = $this->request->uri->getSegment(3);
// $file_id = $this->request->uri->getSegment(3);
$empServiceController = new EmployeeServiceController();
// Render views and capture output
$result = $empServiceController->getExcelErrorData($file_id);
if($retun_type == 'api'){
if(!empty($result)){
return $this->respond(['status' => true, 'code' => 200, 'message' => 'Error data feteched successfully', 'data' => $result], 200);
}else{
return $this->respond(['status' => false, 'code' => 404, 'message' => 'Failed to fetch error data', 'data' => []], 200);
}
}
if ($result != 0) {
$result['file_id'] = $file_id;
@ -2828,7 +2958,7 @@ class EmployeeController extends AdminController
if (!is_dir($exportDir)) {
mkdir($exportDir, 0777, true);
} else {
chmod($exportDir, 0777);
// chmod($exportDir, 0777);
}
$filename = 'inception_export_' . date('Ymd_His') . '.xlsx';

View File

@ -236,7 +236,7 @@ class EmployeeRestController extends AdminController
$data = $this->request->getJSON();
//enrolment check
$openForEnrollment = $this->findThePolicyIsOpenForEnrollment($data[0]->client_policy_id);
$openForEnrollment = $this->findThePolicyIsOpenForEnrollment($data[0]->client_policy_id, $data[0]->emp_code);
if($openForEnrollment == false){
return $this->respond(['status' => 'failed','code' => 404,'data' => [],'message' => 'Enrollment closed.'], 200);
}
@ -369,7 +369,20 @@ class EmployeeRestController extends AdminController
$basic_cover_si = $policy_terms->sum_insured;
}
$checkDataExist = $this->employeePolicyModel->where('employee_id',$employee_id)->where('client_policy_id',$client_policy_id)->first();
$other_employee_policy_data = $this->employeePolicyModel
->select('employee_polices.*')
->join('employees', 'employee_polices.employee_id = employees.id', 'left')
->where('employees.emp_code', $emp_code)
->where('employee_polices.client_policy_id', $client_policy_id)
->where('employee_polices.is_active', 1)
->where('employees.is_active', 1)
->whereIn('employee_polices.status', ['draft', 'enrolled'])
->whereIn('employees.emp_status', ['draft', 'enrolled'])
->where('employee_polices.enrollment_open_date is not null')
->where('employee_polices.enrollment_close_date is not null')
->first();
$checkDataExist = $this->employeePolicyModel->where('employee_id',$employee_id)->where('client_policy_id',$client_policy_id)->where('is_active', 1)->first();
if($checkDataExist){
@ -389,6 +402,11 @@ class EmployeeRestController extends AdminController
$data['status']= 'draft';
$data['date_coverage'] = $this->getEmployeeCoverageDate($emp_code, $client_policy_id);
if(!empty($other_employee_policy_data)){
$data['enrollment_open_date']= $other_employee_policy_data['enrollment_open_date'] ?? null;
$data['enrollment_close_date']= $other_employee_policy_data['enrollment_close_date'] ?? null;
}
// dd($data);
$this->employeePolicyModel->insert($data);
@ -470,7 +488,6 @@ class EmployeeRestController extends AdminController
}else{ return null; }
}
public function RelationshipMap($value){
if ($value === 'Mother' || $value === 'Father') {
@ -526,16 +543,30 @@ class EmployeeRestController extends AdminController
try {
if($this->request->getGet('id'))
{
$this->employeeModel->where('id', $this->request->getGet('id') )
->where('is_active', 1 )
->set(array('is_active'=> 0 ))
->update();
{
$is_from_copy = $this->request->getGet('is_from_copy') ?? null;
if($is_from_copy == 'false' || $is_from_copy == false || $is_from_copy == 'null' || $is_from_copy == null){
$this->employeeModel->where('id', $this->request->getGet('id') )
->where('is_active', 1 )
->set(array('is_active'=> 0 ))
->update();
}
$query = $this->employeePolicyModel
->where('employee_id', $this->request->getGet('id'))
->where('is_active', 1);
// 👉 Add condition only if client_policy_id exists
$clientPolicyId = $this->request->getGet('client_policy_id') ?? null;
if (!empty($clientPolicyId)) {
$query->where('client_policy_id', $clientPolicyId);
}
$query->set(['is_active' => 0])->update();
$this->employeePolicyModel->where('employee_id',$this->request->getGet('id') )
->where('is_active', 1 )
->set(array('is_active'=> 0 ))
->update();
return $this->respond(['status' => 'success','code' => 200,'data' =>[] ], 200);
}else{
@ -559,7 +590,7 @@ class EmployeeRestController extends AdminController
// print_r($requestData);
// dd($requestData);
$openForEnrollment = $this->findThePolicyIsOpenForEnrollment($requestData[0]->client_policy_id);
$openForEnrollment = $this->findThePolicyIsOpenForEnrollment($requestData[0]->client_policy_id, $requestData[0]->emp_code);
if($openForEnrollment == false){ return $this->respond(['status' => 'failed','code' => 404,'data' => 'Enrollment closed'], 404); }
foreach ($requestData as $key => $value)
@ -755,8 +786,48 @@ class EmployeeRestController extends AdminController
}
// Upload the Employee Detail in DB by Sheet Data
public function employeeUpload()
{
try{
$post_data = [
'client_id' => $this->request->getPost('client_id') ?? null,
'client_branch_id' => $this->request->getPost('client_branch_id'),
'policy_id' => $this->request->getPost('policy_id'),
'enrollment_open_date' => $this->request->getPost('enrollment_open_date'),
'enrollment_close_date' => $this->request->getPost('enrollment_close_date'),
'file_action' => "enrollment",
'created_by' => $this->request->getPost('created_by'),
'emplist' => $this->request->getFile('file')
];
// print_r($post_data); die;
if(empty($post_data['client_id'])){
return $this->respondCreated(['status' => false, 'message' => 'Client is required', 'data' => []]);
}
$employeeController = new EmployeeController();
$responce = $employeeController->employeesUplodWithEvents($post_data);
// print_r($responce); die;
if($responce['status']){
$file_data = $this->getDataFromFilesTable(['file_id' => $responce['file_id']]);
$responce['data'] = $file_data;
return $this->respond($responce, 200);
}else{
$responce['data'] = [];
return $this->respond($responce, 200);
}
}catch(\Exception $e){
return $this->respondCreated(['status' => false, 'message' => $e->getMessage(), 'data' => []]);
}
}
// Upload the Employee Detail in DB by Sheet Data (DO NOT REMOVE THIS)
public function employeeUploadOld()
{
try {
$file = $this->request->getFile('file');
@ -1114,9 +1185,69 @@ class EmployeeRestController extends AdminController
return $this->respond(['status' => 'failed','code' => 500,'data' => $th->getMessage(), 'error_data' => $errorData], 500);
}
}
public function getDataFromFilesTable($search_data)
{
$file_download_base = base_url('util/download-file-list/');
$builder = $this->fileModel
->select("
files.id,
files.client_id,
files.client_branch_id,
files.policy_id,
cp.policy_no,
files.file_name,
files.action,
files.created_at,
files.created_by,
files.updated_at,
files.updated_by,
c.short_name,
cb.branch_name,
lc.name as first_name,
CONCAT(UCASE(LEFT(files.status, 1)), LCASE(SUBSTRING(files.status, 2))) as status,
CASE
WHEN status = 'failed' THEN 1
ELSE 0
END AS file_error_status,
CONCAT('{$file_download_base}', files.id, '/api') AS file_download_link
", false)
->join('clients c', 'files.client_id = c.id AND c.is_active = 1', 'left')
->join('client_branch cb', 'files.client_branch_id = cb.id AND cb.is_active = 1', 'left')
->join('client_policy cp', 'files.policy_id = cp.id AND cp.is_active = 1', 'left')
->join('level_contacts lc', 'files.hr_id = lc.id AND lc.contact_type = "client" AND lc.is_active = 1', 'left');
if (isset($search_data['policy_id']) && !empty($search_data['policy_id'])) {
$builder->where("files.policy_id", $search_data['policy_id']);
}
if (isset($search_data['created_by']) && !empty($search_data['created_by'])) {
$builder->where("files.hr_id", $search_data['created_by']);
}
if (isset($search_data['policy_no']) && !empty($search_data['policy_no'])) {
$builder->where("cp.policy_no", $search_data['policy_no']);
}
if (isset($search_data['client_id']) && !empty($search_data['client_id'])) {
$builder->where("files.client_id", $search_data['client_id']);
}
if (isset($search_data['file_id']) && !empty($search_data['file_id'])) {
$builder->where("files.id", $search_data['file_id']);
}
// Execute query
$data = $builder->get()->getResultArray();
if (!empty($data)) {
return $data;
}
return [];
}
@ -1160,13 +1291,25 @@ class EmployeeRestController extends AdminController
if ($empPolicy) {
$latest_gmc_policy_id = getLatestGMCPolicy((array)$empPolicy);
$result = [];
foreach ($empPolicy as $array) {
// Reset employee array
$empData = $employeeData;
// Reset employee array
// $empData = $employeeData;
$empData = $this->employeeModel
->select('employees.*')
->join('employee_polices', 'employee_polices.employee_id = employees.id')
->where('employees.emp_code',$emp_code)
->where('employees.client_id',$client_id)
->where('employees.client_branch_id',$client_branch_id)
->where('employee_polices.client_policy_id',$array->ClientPolicyId)
->where('employees.is_active', 1 )
->where('employee_polices.is_active', 1 )
->where('employees.is_addon_value',0)
->findAll();
// Removes specific keys from the decoded array and assigns the result to $refusingData
$decodedArray = json_decode($array->Policy_Terms);
$refusingData = (object) array_diff_key((array) $decodedArray, array_flip($keysToRemove));
@ -1248,6 +1391,11 @@ class EmployeeRestController extends AdminController
$array->to_be_added_relationship = [];
$array->existing_relationship = [];
if(!empty($latest_gmc_policy_id) && $latest_gmc_policy_id == $array->ClientPolicyId){
$array->copy_dependence_data_enable = true;
}else{
$array->copy_dependence_data_enable = false;
}
// Map family floaters that already exist in the employee table
$familyFloates = $array->Policy_Terms->family_floaters;
@ -1415,25 +1563,55 @@ class EmployeeRestController extends AdminController
$array->mapped_family_floaters = $data;
$array->type = "GMC";
$array->family_floaters_of_dependent_and_si_value = $dependent_and_si_value > 0 ? $dependent_and_si_value : 0;
$array->family_floaters_of_dependent_and_si_value = $dependent_and_si_value > 0 ? $dependent_and_si_value : 0.0;
if($array->is_premium_summery == 1){
$array->family_floaters_of_dependent_and_si_premium_value = $dependent_and_si_premium_value > 0 ? round($dependent_and_si_premium_value) : 0;
$array->family_floaters_of_dependent_and_gst_value = $dependent_and_si_gst_value > 0 ? round($dependent_and_si_gst_value) : 0;
$array->family_floaters_of_dependent_and_si_premium_value = $dependent_and_si_premium_value > 0 ? round($dependent_and_si_premium_value) : 0.0;
$array->family_floaters_of_dependent_and_gst_value = $dependent_and_si_gst_value > 0 ? round($dependent_and_si_gst_value) : 0.0;
}else{
$array->family_floaters_of_dependent_and_si_premium_value = 0;
$array->family_floaters_of_dependent_and_gst_value = 0;
$array->family_floaters_of_dependent_and_si_premium_value = 0.0;
$array->family_floaters_of_dependent_and_gst_value = 0.0;
}
$checkGmcParentsPolicyExist = $this->clientPolicyModel->select('client_policy.id as ClientPolicyId , client_policy.client_id as ClientId, client_policy.policy_type_id as policy_type_id, policy_type.long_name as Policy_Name , client_policy.is_addon as is_addon , client_policy.open_for_enrollment as OpenForEnrollment , client_policy.inception_type as inception_type , client_policy.policy_terms as Policy_Terms , client_policy.is_premium_summery as is_premium_summery, client_policy.enrolment_visibility')
->join('policy_type', 'client_policy.policy_type_id = policy_type.id', 'left')
->where('client_policy.policy_type_id', 3 )
->where('client_policy.is_addon', 1 )
->where('client_policy.client_id', $this->request->getGet('client_id') )
->where('client_policy.client_branch_id', $this->request->getGet('client_branch_id') )
->where('client_policy.is_active', 1 )
->where('client_policy.enrolment_visibility', 1 )
->get()
->getResult();
$checkGmcParentsPolicyExist = $this->clientPolicyModel->select("
client_policy.id as ClientPolicyId,
client_policy.client_id as ClientId,
client_policy.policy_type_id as policy_type_id,
policy_type.long_name as Policy_Name ,
client_policy.is_addon as is_addon ,
(
SELECT COALESCE(
MAX(
CASE
WHEN ep.enrollment_open_date <= CURDATE()
AND ep.enrollment_close_date >= CURDATE()
THEN 1
ELSE 0
END
), 0
)
FROM employee_polices ep
INNER JOIN employees e ON e.id = ep.employee_id
WHERE e.is_active = 1
AND ep.is_active = 1
AND ep.enrollment_open_date IS NOT NULL
AND ep.enrollment_close_date IS NOT NULL
AND e.emp_code = '{$emp_code}'
AND ep.client_policy_id = client_policy.id
) AS OpenForEnrollment,
client_policy.inception_type as inception_type ,
client_policy.policy_terms as Policy_Terms ,
client_policy.is_premium_summery as is_premium_summery,
client_policy.enrolment_visibility
")
->join('policy_type', 'client_policy.policy_type_id = policy_type.id', 'left')
->where('client_policy.policy_type_id', 3 )
->where('client_policy.is_addon', 1 )
->where('client_policy.client_id', $this->request->getGet('client_id') )
->where('client_policy.client_branch_id', $this->request->getGet('client_branch_id') )
->where('client_policy.is_active', 1 )
->where('client_policy.enrolment_visibility', 1 )
->get()
->getResult();
if($checkGmcParentsPolicyExist)
{
$GmcParrentsData = $this->getGmcParrentsPolicy($checkGmcParentsPolicyExist,$emp_code,$client_id,$client_branch_id);
@ -1442,7 +1620,7 @@ class EmployeeRestController extends AdminController
$result[] = $GmcParrentsData;
}
if($this->request->getGet('policy') == 'GMC'){
if($this->request->getGet('policy') == 'GMC' && !$checkGmcParentsPolicyExist){
// return $this->respond(['status' => 'success','code' => 200,'data' => [$array]], 200);
$result[] = $array;
}
@ -1453,7 +1631,8 @@ class EmployeeRestController extends AdminController
}
if(!empty($result) && $this->request->getGet('policy') == 'GMC'){
return $this->respond(['status' => 'success','code' => 200,'data' => $result], 200);
// return $this->respond(['status' => 'success','code' => 200,'data' => $result], 200);
echo json_encode(['status' => 'success','code' => 200,'data' => $result], JSON_PRETTY_PRINT | JSON_PRESERVE_ZERO_FRACTION);
}else{
return $this->respond(['status' => 'success','code' => 200,'data' => []], 200);
}
@ -1462,6 +1641,7 @@ class EmployeeRestController extends AdminController
}else{
return $this->respond(['status' => 'failed','code' => 404,'data' => []], 200);
}
} catch (\Exception $e) {
$errorData = [
@ -1483,11 +1663,11 @@ class EmployeeRestController extends AdminController
public function getGmcParrentsPolicy($GmcParrentsPolicy,$emp_code,$client_id,$client_branch_id)
{
$employeeData = $this->employeeModel->where('emp_code',$emp_code)
->where('client_id',$client_id)
->where('client_branch_id',$client_branch_id)
->where('is_active', 1 )
->where('is_addon_value',0)->findAll();
// $employeeData = $this->employeeModel->where('emp_code',$emp_code)
// ->where('client_id',$client_id)
// ->where('client_branch_id',$client_branch_id)
// ->where('is_active', 1 )
// ->where('is_addon_value',0)->findAll();
// return $employeeData;
foreach ($GmcParrentsPolicy as $key => $array) {
@ -1496,8 +1676,18 @@ class EmployeeRestController extends AdminController
// Reset employee array
$empData = $employeeData;
// $empData = $employeeData;
$empData = $this->employeeModel
->select('employees.*')
->join('employee_polices', 'employee_polices.employee_id = employees.id')
->where('employees.emp_code',$emp_code)
->where('employees.client_id',$client_id)
->where('employees.client_branch_id',$client_branch_id)
->where('employee_polices.client_policy_id',$array->ClientPolicyId)
->where('employees.is_active', 1 )
->where('employee_polices.is_active', 1 )
->where('employees.is_addon_value',0)
->findAll();
$array->Policy_Terms = json_decode($array->Policy_Terms);
@ -1511,6 +1701,7 @@ class EmployeeRestController extends AdminController
->join('employee_polices', 'employee_polices.employee_id = employees.id')
->where('employees.emp_code',$emp_code)
->where('employees.is_active',1)
->where('employee_polices.is_active',1)
->where('employee_polices.client_policy_id',$array->ClientPolicyId)
->get()
->getResult();
@ -1627,29 +1818,29 @@ class EmployeeRestController extends AdminController
// Add family floter buttons placement data for FE validation
if(count($floters)){
foreach ($floters as $familyFloatesValue) {
foreach ($floters as $familyFloatesValue) {
$temp2['is_value_exist'] = false;
$temp2['data']['family_floater_key'] = $familyFloatesValue;
$temp2['data']['relationship'] = ucfirst(str_replace('_', ' ', preg_replace('/\d/', '', $familyFloatesValue)));
$temp2['data']['client_policy_id'] = $array->ClientPolicyId;
$temp2['data']['button_name'] = 'Add '.ucfirst(str_replace('_', ' ', preg_replace('/\d/', '', $familyFloatesValue)));
$temp2['data']['form_type'] = preg_replace('/\d/', '', $familyFloatesValue);
$temp2['data']['age_validation'] = $this->getAgeRange($array->Policy_Terms,$familyFloatesValue);
array_push($data,$temp2);
$temp2['is_value_exist'] = false;
$temp2['data']['family_floater_key'] = $familyFloatesValue;
$temp2['data']['relationship'] = ucfirst(str_replace('_', ' ', preg_replace('/\d/', '', $familyFloatesValue)));
$temp2['data']['client_policy_id'] = $array->ClientPolicyId;
$temp2['data']['button_name'] = 'Add '.ucfirst(str_replace('_', ' ', preg_replace('/\d/', '', $familyFloatesValue)));
$temp2['data']['form_type'] = preg_replace('/\d/', '', $familyFloatesValue);
$temp2['data']['age_validation'] = $this->getAgeRange($array->Policy_Terms,$familyFloatesValue);
array_push($data,$temp2);
array_push($array->to_be_added_relationship,['relationship'=>$temp2['data']['relationship'],'age_validation'=>$temp2['data']['age_validation']]);
$array->to_be_added_relationship = array_values(
array_map('unserialize',
array_unique(
array_map('serialize', $array->to_be_added_relationship)
array_push($array->to_be_added_relationship,['relationship'=>$temp2['data']['relationship'],'age_validation'=>$temp2['data']['age_validation']]);
$array->to_be_added_relationship = array_values(
array_map('unserialize',
array_unique(
array_map('serialize', $array->to_be_added_relationship)
)
)
)
);
);
}
}
}
$array->relationship = [];
foreach ($array->to_be_added_relationship as $key => $value) {
@ -1685,13 +1876,13 @@ class EmployeeRestController extends AdminController
$array->mapped_family_floaters = $data;
$array->type = "GMC - Parents";
$array->family_floaters_of_dependent_and_si_value = $dependent_and_si_value > 0 ? $dependent_and_si_value : 0;
$array->family_floaters_of_dependent_and_si_value = $dependent_and_si_value > 0 ? $dependent_and_si_value : 0.0;
if($array->is_premium_summery == 1){
$array->family_floaters_of_dependent_and_si_premium_value = $dependent_and_si_premium_value > 0 ? round($dependent_and_si_premium_value) : 0;
$array->family_floaters_of_dependent_and_gst_value = $dependent_and_si_gst_value > 0 ? round($dependent_and_si_gst_value) : 0;
$array->family_floaters_of_dependent_and_si_premium_value = $dependent_and_si_premium_value > 0 ? round($dependent_and_si_premium_value) : 0.0;
$array->family_floaters_of_dependent_and_gst_value = $dependent_and_si_gst_value > 0 ? round($dependent_and_si_gst_value) : 0.0;
}else{
$array->family_floaters_of_dependent_and_si_premium_value = 0;
$array->family_floaters_of_dependent_and_gst_value = 0;
$array->family_floaters_of_dependent_and_si_premium_value = 0.0;
$array->family_floaters_of_dependent_and_gst_value = 0.0;
}
return $array;
@ -1703,7 +1894,36 @@ class EmployeeRestController extends AdminController
public function getAdditionalGPAPolicy($empData,$policy_type,$emp_code,$client_id,$client_branch_id,$login_by_hr)
{
$checkPolicyExist = $this->clientPolicyModel->select('client_policy.id as ClientPolicyId , client_policy.client_id as ClientId, client_policy.policy_type_id as policy_type_id, client_policy.is_addon as is_addon , client_policy.open_for_enrollment as OpenForEnrollment , client_policy.inception_type as inception_type , client_policy.policy_terms as Policy_Terms , client_policy.enrolment_visibility,client_policy.is_premium_summery')
$checkPolicyExist = $this->clientPolicyModel->select("
client_policy.id as ClientPolicyId ,
client_policy.client_id as ClientId,
client_policy.policy_type_id as policy_type_id,
client_policy.is_addon as is_addon ,
(
SELECT COALESCE(
MAX(
CASE
WHEN ep.enrollment_open_date <= CURDATE()
AND ep.enrollment_close_date >= CURDATE()
THEN 1
ELSE 0
END
), 0
)
FROM employee_polices ep
INNER JOIN employees e ON e.id = ep.employee_id
WHERE e.is_active = 1
AND ep.is_active = 1
AND ep.enrollment_open_date IS NOT NULL
AND ep.enrollment_close_date IS NOT NULL
AND e.emp_code = '{$emp_code}'
AND ep.client_policy_id = client_policy.id
) AS OpenForEnrollment,
client_policy.inception_type as inception_type ,
client_policy.policy_terms as Policy_Terms ,
client_policy.enrolment_visibility,
client_policy.is_premium_summery
")
->where('client_policy.policy_type_id', $policy_type )
->where('client_policy.is_addon', 1 )
->where('client_policy.client_id', $client_id )
@ -2019,6 +2239,7 @@ class EmployeeRestController extends AdminController
{
try {
$emp_code = $this->request->getGet('emp_code');
$addOnEmployeeData = $this->employeeModel->where('is_active', 1 )
->where('emp_code',$this->request->getGet('emp_code'))
->where('client_id',$this->request->getGet('client_id'))
@ -2027,7 +2248,30 @@ class EmployeeRestController extends AdminController
$clientPolicy = $this->clientPolicyModel->where('client_id',$this->request->getGet('client_id'))
$clientPolicy = $this->clientPolicyModel->select("
client_policy.*,
(
SELECT COALESCE(
MAX(
CASE
WHEN ep.enrollment_open_date <= CURDATE()
AND ep.enrollment_close_date >= CURDATE()
THEN 1
ELSE 0
END
), 0
)
FROM employee_polices ep
INNER JOIN employees e ON e.id = ep.employee_id
WHERE e.is_active = 1
AND ep.is_active = 1
AND ep.enrollment_open_date IS NOT NULL
AND ep.enrollment_close_date IS NOT NULL
AND e.emp_code = '{$emp_code}'
AND ep.client_policy_id = client_policy.id
) AS open_for_enrollment
")
->where('client_id',$this->request->getGet('client_id'))
->where('client_branch_id',$this->request->getGet('client_branch_id'))
->where('policy_status', 1)
->where('is_active', 1)
@ -2036,6 +2280,7 @@ class EmployeeRestController extends AdminController
if(count($clientPolicy))
{
$self = $this->employeeModel->where('employees.is_active', 1)
->where('employees.emp_code', $this->request->getGet('emp_code'))
->where('employees.client_id', $this->request->getGet('client_id'))
@ -2280,13 +2525,13 @@ class EmployeeRestController extends AdminController
}
$responce['family_floaters_of_dependent_and_si_array'] = $data;
$responce['family_floaters_of_dependent_and_si_value'] = $dependent_and_si_value > 0 ? $dependent_and_si_value : 0;
$responce['family_floaters_of_dependent_and_si_value'] = $dependent_and_si_value > 0 ? $dependent_and_si_value : 0.0;
if($array['is_premium_summery']){
$responce['family_floaters_of_dependent_and_si_premium_value'] = $dependent_and_si_premium_value > 0 ? round($dependent_and_si_premium_value) : 0;
$responce['family_floaters_of_dependent_and_gst_value'] = $dependent_and_si_gst_value > 0 ? round($dependent_and_si_gst_value) : 0;
$responce['family_floaters_of_dependent_and_si_premium_value'] = $dependent_and_si_premium_value > 0 ? round($dependent_and_si_premium_value) : 0.0;
$responce['family_floaters_of_dependent_and_gst_value'] = $dependent_and_si_gst_value > 0 ? round($dependent_and_si_gst_value) : 0.0;
}else{
$responce['family_floaters_of_dependent_and_si_premium_value'] = 0;
$responce['family_floaters_of_dependent_and_gst_value'] = 0;
$responce['family_floaters_of_dependent_and_si_premium_value'] = 0.0;
$responce['family_floaters_of_dependent_and_gst_value'] = 0.0;
}
@ -2295,7 +2540,8 @@ class EmployeeRestController extends AdminController
if($this->request->getGet('policy') == 'GMC-DEPENDENT-ADDON'){
return $this->respond(['status' => 'success','code' => 200,'data' => ['gmc_dependent_addon'=>$responce]], 200);
// return $this->respond(['status' => 'success','code' => 200,'data' => ['gmc_dependent_addon'=>$responce]], 200);
echo json_encode(['status' => 'success','code' => 200,'data' => ['gmc_dependent_addon'=>$responce]], JSON_PRETTY_PRINT | JSON_PRESERVE_ZERO_FRACTION);
}
//array_push($PolicyData, $responce);
@ -2462,7 +2708,8 @@ class EmployeeRestController extends AdminController
$array_list = [];
foreach ($client_policy_id as $key => $value)
{
$policy = $this->clientPolicyModel->where('id',$value)->where('open_for_enrollment',1)->find();
// $policy = $this->clientPolicyModel->where('id',$value)->where('open_for_enrollment',1)->find();
$policy = $this->findThePolicyIsOpenForEnrollment($client_policy_id, $emp_code);
if($policy)
{
$this->myLogger->logme("error", 'client policy id = '.$value.' is open for enrollment');
@ -3589,20 +3836,33 @@ class EmployeeRestController extends AdminController
}
public function findThePolicyIsOpenForEnrollment($plicy_id)
public function findThePolicyIsOpenForEnrollment($policy_id, $emp_code)
{
$policy = $this->clientPolicyModel->where('id',$plicy_id)->where('open_for_enrollment',1)->find();
// $policy = $this->clientPolicyModel->where('id',$plicy_id)->where('open_for_enrollment',1)->find();
$policy = $this->employeePolicyModel
->join('employees', 'employee_polices.employee_id = employees.id')
->where('employees.emp_code',$emp_code)
->where('employee_polices.client_policy_id',$policy_id)
->where('employee_polices.enrollment_open_date <= CURDATE()', null, false)
->where('employee_polices.enrollment_close_date >= CURDATE()', null, false)
->where('employee_polices.enrollment_open_date is not null')
->where('employee_polices.enrollment_close_date is not null')
->where('employees.is_active', 1)
->where('employee_polices.is_active', 1)
->whereIn('employee_polices.status', ['draft', 'enrolled'])
->whereIn('employees.emp_status', ['draft', 'enrolled'])
->first();
if($policy)
return true;
return true;
else
return false;
return false;
}
public function getPreEmployeePolicyCount()
public function getPreEmployeePolicyCountOld()
{
log_message('error', 'STEP 1: getPreEmployeePolicyCount API called');
@ -3650,6 +3910,7 @@ class EmployeeRestController extends AdminController
->join('client_policy cp', 'employee_polices.client_policy_id = cp.id')
->where('employees.is_active', 1)
->whereIn('employees.emp_status', ['draft', 'enrolled'])
->where('employees.family_floater_key', 'self')
->where('employee_polices.is_active', 1)
->whereIn('employee_polices.status', ['draft', 'enrolled'])
->where('cp.enrolment_visibility', 1)
@ -3686,6 +3947,161 @@ class EmployeeRestController extends AdminController
}
}
public function getPreEmployeePolicyCount()
{
log_message('error', 'STEP 1: getPreEmployeePolicyCount API called');
$request = $this->request->getJSON(true);
$mobile_no = $request['mobile_number'] ?? null;
$email_id = $request['email_id'] ?? null;
$client_short_name = $request['client_short_name'] ?? null;
log_message('error', 'STEP 2: Received input - ' . json_encode($request));
/** ---------------------------------------------------------------
* STEP 3: Resolve Client ID (If client_short_name passed)
* --------------------------------------------------------------- */
$clientId = null;
if (!empty($client_short_name)) {
log_message('error', 'STEP 3: Looking up client with short_name: ' . $client_short_name);
$client = $this->clientModel
->select('id')
->where('is_active', 1)
->where('short_name', $client_short_name)
->first();
if (!empty($client)) {
$clientId = $client['id'];
log_message('error', 'STEP 4: Found client ID: ' . $clientId);
} else {
log_message('error', 'STEP 4: No client found for short_name: ' . $client_short_name);
}
} else {
log_message('error', 'STEP 3: client_short_name is empty.');
}
/** ---------------------------------------------------------------
* STEP 4: Validate Request (either mobile or email is required)
* --------------------------------------------------------------- */
if (empty($mobile_no) && empty($email_id)) {
log_message('error', 'STEP 5: Mobile number and Email both empty. Returning 0.');
return $this->respond(['data' => 0, 'empNotEnrolledCount' => 0]);
}
try {
/** ---------------------------------------------------------------
* STEP 6: Base Query Builder (extract common conditions)
* --------------------------------------------------------------- */
$baseQuery = $this->employeeModel
->join('employee_polices', 'employees.id = employee_polices.employee_id')
->join('client_policy cp', 'employee_polices.client_policy_id = cp.id')
->where('employees.is_active', 1)
->where('employee_polices.is_active', 1)
->where('cp.enrolment_visibility', 1)
// ->where('cp.open_for_enrollment', 1)
->where('employee_polices.enrollment_open_date <= CURDATE()', null, false)
->where('employee_polices.enrollment_close_date >= CURDATE()', null, false)
->where('cp.policy_status', 1)
->whereIn('cp.policy_type_id', [1, 2, 3, 6, 7])
->orderBy('employees.created_at', 'desc')
->groupBy('employee_polices.client_policy_id');
// 🔹 Apply Client Filter if Provided
if (!empty($clientId)) {
$baseQuery->where('employees.client_id', $clientId);
log_message('error', 'Applied client ID filter: ' . $clientId);
}
// 🔹 Apply Mobile Filter if Provided
if (!empty($mobile_no)) {
$baseQuery->where('employees.mobile', $mobile_no);
log_message('error', 'Applied mobile_no filter: ' . $mobile_no);
}
// 🔹 Apply Email Filter if Provided
if (!empty($email_id)) {
$baseQuery->where('employees.email_corporate', $email_id);
log_message('error', 'Applied email_id filter: ' . $email_id);
}
/** ---------------------------------------------------------------
* STEP 7: Count Enrolled + Draft (eligible)
* --------------------------------------------------------------- */
$baseQuery->whereIn('employees.emp_status', ['draft', 'enrolled'])
->whereIn('employee_polices.status', ['draft', 'enrolled'])
->where('employees.family_floater_key', 'self');
$count = $baseQuery->get()->getNumRows();
log_message('error', 'Eligible policy count = ' . $count);
/** ---------------------------------------------------------------
* STEP 8: Count Only Draft (Not Enrolled yet)
* --------------------------------------------------------------- */
$notEnrolledQuery = $this->employeeModel
->select("
(
SELECT COUNT(e2.id)
FROM employees AS e2
WHERE e2.is_active = 1
AND e2.emp_status = 'draft'
AND e2.emp_code = employees.emp_code
) AS draft_count
")
->join('employee_polices', 'employees.id = employee_polices.employee_id')
->join('client_policy cp', 'employee_polices.client_policy_id = cp.id')
->where('employees.is_active', 1)
->where('employee_polices.is_active', 1)
->where('cp.enrolment_visibility', 1)
// ->where('cp.open_for_enrollment', 1)
->where('employee_polices.enrollment_open_date <= CURDATE()', null, false)
->where('employee_polices.enrollment_close_date >= CURDATE()', null, false)
->where('cp.policy_status', 1)
->whereIn('cp.policy_type_id', [1, 2, 3, 6, 7])
->orderBy('employees.created_at', 'desc');
// 🔹 Apply Client Filter if Provided
if (!empty($clientId)) {
$notEnrolledQuery->where('employees.client_id', $clientId);
log_message('error', 'Applied client ID filter: ' . $clientId);
}
// 🔹 Apply Mobile Filter if Provided
if (!empty($mobile_no)) {
$notEnrolledQuery->where('employees.mobile', $mobile_no);
log_message('error', 'Applied mobile_no filter: ' . $mobile_no);
}
// 🔹 Apply Email Filter if Provided
if (!empty($email_id)) {
$notEnrolledQuery->where('employees.email_corporate', $email_id);
log_message('error', 'Applied email_id filter: ' . $email_id);
}
$notEnrolledQuery->whereIn('employees.emp_status', ['draft'])
->whereIn('employee_polices.status', ['draft']);
$not_enrolled_count = $notEnrolledQuery->get()->getRowArray()['draft_count'] ?? 0;
log_message('error', 'Not enrolled policy count = ' . $not_enrolled_count);
/** ---------------------------------------------------------------
* STEP 9: Final Response
* --------------------------------------------------------------- */
return $this->respond([
'pre_policy_count' => $count,
'emp_not_enrolled_count' => (int) $not_enrolled_count
]);
} catch (\Throwable $e) {
log_message('error', 'Exception occurred: ' . $e->getMessage());
return $this->respond([
'pre_policy_count' => 0,
'emp_not_enrolled_count' => 0
]);
}
}
//--------------------------------------------------------------------------------------------
@ -3882,7 +4298,7 @@ class EmployeeRestController extends AdminController
$empData = $this->employeeModel
->where('emp_code', $emp_code)
->where('client_id', $client_id)
->where('emp_status', 'enrolled')
// ->where('emp_status', 'enrolled')
->where('is_active', 1)
->findAll();
@ -3890,10 +4306,17 @@ class EmployeeRestController extends AdminController
return $this->respond(['status' => "failed", 'code' => 404, 'message' => "employee data not found", 'data' => []], 200);
}
$selfData = array_column(
array_filter($empData, function($row) {
return isset($row['relationship']) && strtolower($row['relationship']) == 'self';
}),
'id'
);
$selfId = !empty($selfData) ? reset($selfData) : null;
$floters = $this->FloterConvertion($family_floaters);
$data = [];
foreach ($floters as $familyFloatesValue) {
$dependent = preg_replace('/\d/', '', $familyFloatesValue);
@ -3902,6 +4325,8 @@ class EmployeeRestController extends AdminController
foreach ($empData as $key => $value) {
if ($value['family_floater_key'] === $dependent) {
$employee_policy = $this->employeePolicyModel->where('employee_id', $selfId)->where('client_policy_id',$new_client_policy_id)->where('is_active', 1 )->get()->getRow();
$temp['is_value_exist'] = true;
$temp['data']['family_floater_key'] = $familyFloatesValue;
$temp['data']['employee_id'] = $value['id'];
@ -3910,7 +4335,7 @@ class EmployeeRestController extends AdminController
$temp['data']['dob'] = $this->convertDateFormatDMY($value['dob']);
$temp['data']['client_policy_id'] = $new_client_policy_id;
$temp['data']['form_type'] = $dependent;
$temp['data']['basic_cover_si'] = null;
$temp['data']['basic_cover_si'] = isset($employee_policy->basic_cover_si) ? $employee_policy->basic_cover_si : 0;
$temp['data']['age_validation'] = $this->getAgeRange($policy_terms, $familyFloatesValue);

View File

@ -1069,6 +1069,20 @@ class EmployeeServiceController extends AdminController
}
}
// check the employee code if dublicate exist
if(($file['action'] == 'inception' || $file['action'] == 'missed_inception' || $file['action'] == 'addition' || $file['action'] == 'enrollment'))
{
$res = check_emp_code_duplication($family, $file);
// dd($res);
if($res['status'])
{
foreach ($res['row_ids'] as $row_id) {
array_push($result['error_summary'],26);
$result['error_data'][ $row_id ]['emp_id']['error'][] = "Employee Code is already exist in the system";
}
}
}
//check self avaialbe either same policy DB level(i.e.) gMC parents
if($file['action'] == 'dependent_addition' || ($policy_details['policy_type_id'] == 3 && !$is_self_available_in_policy_terms)) // 3 is GMC parents as base policy not as dep addon)
{
@ -1981,221 +1995,251 @@ public function getFileMetaDataByFileId($file_id, $status = 'success'){
public function employeesEnrollmentInsert($params)
{
// dd($this->request);
helper('excel_util_helper');
//get file name
$file_id = $params['file_id'];
$file = $this->fileModel->find($file_id);
// dd($file);
$return = [];
if(!isset($file))
{
//file not found in DB
return array('status' => false, 'msg' => 'file not found in DB');
}
$file_name_with_path = WRITEPATH."/uploads/excel/".$file['file_name'];
//check physical file
if(!file_exists($file_name_with_path))
{
//file not found update status and reason
$message = "Physical file not found";
// echo $message;
$this->myLogger->logme('error',($message . ' for file id ' . $file_id));
$this->fileModel->where('id', $file_id)->set(['status' => 'failed','reason' => json_encode(['error_summary' => array_count_values([5]),'error_data' => $message])])->update();
return array('error_summary' => [5], 'error_data' => $message);
}
helper('excel_util_helper');
//get file name
$file_id = $params['file_id'];
$file = $this->fileModel->find($file_id);
// dd($file);
$return = [];
if (!isset($file)) {
//file not found in DB
return array('status' => false, 'msg' => 'file not found in DB');
}
$file_name_with_path = WRITEPATH . "/uploads/excel/" . $file['file_name'];
//get excel data
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file_name_with_path);
$sheet = $spreadsheet->getActiveSheet();
$highestRowAndColumn = $sheet->getHighestRowAndColumn();
$result = ['error_type' => 2,'error_summary' => [], 'error_data' => [] ];
$columns_to_check = $this->enrollment_excel_columns;
$keys = array_keys($columns_to_check);
$allowedHighestColumn = end($columns_to_check);
$excel_data = $sheet->rangeToArray('A1:' . $allowedHighestColumn['col_cell_name'] . $highestRowAndColumn['row']);
// print_r($keys);die();
//get existing units in the current branch
$existing_units = $this->clientBranchModel->getExisitingUnits(client_id: $file['client_id'],client_branch_id: $file['client_branch_id']);
//remove header
unset($excel_data[0]);
// dd($excel_data);
$emp_emails = [];
//check physical file
if (!file_exists($file_name_with_path)) {
//file not found update status and reason
$message = "Physical file not found";
// echo $message;
$this->myLogger->logme('error', ($message . ' for file id ' . $file_id));
$this->fileModel->where('id', $file_id)->set(['status' => 'failed', 'reason' => json_encode(['error_summary' => array_count_values([5]), 'error_data' => $message])])->update();
return array('error_summary' => [5], 'error_data' => $message);
}
//check is welcome notification enabled
$notification = $this->notificationModel->where('client_id',$file['client_id'])->where('template_name','member_welcome_mail')->first();
// dd($notification);
$client_details = $this->clientModel->where('id', $file['client_id'])->first();
$policy_details = $this->clientPolicyModel->where('id', $file['policy_id'])->first();
//get excel data
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file_name_with_path);
$sheet = $spreadsheet->getActiveSheet();
// dd($policy_details);
//get policy slab rates
// $slab_details = $this->policiesModel->getPolicySlabRatesForEmpOnboard($file['policy_id'],$file['client_id']);
// dd($slab_details);
$highestRowAndColumn = $sheet->getHighestRowAndColumn();
$result = ['error_type' => 2, 'error_summary' => [], 'error_data' => []];
$columns_to_check = $this->enrollment_excel_columns;
$keys = array_keys($columns_to_check);
$allowedHighestColumn = end($columns_to_check);
$excel_data = $sheet->rangeToArray('A1:' . $allowedHighestColumn['col_cell_name'] . $highestRowAndColumn['row']);
// print_r($keys);die();
//get existing units in the current branch
$existing_units = $this->clientBranchModel->getExisitingUnits(client_id: $file['client_id'], client_branch_id: $file['client_branch_id']);
//remove header
unset($excel_data[0]);
// dd($excel_data);
$emp_emails = [];
foreach ($excel_data as $key => $row)
{
$is_row_empty = check_row_is_empty_or_null($row);
if(!$is_row_empty)
{
//check is welcome notification enabled
$notification = $this->notificationModel->where('client_id', $file['client_id'])->where('template_name', 'member_welcome_mail')->first();
// dd($notification);
$client_details = $this->clientModel->where('id', $file['client_id'])->first();
$policy_details = $this->clientPolicyModel->where('id', $file['policy_id'])->first();
$value = [];
$policy_data = [];
$temp_unit = '';
if(empty($row[12]))
{
$temp_unit = $existing_units[0];
}
$value['emp_code'] = $row[1];
$value['name'] = $row[2];
$value['doj'] = (!empty($row[3]) ? change_date_format($row[3],'d-M-Y','Y-m-d') : null );
$value['gender'] = $row[4];
$value['relationship'] = ucfirst(trim($row[5]));
$value['dob'] = change_date_format($row[6],'d-M-Y','Y-m-d');
$value['email_corporate'] = $row[7];
$value['mobile'] = $row[8];
$value['band'] = $row[10];
$value['basic_pay'] = $row[11];
$value['unit'] = $temp_unit;
$value['family_floater_key'] = null;
$value['client_id'] = $file['client_id'];
$value['client_branch_id'] = $file['client_branch_id'];
$value['file_id'] = $file_id;
$value['is_addon_value'] = $policy_details['policy_type_id'] == 3 ? 1 : 0;
// dd($policy_details);
$value['temp']['emp_id'] = null; // dummy value for using exisitng funciton in model
if (strtolower(trim($value['relationship'])) === 'mother' || strtolower(trim($value['relationship'])) === 'father') {
$relation = 'parent';
} else if(strtolower(trim($value['relationship'])) === 'son' || strtolower(trim($value['relationship'])) === 'daughter'){
$relation = 'child';
}else if((strtolower(trim($value['relationship'])) === 'father in law' || strtolower(trim($value['relationship'])) === 'mother in law') || (strtolower(trim($value['relationship'])) === 'father-in-law' || strtolower(trim($value['relationship'])) === 'mother-in-law')){
$relation = 'parent_in_law';
}else if(strtolower(trim($value['relationship'])) === 'spouse'){
$relation = 'spouse';
}else if(strtolower(trim($value['relationship'])) === 'self'){
$relation = 'self';
}else {
$relation = '';
}
$value['family_floater_key'] = $relation;
//get policy slab rates
// $slab_details = $this->policiesModel->getPolicySlabRatesForEmpOnboard($file['policy_id'],$file['client_id']);
// dd($slab_details);
$parent_policy_mail_sended_emp_code = [];
foreach ($excel_data as $key => $row) {
$is_row_empty = check_row_is_empty_or_null($row);
if (!$is_row_empty) {
$policy_data['basic_cover_si'] = $row[9];
$policy_data['date_coverage'] = $row[13] != "" && $row[13] != null ? change_date_format($row[13],'d-M-Y','Y-m-d') : null;
$policy_data['client_policy_id'] = $file['policy_id'];
$employee = $this->employeeModel->checkExistingEmployee($value,$file['client_branch_id']);
unset($value['temp']);
//save employee table
// dd($employee['id']);
if($employee !== null)
{
$value['updated_by'] = $file['created_by'];
$value['id'] = $employee['id'];
$value['emp_status'] = 'draft';
$log_message = 'Enrollment Update Employee - '.$employee['name'].'('.$employee['emp_code'].') with PK '.$employee['id'];
}
else
{
$value['emp_status'] = 'draft';
$value['created_by'] = $file['created_by'];
$log_message = 'Enrollment Insert Employee- '.$value['name'] .'('.$value['emp_code'] .') with PK ';
}
$value = ExcelSanitizeHelper::sanitizeArrayData($value);
$this->employeeModel->save($value);
if (isset($value['id']))
{ $emp_id = $value['id']; }
else { $emp_id = $this->employeeModel->getInsertID();
$log_message .= $emp_id;
}
// $emp_id = $this->employeeModel->getInsertID();
// if($emp_id != 0){ $log_message .= $emp_id; }
// else{ $emp_id = $employee['id']; }
$this->myLogger->logme('error',$log_message);
//save policy table
$employee_policy = $this->employeePolicyModel->checkExistingEmpPolicy(['employee_id' => $emp_id,'client_policy_id' => $file['policy_id']]);
if(count($employee_policy))
{
$policy_data['updated_by'] = $file['created_by'];
$policy_data['id'] = $employee_policy[0]['id'];
$policy_data['status'] = 'draft';
$policy_data['payable_employee'] = check_pay_by_employee_or_company($policy_details['policy_terms'], $value['relationship']);
$policy_data['file_id'] = isset($employee_policy[0]['file_id']) && $employee_policy[0]['file_id'] != '' ? $employee_policy[0]['file_id'] : $file_id ;
$log_message = 'Update Employee Policy for '. $value['name'].'('. $value['emp_code'].') with PK- ' . $employee_policy[0]['id'] .' client policy ID '.$employee_policy[0]['client_policy_id'].' with SI '.$policy_data['basic_cover_si'];
// echo 'insert policy';
}
else
{
$policy_data['employee_id'] = $emp_id;
$policy_data['client_policy_id'] = $file['policy_id'];
$policy_data['created_by'] = $file['created_by'];
$policy_data['status'] = 'draft';
$policy_data['payable_employee'] = check_pay_by_employee_or_company($policy_details['policy_terms'], $value['relationship']);
$policy_data['file_id'] = $file_id;
$log_message = 'Insert Employee Policy for '. $value['name'].'('. $value['emp_code'].') - client policy id -'. $file['policy_id'].' - with SI '.$policy_data['basic_cover_si'];
// echo 'update policy';
}
log_message('error',json_encode($policy_data));
// dd($policy_data);
$this->employeePolicyModel->save($policy_data);
$emp_policy_id = $this->employeePolicyModel->getInsertID();
$this->myLogger->logme('error',$log_message);
$employeeRestController = new EmployeeRestController();
$employeeRestController->updatePremiumAmount($file['policy_id'], $value['emp_code'], $file['client_branch_id']);
//save email of self for send mail later
if (isset($notification) && $notification['enabled'] == 1 && $notification['mail_content'] != '')
{
if(strtolower($value['relationship']) == 'self' && $value['email_corporate'] != "")
{
$params['dataToInsert'] = $value; //holds employee master data
$params['notification'] = $notification;
$params['client_data'] = $client_details;
$params['common'] = [
'client_id' => $file['client_id'],
'client_branch_id' => $file['client_branch_id'],
'client_policy_id' => $file['policy_id'],
'employee_policy_id' => $emp_policy_id ?? null,
'employee_id' => $emp_id,
'mail_type' => 'member_welcome_mail',
];
//store email and mail content via helper to send notification
$emp_emails[] = sendMailNotification::sendMailNotification('member_welcome_mail', $params);
}
}
}// endof if row is empty check
} //end of for loop
// dd($emp_emails);
// for bulk mail queue job push
if (!empty($emp_emails) && count($emp_emails) > 0) {
$emp_emails = array_chunk($emp_emails, 20);
foreach ($emp_emails as $key => $value) {
$job_details = new Jobs();
$r = Jobs::addJob(['job_name' => 'bulk_mail', 'payload' => $value]);
$value = [];
$policy_data = [];
$temp_unit = '';
if (empty($row[12])) {
$temp_unit = $existing_units[0];
}
$value['emp_code'] = $row[1];
$value['name'] = $row[2];
$value['doj'] = (!empty($row[3]) ? change_date_format($row[3], 'd-M-Y', 'Y-m-d') : null);
$value['gender'] = $row[4];
$value['relationship'] = ucfirst(trim($row[5]));
$value['dob'] = change_date_format($row[6], 'd-M-Y', 'Y-m-d');
$value['email_corporate'] = $row[7];
$value['mobile'] = $row[8];
$value['band'] = $row[10];
$value['basic_pay'] = $row[11];
$value['unit'] = $temp_unit;
$value['family_floater_key'] = null;
$value['client_id'] = $file['client_id'];
$value['client_branch_id'] = $file['client_branch_id'];
$value['file_id'] = $file_id;
$value['is_addon_value'] = $policy_details['policy_type_id'] == 3 ? 1 : 0;
$value['temp']['emp_id'] = null; // dummy value for using exisitng funciton in model
if (strtolower(trim($value['relationship'])) === 'mother' || strtolower(trim($value['relationship'])) === 'father') {
$relation = 'parent';
} else if (strtolower(trim($value['relationship'])) === 'son' || strtolower(trim($value['relationship'])) === 'daughter') {
$relation = 'child';
} else if ((strtolower(trim($value['relationship'])) === 'father in law' || strtolower(trim($value['relationship'])) === 'mother in law') || (strtolower(trim($value['relationship'])) === 'father-in-law' || strtolower(trim($value['relationship'])) === 'mother-in-law')) {
$relation = 'parent_in_law';
} else if (strtolower(trim($value['relationship'])) === 'spouse') {
$relation = 'spouse';
} else if (strtolower(trim($value['relationship'])) === 'self') {
$relation = 'self';
} else {
$relation = '';
}
$value['family_floater_key'] = $relation;
$policy_data['basic_cover_si'] = $row[9];
$policy_data['date_coverage'] = $row[13] != "" && $row[13] != null ? change_date_format($row[13], 'd-M-Y', 'Y-m-d') : null;
$policy_data['client_policy_id'] = $file['policy_id'];
$policy_data['enrollment_open_date'] = $file['enrollment_open_date'] ?? null;
$policy_data['enrollment_close_date'] = $file['enrollment_close_date'] ?? null;
$employee = $this->employeeModel->checkExistingEmployee($value, $file['client_branch_id']);
unset($value['temp']);
//save employee table
// dd($employee['id']);
if ($employee !== null) {
$value['updated_by'] = $file['created_by'];
$value['id'] = $employee['id'];
$value['emp_status'] = 'draft';
$log_message = 'Enrollment Update Employee - ' . $employee['name'] . '(' . $employee['emp_code'] . ') with PK ' . $employee['id'];
} else {
$value['emp_status'] = 'draft';
$value['created_by'] = $file['created_by'];
$log_message = 'Enrollment Insert Employee- ' . $value['name'] . '(' . $value['emp_code'] . ') with PK ';
}
$value = ExcelSanitizeHelper::sanitizeArrayData($value);
$this->employeeModel->save($value);
if (isset($value['id'])) {
$emp_id = $value['id'];
} else {
$emp_id = $this->employeeModel->getInsertID();
$log_message .= $emp_id;
}
// $emp_id = $this->employeeModel->getInsertID();
// if($emp_id != 0){ $log_message .= $emp_id; }
// else{ $emp_id = $employee['id']; }
$this->myLogger->logme('error', $log_message);
//save policy table
$employee_policy = $this->employeePolicyModel->checkExistingEmpPolicy(['employee_id' => $emp_id, 'client_policy_id' => $file['policy_id']]);
if (count($employee_policy)) {
$policy_data['updated_by'] = $file['created_by'];
$policy_data['id'] = $employee_policy[0]['id'];
$policy_data['status'] = 'draft';
$policy_data['payable_employee'] = check_pay_by_employee_or_company($policy_details['policy_terms'], $value['relationship']);
$policy_data['file_id'] = isset($employee_policy[0]['file_id']) && $employee_policy[0]['file_id'] != '' ? $employee_policy[0]['file_id'] : $file_id;
$log_message = 'Update Employee Policy for ' . $value['name'] . '(' . $value['emp_code'] . ') with PK- ' . $employee_policy[0]['id'] . ' client policy ID ' . $employee_policy[0]['client_policy_id'] . ' with SI ' . $policy_data['basic_cover_si'];
// echo 'insert policy';
} else {
$policy_data['employee_id'] = $emp_id;
$policy_data['client_policy_id'] = $file['policy_id'];
$policy_data['created_by'] = $file['created_by'];
$policy_data['status'] = 'draft';
$policy_data['payable_employee'] = check_pay_by_employee_or_company($policy_details['policy_terms'], $value['relationship']);
$policy_data['file_id'] = $file_id;
$log_message = 'Insert Employee Policy for ' . $value['name'] . '(' . $value['emp_code'] . ') - client policy id -' . $file['policy_id'] . ' - with SI ' . $policy_data['basic_cover_si'];
// echo 'update policy';
}
log_message('error', json_encode($policy_data));
// dd($policy_data);
$this->employeePolicyModel->save($policy_data);
$emp_policy_id = $this->employeePolicyModel->getInsertID();
$this->myLogger->logme('error', $log_message);
$employeeRestController = new EmployeeRestController();
$employeeRestController->updatePremiumAmount($file['policy_id'], $value['emp_code'], $file['client_branch_id']);
//save email of self for send mail later
if (isset($notification) && $notification['enabled'] == 1 && $notification['mail_content'] != '') {
if (strtolower($value['relationship']) == 'self' && $value['email_corporate'] != "") {
$params['dataToInsert'] = $value; //holds employee master data
$params['notification'] = $notification;
$params['client_data'] = $client_details;
$params['common'] = [
'client_id' => $file['client_id'],
'client_branch_id' => $file['client_branch_id'],
'client_policy_id' => $file['policy_id'],
'employee_policy_id' => $emp_policy_id ?? null,
'employee_id' => $emp_id,
'mail_type' => 'member_welcome_mail',
];
$params['enrollment_open_date'] = $file['enrollment_open_date'] ?? null;
$params['enrollment_close_date'] = $file['enrollment_close_date'] ?? null;
//store email and mail content via helper to send notification
$emp_emails[] = sendMailNotification::sendMailNotification('member_welcome_mail', $params);
} else if ($policy_details['policy_type_id'] == 3 && $policy_details['is_addon'] == 3 && !in_array($row[1], $parent_policy_mail_sended_emp_code)) {
$sefData = $this->employeeModel
->where('is_active', 1)
->whereIn('emp_status', ['draft', 'enrolled'])
->where('family_floater_key', 'self')
->where('emp_code', $row[1])
->where('client_id', $file['client_id'])
->where('client_branch_id', $file['client_branch_id'])
->where('email_corporate is not null')
->first();
if (!empty($sefData)) {
$value['email_corporate'] = $sefData['email_corporate'];
$value['name'] = $sefData['name'];
$value['mobile'] = $sefData['mobile'];
$params['dataToInsert'] = $value; //holds employee master data
$params['notification'] = $notification;
$params['client_data'] = $client_details;
$params['common'] = [
'client_id' => $file['client_id'],
'client_branch_id' => $file['client_branch_id'],
'client_policy_id' => $file['policy_id'],
'employee_policy_id' => $emp_policy_id ?? null,
'employee_id' => $emp_id,
'mail_type' => 'member_welcome_mail',
];
$params['enrollment_open_date'] = $file['enrollment_open_date'] ?? null;
$params['enrollment_close_date'] = $file['enrollment_close_date'] ?? null;
//store email and mail content via helper to send notification
$emp_emails[] = sendMailNotification::sendMailNotification('member_welcome_mail', $params);
$parent_policy_mail_sended_emp_code[] = $row[1];
}
}
}
} // endof if row is empty check
} //end of for loop
// dd($emp_emails);
// for bulk mail queue job push
if (!empty($emp_emails) && count($emp_emails) > 0) {
$emp_emails = array_chunk($emp_emails, 20);
foreach ($emp_emails as $key => $value) {
$job_details = new Jobs();
$r = Jobs::addJob(['job_name' => 'bulk_mail', 'payload' => $value]);
}
}
$this->fileModel->where('id', $file_id)->set(['status' => 'success','reason' => ''])->update();
$this->myLogger->logme("error",'{file_id} uploaded success',['file_id' => $file_id]);
$this->fileModel->where('id', $file_id)->set(['status' => 'success', 'reason' => ''])->update();
$this->myLogger->logme("error", '{file_id} uploaded success', ['file_id' => $file_id]);
$this->setPullNotification($this->getFileMetaDataByFileId($file_id,'success'));
$this->setPullNotification($this->getFileMetaDataByFileId($file_id, 'success'));
return true;
}//end of employeesEnrollmentInsert
return true;
} //end of employeesEnrollmentInsert
}

View File

@ -9,6 +9,7 @@ use Psr\Log\LoggerInterface;
use App\Models\UserModel;
use App\Models\AuthHistoryModel;
use App\Libraries\AuthLogout;
class LoginController extends BaseController
{
@ -54,25 +55,29 @@ class LoginController extends BaseController
$path = getenv('cookie.Path');
$domain = getenv('cookie.Domain');
$https = getenv('ccokie.secure');
setcookie('session_data', json_encode($session_data), time() + 12 * 60 * 60, $path, $domain, $https, true);
// setcookie('session_data', json_encode($session_data), time() + 12 * 60 * 60, $path, $domain, $https, true);
set_session_data($session_data);
// Bind session to device
set_session_data(['fingerprint' => hash('sha256',
($this->request->getUserAgent()->getAgentString() . '|' . ($this->request->getIPAddress()
)))]);
log_message('error', 'Set The UserId : `'. $user->id .'` in Session');
log_message('error', 'User Login Sucessfully');
$this->getUserDeviceInfo($user->id, 'NhanceUser');
return redirect()->to(base_url('/dashboard/view'));
return AuthLogout::logout();
}else{
log_message('error', 'User Not Active');
session()->setFlashdata('error', 'User Not Active');
return redirect()->to(base_url('login'));
return AuthLogout::logout();
}
}else{
log_message('error', 'User Not Registered');
session()->setFlashdata('error', 'User Not Registered');
return redirect()->to(base_url('login'));
return AuthLogout::logout();
}
}
@ -94,14 +99,16 @@ class LoginController extends BaseController
// setcookie('session_data', '', time() - 3600, $path);
// return redirect()->to(base_url('login'));
$path = getenv('cookie.Path');
session()->destroy();
// setcookie('session_data', '', time() - 3600, $path);
$path = getenv('cookie.Path');
$domain = getenv('cookie.Domain');
$https = getenv('cookie.secure');
setcookie('session_data',null, time() -3600, $path, $domain, $https, true);
return redirect()->to(base_url('login'));
// $path = getenv('cookie.Path');
// session()->destroy();
// // setcookie('session_data', '', time() - 3600, $path);
// $path = getenv('cookie.Path');
// $domain = getenv('cookie.Domain');
// $https = getenv('cookie.secure');
// setcookie('session_data',null, time() -3600, $path, $domain, $https, true);
// return redirect()->to(base_url('login'));
return AuthLogout::logout();
}

View File

@ -37,6 +37,7 @@ use App\Models\SettingsModel;
use App\Models\VehicleModel;
use CodeIgniter\CLI\CLI;
use CodeIgniter\CLI\BaseCommand;
class MasterController extends AdminController
{
@ -1741,6 +1742,7 @@ class MasterController extends AdminController
'cache' => WRITEPATH . 'cache',
'sample_import_excel' => ROOTPATH . 'public/sample_import_excel',
'lead_files' => WRITEPATH . 'uploads/lead_files/',
'exports' => WRITEPATH . 'exports/',
];
foreach ($folders as $folderName => $folderPath) {
@ -1822,4 +1824,78 @@ class MasterController extends AdminController
echo "################################################################\n\n";
}
public function checkEnv()
{
$root = ROOTPATH;
$sample_file_name = '.env.sample';
$sample_file_path = $root . $sample_file_name;
$envFile = $root . '.env';
// echo ($exampleFile);//die();
if (!file_exists($sample_file_path)) {
echo ("$sample_file_path file not found");
exit();
}
if (!file_exists($envFile)) {
echo('.env file not found');
exit();
}
$example = $this->parseEnv($sample_file_path);
$actual = $this->parseEnv($envFile);
$missing = array_diff_key($example, $actual);
$extra = array_diff_key($actual, $example);
CLI::write("#################### CHECKING ENV ##############################\n");
if ($extra) {
CLI::write('⚠️ Extra ENV keys (not in .env.example)', 'yellow');
foreach (array_keys($extra) as $key) {
CLI::write(" - $key", 'yellow');
}
}
CLI::newLine();
if ($missing) {
CLI::error('❌ Missing ENV keys');
foreach (array_keys($missing) as $key) {
CLI::write(" - $key", 'red');
}
}
CLI::newLine();
if (!$missing && !$extra) {
CLI::write('✅ ENV configuration is clean', 'green');
return CLI::EXIT_SUCCESS;
}
CLI::write("#################### END OF CHECKING ENV ############################\n");
}
private function parseEnv(string $file): array
{
$lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$env = [];
foreach ($lines as $line) {
$line = trim($line);
if ($line === '' || str_starts_with($line, '#')) {
continue;
}
if (strpos($line, '=') !== false) {
[$key] = explode('=', $line, 2);
$env[trim($key)] = true;
}
}
return $env;
}
}

View File

@ -5,12 +5,29 @@ use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use App\Libraries\AuthLogout;
class AuthMVC implements FilterInterface
{
public function before(RequestInterface $request, $arguments = null)
{
if (!check_session() && !check_cookie()) {
return redirect()->to(base_url('/login'));
if (!check_session())
{
return AuthLogout::logout();
}
// if (!check_cookie())
// {
// return AuthLogout::logout();
// }
// Fingerprint validation
$fp = hash('sha256',
$request->getUserAgent()->getAgentString() . '|' . $request->getIPAddress()
);
if (session()->get('fingerprint') !== $fp) {
return AuthLogout::logout();
}
}

View File

@ -107,11 +107,11 @@ class Cors implements FilterInterface
);
}
$this->log('CORS filter initialized', [
'allowed_origins' => $this->allowedOrigins,
'allow_credentials' => $this->allowCredentials,
'allowed_methods' => $this->allowedMethods,
]);
// $this->log('CORS filter initialized', [
// 'allowed_origins' => $this->allowedOrigins,
// 'allow_credentials' => $this->allowCredentials,
// 'allowed_methods' => $this->allowedMethods,
// ]);
}
/**
@ -143,7 +143,7 @@ class Cors implements FilterInterface
// If wildcard present in configuration, allow any origin
if (in_array('*', $this->allowedOrigins, true)) {
$this->log('Origin allowed: wildcard match', ['origin' => $origin]);
// $this->log('Origin allowed: wildcard match', ['origin' => $origin]);
return true;
}
@ -159,10 +159,10 @@ class Cors implements FilterInterface
// 1. Exact match (including scheme and port)
// Example: https://example.com matches https://example.com
if (strcasecmp($allowed, $origin) === 0) {
$this->log('Origin allowed: exact match', [
'origin' => $origin,
'matched_rule' => $allowed
]);
// $this->log('Origin allowed: exact match', [
// 'origin' => $origin,
// 'matched_rule' => $allowed
// ]);
return true;
}
@ -178,11 +178,11 @@ class Cors implements FilterInterface
// Check if origin host ends with the allowed root domain
if ($originHost === $allowedRoot || str_ends_with($originHost, '.' . $allowedRoot)) {
$this->log('Origin allowed: wildcard subdomain match', [
'origin' => $origin,
'matched_rule' => $allowed,
'origin_host' => $originHost
]);
// $this->log('Origin allowed: wildcard subdomain match', [
// 'origin' => $origin,
// 'matched_rule' => $allowed,
// 'origin_host' => $originHost
// ]);
return true;
}
}
@ -191,11 +191,11 @@ class Cors implements FilterInterface
// Example: example.com matches both http://example.com and https://example.com
else {
if (strcasecmp($allowed, $originHost) === 0) {
$this->log('Origin allowed: host match (scheme-less)', [
'origin' => $origin,
'matched_rule' => $allowed,
'origin_host' => $originHost
]);
// $this->log('Origin allowed: host match (scheme-less)', [
// 'origin' => $origin,
// 'matched_rule' => $allowed,
// 'origin_host' => $originHost
// ]);
return true;
}
}
@ -320,11 +320,11 @@ class Cors implements FilterInterface
// Preflight is sent by browsers before actual cross-origin requests
// to check if the actual request is safe to send
if ($method === 'OPTIONS') {
$this->log('Preflight request received', [
'origin' => $origin,
'method' => $method,
'uri' => (string) $request->getUri()
]);
// $this->log('Preflight request received', [
// 'origin' => $origin,
// 'method' => $method,
// 'uri' => (string) $request->getUri()
// ]);
// Validate origin - reject if not allowed
if (empty($origin) || !$this->isOriginAllowed($origin)) {
@ -346,10 +346,10 @@ class Cors implements FilterInterface
$response->setStatusCode(204);
$response->setBody('');
$this->log('Preflight approved', [
'origin' => $origin,
'allowed_methods' => $this->allowedMethods
]);
// $this->log('Preflight approved', [
// 'origin' => $origin,
// 'allowed_methods' => $this->allowedMethods
// ]);
return $response;
}
@ -392,10 +392,10 @@ class Cors implements FilterInterface
// Add CORS headers to the response
$this->addCorsHeaders($response, $request, $origin, false);
$this->log('CORS headers added to response', [
'origin' => $origin,
'status' => $response->getStatusCode()
]);
// $this->log('CORS headers added to response', [
// 'origin' => $origin,
// 'status' => $response->getStatusCode()
// ]);
}
/**

View File

@ -0,0 +1,147 @@
<?php
namespace App\Filters;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface;
use Config\Services;
use finfo;
class GlobalPostFileUploadGuard implements FilterInterface
{
/**
* Max file size (in bytes) 25MB
*/
protected int $maxFileSize = 25 * 1024 * 1024;
/**
* Allowed MIME types mapped to extensions
*/
protected array $allowedMimeMap = [
'image/jpeg' => ['jpg', 'jpeg'],
'image/png' => ['png'],
'image/gif' => ['gif'],
'image/webp' => ['webp'],
'image/svg+xml' => ['svg'],
'application/pdf' => ['pdf'],
'application/msword' => ['doc'],
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => ['docx'],
'application/vnd.oasis.opendocument.text' => ['odt'],
'text/rtf' => ['rtf'],
'application/rtf' => ['rtf'],
'application/vnd.ms-excel' => ['xls'],
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => ['xlsx'],
'application/vnd.oasis.opendocument.spreadsheet' => ['ods'],
'text/csv' => ['csv'],
'application/csv' => ['csv'],
'text/plain' => ['txt', 'csv'],
];
protected array $blockedExtensions = [
'php', 'phtml', 'pht', 'phar', 'php3', 'php4', 'php5', 'php7', 'php8', 'phps',
'cgi', 'fcgi', 'pl', 'py', 'rb', 'lua', 'tcl', 'go', 'rs', 'jar', 'class',
'exe', 'dll', 'com', 'bat', 'cmd', 'msi', 'vbs', 'ps1', 'scr',
'sh', 'bash', 'zsh', 'apk', 'app', 'deb', 'rpm', 'bin', 'run',
'js', 'mjs', 'jsp', 'asp', 'aspx', 'cer', 'swf',
'env', 'ini', 'user.ini', 'htaccess', 'htpasswd', 'conf', 'config', 'log', 'sql',
'zip', 'rar', '7z', 'tar', 'gz', 'bz2', 'xz', 'iso',
'lnk', 'url', 'reg', 'sys', 'drv', 'vxd', 'tmp', 'bak', 'old', 'backup', 'key', 'pem'
];
public function before(RequestInterface $request, $arguments = null)
{
if ($request->getMethod() !== 'post') {
return;
}
$files = $request->getFiles();
if (empty($files)) {
return;
}
foreach ($files as $inputName => $fileData) {
$this->validateFileInput($fileData, $inputName);
}
}
private function validateFileInput($fileData, string $inputName): void
{
if (is_array($fileData)) {
foreach ($fileData as $file) {
$this->validateSingleFile($file, $inputName);
}
} else {
$this->validateSingleFile($fileData, $inputName);
}
}
private function validateSingleFile($file, string $inputName): void
{
$request = Services::request();
$clientIp = $request->getIPAddress();
$uri = $request->getUri()->getPath();
if (!$file->isValid()) {
if ($file->getError() === UPLOAD_ERR_INI_SIZE || $file->getError() === UPLOAD_ERR_FORM_SIZE) {
$this->block("File exceeds server-side size limit", $clientIp, $uri, $inputName, $file->getClientName(), 'unknown', 'unknown', 0);
}
return;
}
$originalName = $file->getClientName();
$extension = strtolower($file->getExtension());
$mime = $file->getMimeType();
$size = $file->getSize();
// --- 1. Fixed Null Byte & Path Traversal Check ---
if (preg_match('/\0|[\/\\\]/', $originalName)) {
$this->block("Malicious filename characters", $clientIp, $uri, $inputName, $originalName, $mime, $extension, $size);
}
// --- 2. Double Extension Attack Check ---
if (preg_match('/\.(php|phtml|phar|exe|sh|bat|cmd|js|jsp|asp|aspx|py|pl)\./i', $originalName)) {
$this->block("Double extension attack", $clientIp, $uri, $inputName, $originalName, $mime, $extension, $size);
}
// --- 3. Forbidden Extension ---
if (in_array($extension, $this->blockedExtensions, true)) {
$this->block("Forbidden extension", $clientIp, $uri, $inputName, $originalName, $mime, $extension, $size);
}
// --- 4. File Size Limit ---
if ($size > $this->maxFileSize) {
$this->block("File too large", $clientIp, $uri, $inputName, $originalName, $mime, $extension, $size);
}
// --- 5. MIME Allow-list Check ---
if (!array_key_exists($mime, $this->allowedMimeMap)) {
$this->block("MIME type not allowed ($mime)", $clientIp, $uri, $inputName, $originalName, $mime, $extension, $size);
}
// --- 6. MIME-Extension Consistency ---
if (!in_array($extension, $this->allowedMimeMap[$mime], true)) {
$this->block("MIME-extension mismatch", $clientIp, $uri, $inputName, $originalName, $mime, $extension, $size);
}
}
private function block(string $reason, string $ip, string $uri, string $field, string $filename, string $mime, string $ext, int $size): void
{
log_message('critical',
'[UPLOAD_BLOCKED] {reason} | IP: {ip} | URI: {uri} | Field: {field} | File: {file} | MIME: {mime} | EXT: {ext} | SIZE: {size}',
['reason'=>$reason, 'ip'=>$ip, 'uri'=>$uri, 'field'=>$field, 'file'=>$filename, 'mime'=>$mime, 'ext'=>$ext, 'size'=>$size]
);
$response = Services::response();
$response->setStatusCode(403)
->setJSON([
'status' => 'error',
'message' => 'File upload rejected: Security policy violation.',
'debug' => (ENVIRONMENT === 'development') ? $reason : null
])
->send();
exit;
}
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) {}
}

View File

@ -0,0 +1,130 @@
<?php
namespace App\Filters;
use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;
class SecurityInputFilter implements FilterInterface
{
/**
* High-confidence XSS patterns only
* (low false-positive set)
**/
protected array $xssPatterns = [
// Script execution
'/<\s*script\b/i',
'/<\/\s*script\s*>/i',
// JavaScript execution vectors
'/javascript\s*:/i',
'/vbscript\s*:/i',
'/data\s*:\s*text\/html/i',
// Inline event handlers (strong signal)
'/on\w+\s*=\s*["\']?/i',
// Dangerous HTML tags
'/<\s*iframe\b/i',
'/<\s*object\b/i',
'/<\s*embed\b/i',
'/<\s*applet\b/i',
'/<\s*img\b/i',
// Image-based execution
'/<\s*img\b[^>]*on\w+/i',
// SVG-based execution (modern bypass)
'/<\s*svg\b/i',
'/<\s*math\b/i',
// Meta refresh redirect
'/<\s*meta\b[^>]*http-equiv\s*=\s*["\']?refresh/i',
// HTML injection via src/href
'/<\s*\w+\b[^>]*(src|href)\s*=\s*["\']?\s*(javascript|data)\s*:/i'
];
public function before(RequestInterface $request, $arguments = null)
{
$logger = Services::mylogger();
$response = Services::response();
// Collect all user-controlled input
$inputs = array_merge(
$request->getGet(),
$request->getPost()
);
if (empty($inputs)) {
return;
}
foreach ($inputs as $field => $value) {
if (is_array($value)) {
$value = json_encode($value);
}
// Step 1: Canonicalization (VERY IMPORTANT)
$canonical = $this->canonicalize($value);
// Step 2: Trim (hygiene)
$canonical = trim($canonical);
// Step 3: Detection (signal-only)
if ($this->detectXss($canonical)) {
// 🔐 Log intent, not data
$logger->logme('critical','SECURITY_BLOCKED_REQUEST - '. json_encode([
'ip' => $request->getIPAddress(),
'method' => $request->getMethod(),
'uri' => current_url(),
'field' => $field,
'attack' => 'XSS_PATTERN',
'length' => strlen($canonical),
'hash' => hash('sha256', $canonical),
]));
// ⛔ Block request
return $response
->setStatusCode(403)
->setJSON([
'status' => 403,
'error' => 'Forbidden',
'message' => 'Malicious input detected'
]);
}
}
}
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
// no-op
}
/**
* Canonicalization prevents encoded bypass
*/
private function canonicalize(string $value): string
{
$value = urldecode($value);
$value = html_entity_decode($value, ENT_QUOTES | ENT_HTML5, 'UTF-8');
// Remove invisible control characters
return preg_replace('/[\x00-\x1F\x7F]/u', '', $value);
}
private function detectXss(string $value): bool
{
foreach ($this->xssPatterns as $pattern) {
if (preg_match($pattern, $value)) {
return true;
}
}
return false;
}
}

View File

@ -553,6 +553,47 @@ if (!function_exists('name_and_empid_check_in_db'))
}
}
if (!function_exists('check_emp_code_duplication')) {
function check_emp_code_duplication($family_data, $actionArr)
{
$employeeModel = new EmployeeModel();
$row_ids = [];
$status = false;
$client_id = $actionArr['client_id'];
$policy_id = $actionArr['policy_id'];
$client_branch_id = $actionArr['client_branch_id'];
$current_action = $actionArr['action'];
foreach ($family_data as $rkey => $row) {
if ($current_action != 'dependent_addition' || (isset($row['temp']) && $row['temp']['source'] != 'db')) {
$res = $employeeModel
->join('client_policy cp', "employees.client_id = cp.client_id")
->join('employee_polices ep', "cp.id = ep.client_policy_id AND employees.id = ep.employee_id")
->where("cp.id", $policy_id)
->where("employees.client_id", $client_id)
->where("employees.client_branch_id", $client_branch_id)
->where("employees.is_active", 1)
->where("employees.emp_status", 'active')
->where("ep.is_active", 1)
->where("ep.status", 'active')
->where('TRIM(emp_code)', trim($row[1]))
->findAll();
if(count($res) > 0){
$row_ids[] = $row[0];
}
}
}
if(!empty($row_ids)){
$status = true;
}
return ['status' => $status, 'row_ids' => $row_ids];
}
}
if (!function_exists('check_dependent_conflict'))
{
function check_dependent_conflict($family_data,$policy_terms,$actionArr,$is_lgbtq)

View File

@ -51,12 +51,23 @@ class sendMailNotification
$nhance_logo = $_ENV['NHANCE_LOGO'];
$client_logo = base_url() . "public/uploads/logo/" . $client_data['client_logo'];
$enrollment_open_date = !empty($params['enrollment_open_date'] ?? null)
? change_date_format($params['enrollment_open_date'], 'Y-m-d', 'F d, Y')
: 'N/A';
$enrollment_close_date = !empty($params['enrollment_close_date'] ?? null)
? change_date_format($params['enrollment_close_date'], 'Y-m-d', 'F d, Y')
: 'N/A';
$mail_content = str_replace(["[[client_logo]]", "{{client_logo}}"], "<img src='$client_logo' alt='Client Logo' width='20'>", $mail_content);
$mail_content = str_replace(["[[nhance_logo]]", "{{nhance_logo}}"], "<img src='$nhance_logo' alt='Nhance Logo' width='20'>", $mail_content);
$mail_content = str_replace(["[[member_name]]", "{{member_name}}"], $employee_name, $mail_content);
$mail_content = str_replace(["[[member_mobile]]", "{{member_mobile}}"], $employee_mobile_no, $mail_content);
$mail_content = str_replace(["[[client_name]]", "{{client_name}}"], $client_data['client_name'], $mail_content);
$mail_content = str_replace(["[[enrollment_open_date]]", "{{enrollment_open_date}}"], $enrollment_open_date, $mail_content);
$mail_content = str_replace(["[[enrollment_close_date]]", "{{enrollment_close_date}}"], $enrollment_close_date, $mail_content);
$mail_content = str_replace(["[[app_link]]", "{{app_link}}"], "<a href='$app_link'>Review Details</a>", $mail_content);
if ($dataToInsert['relationship'] == 'Self' && $mail != null || $mail != '') {
@ -1247,6 +1258,13 @@ class sendMailNotification
$app_link = $_ENV['App_Url'];
$nhance_logo = $_ENV['NHANCE_LOGO'];
$enrollment_open_date = !empty($params['enrollment_open_date'] ?? null)
? date('F d, Y', strtotime(str_replace('/', '-', $params['enrollment_open_date'] ?? '')))
: date('F d, Y');
$enrollment_close_date = !empty($params['enrollment_close_date'] ?? null)
? date('F d, Y', strtotime(str_replace('/', '-', $params['enrollment_close_date'] ?? '')))
: date('F d, Y', strtotime('+15 days'));
$client_logo = base_url() . "public/uploads/logo/" . $client_data['client_logo'];
@ -1256,6 +1274,9 @@ class sendMailNotification
$mail_content = str_replace(["[[member_mobile]]", "{{member_mobile}}"], $mobile, $mail_content);
$mail_content = str_replace(["[[client_name]]", "{{client_name}}"], $client_data['client_name'], $mail_content);
$mail_content = str_replace(["[[enrollment_open_date]]", "{{enrollment_open_date}}"], $enrollment_open_date, $mail_content);
$mail_content = str_replace(["[[enrollment_close_date]]", "{{enrollment_close_date}}"], $enrollment_close_date, $mail_content);
$mail_content = str_replace(["[[app_link]]", "{{app_link}}"], "<a href='$app_link'>Review Details</a>", $mail_content);
if ($mail != null || $mail != '') {

View File

@ -21,7 +21,7 @@ if(!function_exists('check_cookie')){
'userProfile' => $value['userProfile'],
'user_team' => $user_team,
];
set_session_data($session_data);
// set_session_data($session_data);
// $this->getUserDeviceInfo($user->id, 'NhanceUser');
// return redirect()->to(base_url('/dashboard/view'));
return true;

View File

@ -556,7 +556,9 @@ if (!function_exists('change_date_format')) {
if ($source_format !== null && $output_format !== null) {
$date = DateTime::createFromFormat($source_format, $date_str);
if (!$date) {
throw new Exception("Invalid date string for source format: $source_format");
// throw new Exception("Invalid date string for source format: $source_format");
log_message('error', "❌ Date format error : Invalid date string | Params => date_str: {$date_str}, source_format: {$source_format}, output_format: {$output_format}");
return null;
}
return $date->format($output_format);
}
@ -565,7 +567,9 @@ if (!function_exists('change_date_format')) {
if ($source_format !== null && $output_format === null) {
$date = DateTime::createFromFormat($source_format, $date_str);
if (!$date) {
throw new Exception("Invalid date string for source format: $source_format");
// throw new Exception("Invalid date string for source format: $source_format");
log_message('error', "❌ Date format error : Invalid date string | Params => date_str: {$date_str}, source_format: {$source_format}, output_format: {$output_format}");
return null;
}
return $date->format('Y-m-d'); // MySQL default format
}
@ -580,10 +584,17 @@ if (!function_exists('change_date_format')) {
}
// If no format matches, throw an exception
$allowed_placeholders = implode(', ', $allowed_formats);
throw new Exception("Invalid date string format. Allowed formats: $allowed_placeholders");
// throw new Exception("Invalid date string format. Allowed formats: $allowed_placeholders");
log_message(
'error',
"❌ Date format error: Invalid date string. Allowed formats: {$allowed_placeholders} | Params => date_str: {$date_str}, source_format: {$source_format}, output_format: {$output_format}"
);
return null;
}
} catch (Exception $e) {
return "Error: " . $e->getMessage();
// return "Error: " . $e->getMessage();
log_message('error', "❌ Date format error: {$e->getMessage()} | Params => date_str: {$date_str}, source_format: {$source_format}, output_format: {$output_format}");
return null;
}
return null;
@ -692,3 +703,56 @@ if (!function_exists('canSendOtp')) {
}
}
if (!function_exists('getLatestGMCPolicy')) {
function getLatestGMCPolicy(array $empPolicy)
{
try{
$filtered = array_filter($empPolicy, function ($row) {
$type = is_object($row) ? $row->policy_type_id : $row['policy_type_id'];
return isset($type) && (int)$type === 2;
});
if (count($filtered) > 1) {
usort($filtered, function ($a, $b) {
$dateA = is_object($a) ? $a->policy_end_date : $a['policy_end_date'];
$dateB = is_object($b) ? $b->policy_end_date : $b['policy_end_date'];
return strtotime($dateB) <=> strtotime($dateA);
});
$row = reset($filtered);
return is_object($row) ? ($row->ClientPolicyId ?? null) : ($row['ClientPolicyId'] ?? null);
}
return null;
}catch(\Exception $e){
log_message('error', 'Exception getLatestGMCPolicy :' . $e->getMessage());
return null;
}
}
}
if (!function_exists('validateExcelFile')) {
function validateExcelFile($file)
{
$allowed = [
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/vnd.oasis.opendocument.spreadsheet'
];
// if ($file->getError() !== UPLOAD_ERR_OK) return 'Upload error';
// if ($file->getSize() > (16 * 1024 * 1024)) return 'File too large';
// if (!in_array($file->getClientMimeType(), $allowed, true)) return 'Invalid file type';
if ($file->getError() !== UPLOAD_ERR_OK) return false;
if ($file->getSize() > (16 * 1024 * 1024)) return false;
if (!in_array($file->getClientMimeType(), $allowed, true)) return false;
return true;
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace App\Libraries;
use CodeIgniter\HTTP\RedirectResponse;
class AuthLogout
{
public static function logout(): RedirectResponse
{
$session = session();
// Regenerate session ID (kills fixation)
$session->regenerate(true);
// Destroy CI session
$session->destroy();
// Kill PHP session cookie safely
if (ini_get('session.use_cookies')) {
$params = session_get_cookie_params();
setcookie(
session_name(), // DO NOT hardcode cookie name
'',
time() - 42000,
$params['path'],
$params['domain'],
$params['secure'],
$params['httponly']
);
}
session_write_close();
// Redirect with anti-cache headers
return redirect()->to(base_url('login'))
->setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
->setHeader('Pragma', 'no-cache')
->setHeader('Expires', 'Sat, 26 Jul 1997 05:00:00 GMT');
}
}

View File

@ -159,14 +159,17 @@ class EmployeeModel extends Model
client_policy.policy_id as PolicyId,
client_policy.id as ClientPolicyId,
client_policy.is_premium_summery,
CASE
WHEN client_policy.open_for_enrollment IS NULL THEN 0
ELSE client_policy.open_for_enrollment
CASE
WHEN employee_polices.enrollment_open_date <= CURDATE()
AND employee_polices.enrollment_close_date >= CURDATE()
THEN 1
ELSE 0
END AS OpenForEnrollment,
client_policy.disclaimer,
client_policy.policy_type_id ,
employee_polices.tpa_id as tpa_id ,
employee_polices.rand_string as rand_string
employee_polices.rand_string as rand_string,
client_policy.policy_end_date
', FALSE) // Select all columns from both tables
->join('client_policy', 'client_policy.id = employee_polices.client_policy_id')
->join('policy_type', 'policy_type.id = client_policy.policy_type_id')

View File

@ -35,7 +35,9 @@ class EmployeePolicyModel extends Model
"claim_status",
'ecard_sent_status',
'payable_employee',
'file_id'
'file_id',
"enrollment_open_date",
"enrollment_close_date",
];
// Callbacks

View File

@ -20,7 +20,10 @@ class FileModel extends Model
"policy_id",
"client_branch_id",
"uploaded_by",
"updated_by"
"updated_by",
"enrollment_open_date",
"enrollment_close_date",
"hr_id",
];

View File

@ -156,7 +156,7 @@ input:checked + .slider:before {
<th>Client Branch</th>
<!-- <th>TPA</th> -->
<th>Date</th>
<th>Enrolment Status</th>
<!-- <th>Enrolment Status</th> -->
<th>Status</th>
<th>Action</th>
</tr>
@ -299,7 +299,8 @@ input:checked + .slider:before {
<label for="inception_type" style="position: relative;bottom: 5px;left: 85px;">Enable
Employee Enrolment Process</label>
</div> -->
<div class="form-group col-md-4" style="padding-top:50px;padding-bottom: 0px;">
<!-- <div class="form-group col-md-4" style="padding-top:50px;padding-bottom: 0px;">
<label for="inception_type" style=" position: relative;bottom: 5px;">
<label class="switch">
<input id="inception_type" type="checkbox" name="inception_type">
@ -307,27 +308,29 @@ input:checked + .slider:before {
</label>Enable
Employee Enrolment Process
</label>
</div>
<div class="form-row">
<div class="form-group col-md-4">
<label for="open_date">Open Date<span class="text-danger">*</span></label>
<input value="" type="text" class="form-control dateofdata"
placeholder="Enter Open Date " name="open_date" id="open_date">
</div>
</div> -->
<div class="form-group col-md-4">
<label for="close_date">Close Date<span class="text-danger">*</span></label>
<input value="" type="text" class="form-control dateofdata"
placeholder="Enter Close Date " name="close_date" id="close_date">
</div>
<!-- <div class="form-row">
<div class="form-group col-md-4">
<label for="open_date">Open Date<span class="text-danger">*</span></label>
<input value="" type="text" class="form-control dateofdata"
placeholder="Enter Open Date " name="open_date" id="open_date">
</div>
<div class="form-group col-md-4">
<label for="close_date">Close Date<span class="text-danger">*</span></label>
<input value="" type="text" class="form-control dateofdata"
placeholder="Enter Close Date " name="close_date" id="close_date">
</div>
<div class="form-group col-md-4">
<label for="reminder_date">Reminder Date<span class="text-danger">*</span></label>
<input value="" type="text" class="form-control dateofdata"
placeholder="Enter Remainder Dates( eg, 28,29,30 )" name="reminder_date"
id="reminder_date">
</div>
</div> -->
<div class="form-group col-md-4">
<label for="reminder_date">Reminder Date<span class="text-danger">*</span></label>
<input value="" type="text" class="form-control dateofdata"
placeholder="Enter Remainder Dates( eg, 28,29,30 )" name="reminder_date"
id="reminder_date">
</div>
</div>
<div class="form-group col-md-12">
<label for="disclaimer">Disclaimer<span class="text-danger">*</span></label>
<textarea class="form-control" placeholder="Enter Disclaimer" name="disclaimer"
@ -389,6 +392,7 @@ input:checked + .slider:before {
</label>
Is LGBTQ Enable</label>
</div>
<div class="form-group col-md-4" style="padding-top:50px;padding-bottom: 0px;">
<label for="is_premium_summery" style=" position: relative;bottom: 5px;">
<label class="switch">
@ -625,9 +629,9 @@ $(document).ready(function() {
<! -- <td>${item.insurer_short} - ${item.insurer_branch_name}</td> -->
<td>${policy_name_data}</td>
<td>${item.branch_name ? item.branch_name : ' - '}</td>
<! -- <td>${tpaValue}</td> -->
<!-- <td>${tpaValue}</td> -->
<td>${(item.policy_start_date)} / ${(item.policy_end_date)}</td>
<td style="text-align: center;">${(enrollmentStatus)}</td>
<!-- <td style="text-align: center;">${(enrollmentStatus)}</td> -->
<td>${checkDateStatus(item.policy_end_date, 1)}</td>
<td>
<div class="btn-group dropdown">
@ -890,7 +894,7 @@ $("#policy_form").submit(function(event) {
<!-- <td>${tpaValue}</td> -->
<td>${(item.policy_start_date)} / ${(item.policy_end_date)}</td>
<td style="text-align: center;">${(enrollmentStatus)}</td>
<!-- <td style="text-align: center;">${(enrollmentStatus)}</td> -->
<td>${checkDateStatus(item.policy_end_date, 1)}</td>
<td>
<div class="btn-group dropdown">
@ -2433,7 +2437,7 @@ $(document).ready(function () {
<td>${item.branch_name ? item.branch_name : ' - '}</td>
<! -- <td>${tpaValue}</td> -->
<td>${(item.policy_start_date)} / ${(item.policy_end_date)}</td>
<td style="text-align: center;">${(enrollmentStatus)}</td>
<!-- <td style="text-align: center;">${(enrollmentStatus)}</td> -->
<td>${checkDateStatus(item.policy_end_date, 1)}</td>
<td>
<div class="btn-group dropdown">
@ -2470,7 +2474,7 @@ $(document).ready(function () {
<td>${item.branch_name ? item.branch_name : ' - '}</td>
<! -- <td>${tpaValue}</td> -->
<td>${(item.policy_start_date)} / ${(item.policy_end_date)}</td>
<td style="text-align: center;">${(enrollmentStatus)}</td>
<! -- <td style="text-align: center;">${(enrollmentStatus)}</td> -->
<td>${checkDateStatus(item.policy_end_date, 1)}</td>
<td>
<div class="btn-group dropdown">

View File

@ -71,6 +71,16 @@ option:disabled {
?>
</select>
</div>
<div class="form-group col-md-4">
<label for="open_date">Enrollment Open Date<span class="text-danger">*</span></label>
<input value="" type="text" class="form-control" placeholder="Enter Open Date " name="enrollment_open_date" id="enrollment_open_date" required>
</div>
<div class="form-group col-md-4">
<label for="close_date">Enrollment Close Date<span class="text-danger">*</span></label>
<input value="" type="text" class="form-control" placeholder="Enter Close Date " name="enrollment_close_date" id="enrollment_close_date" required>
</div>
</div>
<hr>
@ -180,6 +190,26 @@ $(document).ready(function() {
$("#policy_id").select2();
$("#branch_id").select2();
var enrollment_open_date = flatpickr("#enrollment_open_date", {
dateFormat: "d/m/Y",
allowInput: false,
minDate: "today",
onChange: function (selectedDates) {
if (selectedDates.length) {
enrollment_close_date.setDate(
new Date(selectedDates[0].getTime() + 15 * 24 * 60 * 60 * 1000),
true
);
}
}
});
var enrollment_close_date = flatpickr("#enrollment_close_date", {
dateFormat: "d/m/Y",
allowInput: false,
minDate: "today"
});
});
// Declare a global variable to store API response data
@ -541,6 +571,11 @@ function fetchFileError(file_id) {
"<strong>Rule conflict: Twofold relationship found within family</strong> <span class='badge badge-danger float-right'>" +
err_count + "</span>";
break;
case 26:
file_error_html +=
"<strong>Duplicate Employee code found</strong> <span class='badge badge-danger float-right'>" +
err_count + "</span>";
break;
default:
file_error_html += "";

View File

@ -44,8 +44,27 @@
// echo $reason;
?>
<tr>
<td><b><?php echo ($key + 1) ?></b></td>
<td class="reload truncate"
data-toggle="tooltip"
data-placement="top"
data-html="true"
title="<?php
echo 'Enrollment Open Date : ' .
(!empty($file['enrollment_open_date'])
? change_date_format($file['enrollment_open_date'], 'Y-m-d', 'd/m/Y')
: 'N/A'
) .
'<br>' .
'Enrollment Close Date : ' .
(!empty($file['enrollment_close_date'])
? change_date_format($file['enrollment_close_date'], 'Y-m-d', 'd/m/Y')
: 'N/A'
);
?>">
<b>
<?php echo ($key + 1) ?>
</b></td>
<td style="overflow: hidden;" class="reload truncate" data-toggle="tooltip" data-placement="top" title="<?php echo $file['file_name'] ?>">
<?php echo $file['file_name']?>
</td>
@ -53,7 +72,7 @@
<td><?php echo $file['branch_name'] ?></td>
<!-- <td><?php echo isset($file['policy_name']) ? $file['policy_name'] : '' ?> - <?php echo isset($file['policy_no']) ? $file['policy_no'] : '' ?> - <?php echo isset($file['policy_type']) ? $file['policy_type'] : '' ?></td> -->
<td><?php echo isset($file['policy_type']) ? $file['policy_type'] : '' ?> - <?php echo isset($file['policy_no']) ? $file['policy_no'] : '' ?></td>
<td><?php echo $file['action'] ?></td>
<td><?= $file['action'] == 'enrollment' ? 'Enrolment' : $file['action'] ?></td>
<td><?php echo change_date_format($file['created_at'],'Y-m-d H:i:s', 'd M Y h:i a') . ' by <strong>' . $file['first_name'] . '</strong>' ?>
</td>
<td>

View File

@ -250,7 +250,7 @@
<select id="member_welcome_mailmodal_customButton" class="form-control" style="border:none;right: 6px;width: auto;position: absolute;z-index: 1;top: 17px;height: 32px;float: right;" onchange="copyToClipboard(this)">
<option value="">PlaceHolders</option>
<?php foreach ($placeHolders as $value): ?>
<?php if ($value == 'member_name' || $value == 'nhance_logo' || $value == 'client_logo' || $value == 'app_link' || $value == 'client_name' || $value == 'member_summary') { ?>
<?php if ($value == 'member_name' || $value == 'nhance_logo' || $value == 'client_logo' || $value == 'app_link' || $value == 'client_name' || $value == 'member_summary' || $value == 'enrollment_open_date' || $value == 'enrollment_close_date') { ?>
<?php $valueChange = str_replace('_', ' ', $value);
$valueChange = ucwords($valueChange); ?>
<option value="{{<?php echo $value; ?>}}"><?php echo $valueChange; ?></option>

76
ca.pem Normal file
View File

@ -0,0 +1,76 @@
-----BEGIN CERTIFICATE-----
MIIEADCCAuigAwIBAgIQB/57HSuaqUkLaasdjxUdPjANBgkqhkiG9w0BAQsFADCB
mDELMAkGA1UEBhMCVVMxIjAgBgNVBAoMGUFtYXpvbiBXZWIgU2VydmljZXMsIElu
Yy4xEzARBgNVBAsMCkFtYXpvbiBSRFMxCzAJBgNVBAgMAldBMTEwLwYDVQQDDChB
bWF6b24gUkRTIGFwLXNvdXRoLTEgUm9vdCBDQSBSU0EyMDQ4IEcxMRAwDgYDVQQH
DAdTZWF0dGxlMCAXDTIxMDUxOTE3NDAzNFoYDzIwNjEwNTE5MTg0MDM0WjCBmDEL
MAkGA1UEBhMCVVMxIjAgBgNVBAoMGUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4x
EzARBgNVBAsMCkFtYXpvbiBSRFMxCzAJBgNVBAgMAldBMTEwLwYDVQQDDChBbWF6
b24gUkRTIGFwLXNvdXRoLTEgUm9vdCBDQSBSU0EyMDQ4IEcxMRAwDgYDVQQHDAdT
ZWF0dGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtbkaoVsUS76o
TgLFmcnaB8cswBk1M3Bf4IVRcwWT3a1HeJSnaJUqWHCJ+u3ip/zGVOYl0gN1MgBb
MuQRIJiB95zGVcIa6HZtx00VezDTr3jgGWRHmRjNVCCHGmxOZWvJjsIE1xavT/1j
QYV/ph4EZEIZ/qPq7e3rHohJaHDe23Z7QM9kbyqp2hANG2JtU/iUhCxqgqUHNozV
Zd0l5K6KnltZQoBhhekKgyiHqdTrH8fWajYl5seD71bs0Axowb+Oh0rwmrws3Db2
Dh+oc2PwREnjHeca9/1C6J2vhY+V0LGaJmnnIuOANrslx2+bgMlyhf9j0Bv8AwSi
dSWsobOhNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQb7vJT
VciLN72yJGhaRKLn6Krn2TAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQAD
ggEBAAxEj8N9GslReAQnNOBpGl8SLgCMTejQ6AW/bapQvzxrZrfVOZOYwp/5oV0f
9S1jcGysDM+DrmfUJNzWxq2Y586R94WtpH4UpJDGqZp+FuOVJL313te4609kopzO
lDdmd+8z61+0Au93wB1rMiEfnIMkOEyt7D2eTFJfJRKNmnPrd8RjimRDlFgcLWJA
3E8wca67Lz/G0eAeLhRHIXv429y8RRXDtKNNz0wA2RwURWIxyPjn1fHjA9SPDkeW
E1Bq7gZj+tBnrqz+ra3yjZ2blss6Ds3/uRY6NYqseFTZWmQWT7FolZEnT9vMUitW
I0VynUbShVpGf6946e0vgaaKw20=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIICrjCCAjWgAwIBAgIQGKVv+5VuzEZEBzJ+bVfx2zAKBggqhkjOPQQDAzCBlzEL
MAkGA1UEBhMCVVMxIjAgBgNVBAoMGUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4x
EzARBgNVBAsMCkFtYXpvbiBSRFMxCzAJBgNVBAgMAldBMTAwLgYDVQQDDCdBbWF6
b24gUkRTIGFwLXNvdXRoLTEgUm9vdCBDQSBFQ0MzODQgRzExEDAOBgNVBAcMB1Nl
YXR0bGUwIBcNMjEwNTE5MTc1MDU5WhgPMjEyMTA1MTkxODUwNTlaMIGXMQswCQYD
VQQGEwJVUzEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNlcywgSW5jLjETMBEG
A1UECwwKQW1hem9uIFJEUzELMAkGA1UECAwCV0ExMDAuBgNVBAMMJ0FtYXpvbiBS
RFMgYXAtc291dGgtMSBSb290IENBIEVDQzM4NCBHMTEQMA4GA1UEBwwHU2VhdHRs
ZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMqdLJ0tZF/DGFZTKZDrGRJZID8ivC2I
JRCYTWweZKCKSCAzoiuGGHzJhr5RlLHQf/QgmFcgXsdmO2n3CggzhA4tOD9Ip7Lk
P05eHd2UPInyPCHRgmGjGb0Z+RdQ6zkitKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAd
BgNVHQ4EFgQUC1yhRgVqU5bR8cGzOUCIxRpl4EYwDgYDVR0PAQH/BAQDAgGGMAoG
CCqGSM49BAMDA2cAMGQCMG0c/zLGECRPzGKJvYCkpFTCUvdP4J74YP0v/dPvKojL
t/BrR1Tg4xlfhaib7hPc7wIwFvgqHes20CubQnZmswbTKLUrgSUW4/lcKFpouFd2
t2/ewfi/0VhkeUW+IiHhOMdU
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIGATCCA+mgAwIBAgIRAKlQ+3JX9yHXyjP/Ja6kZhkwDQYJKoZIhvcNAQEMBQAw
gZgxCzAJBgNVBAYTAlVTMSIwIAYDVQQKDBlBbWF6b24gV2ViIFNlcnZpY2VzLCBJ
bmMuMRMwEQYDVQQLDApBbWF6b24gUkRTMQswCQYDVQQIDAJXQTExMC8GA1UEAwwo
QW1hem9uIFJEUyBhcC1zb3V0aC0xIFJvb3QgQ0EgUlNBNDA5NiBHMTEQMA4GA1UE
BwwHU2VhdHRsZTAgFw0yMTA1MTkxNzQ1MjBaGA8yMTIxMDUxOTE4NDUyMFowgZgx
CzAJBgNVBAYTAlVTMSIwIAYDVQQKDBlBbWF6b24gV2ViIFNlcnZpY2VzLCBJbmMu
MRMwEQYDVQQLDApBbWF6b24gUkRTMQswCQYDVQQIDAJXQTExMC8GA1UEAwwoQW1h
em9uIFJEUyBhcC1zb3V0aC0xIFJvb3QgQ0EgUlNBNDA5NiBHMTEQMA4GA1UEBwwH
U2VhdHRsZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKtahBrpUjQ6
H2mni05BAKU6Z5USPZeSKmBBJN3YgD17rJ93ikJxSgzJ+CupGy5rvYQ0xznJyiV0
91QeQN4P+G2MjGQR0RGeUuZcfcZitJro7iAg3UBvw8WIGkcDUg+MGVpRv/B7ry88
7E4OxKb8CPNoa+a9j6ABjOaaxaI22Bb7j3OJ+JyMICs6CU2bgkJaj3VUV9FCNUOc
h9PxD4jzT9yyGYm/sK9BAT1WOTPG8XQUkpcFqy/IerZDfiQkf1koiSd4s5VhBkUn
aQHOdri/stldT7a+HJFVyz2AXDGPDj+UBMOuLq0K6GAT6ThpkXCb2RIf4mdTy7ox
N5BaJ+ih+Ro3ZwPkok60egnt/RN98jgbm+WstgjJWuLqSNInnMUgkuqjyBWwePqX
Kib+wdpyx/LOzhKPEFpeMIvHQ3A0sjlulIjnh+j+itezD+dp0UNxMERlW4Bn/IlS
sYQVNfYutWkRPRLErXOZXtlxxkI98JWQtLjvGzQr+jywxTiw644FSLWdhKa6DtfU
2JWBHqQPJicMElfZpmfaHZjtXuCZNdZQXWg7onZYohe281ZrdFPOqC4rUq7gYamL
T+ZB+2P+YCPOLJ60bj/XSvcB7mesAdg8P0DNddPhHUFWx2dFqOs1HxIVB4FZVA9U
Ppbv4a484yxjTgG7zFZNqXHKTqze6rBBAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB
Af8wHQYDVR0OBBYEFCEAqjighncv/UnWzBjqu1Ka2Yb4MA4GA1UdDwEB/wQEAwIB
hjANBgkqhkiG9w0BAQwFAAOCAgEAYyvumblckIXlohzi3QiShkZhqFzZultbFIu9
GhA5CDar1IFMhJ9vJpO9nUK/camKs1VQRs8ZsBbXa0GFUM2p8y2cgUfLwFULAiC/
sWETyW5lcX/xc4Pyf6dONhqFJt/ovVBxNZtcmMEWv/1D6Tf0nLeEb0P2i/pnSRR4
Oq99LVFjossXtyvtaq06OSiUUZ1zLPvV6AQINg8dWeBOWRcQYhYcEcC2wQ06KShZ
0ahuu7ar5Gym3vuLK6nH+eQrkUievVomN/LpASrYhK32joQ5ypIJej3sICIgJUEP
UoeswJ+Z16f3ECoL1OSnq4A0riiLj1ZGmVHNhM6m/gotKaHNMxsK9zsbqmuU6IT/
P6cR0S+vdigQG8ZNFf5vEyVNXhl8KcaJn6lMD/gMB2rY0qpaeTg4gPfU5wcg8S4Y
C9V//tw3hv0f2n+8kGNmqZrylOQDQWSSo8j8M2SRSXiwOHDoTASd1fyBEIqBAwzn
LvXVg8wQd1WlmM3b0Vrsbzltyh6y4SuKSkmgufYYvC07NknQO5vqvZcNoYbLNea3
76NkFaMHUekSbwVejZgG5HGwbaYBgNdJEdpbWlA3X4yGRVxknQSUyt4dZRnw/HrX
k8x6/wvtw7wht0/DOqz1li7baSsMazqxx+jDdSr1h9xML416Q4loFCLgqQhil8Jq
Em4Hy3A=
-----END CERTIFICATE-----