Merge branch 'main' of bitbucket.org:venbaittech/tstat_be
This commit is contained in:
commit
abfe5660a7
9
.gitignore
vendored
9
.gitignore
vendored
@ -10,3 +10,12 @@
|
||||
# Ignore env File here
|
||||
.env
|
||||
|
||||
/writable/pdf/forex/*
|
||||
/writable/pdf/trips/*
|
||||
/writable/uploads/logo/*
|
||||
/writable/uploads/passport/*
|
||||
/writable/uploads/signature/*
|
||||
/writable/uploads/template/*
|
||||
|
||||
|
||||
/public/assets/images/signature/*
|
||||
|
||||
@ -14,6 +14,7 @@ use CodeIgniter\Filters\PerformanceMetrics;
|
||||
use CodeIgniter\Filters\SecureHeaders;
|
||||
use App\Filters\JwtAuthFilter;
|
||||
use App\Filters\SignedUrlFilter;
|
||||
use App\Filters\VerifyAppSignature;
|
||||
class Filters extends BaseFilters
|
||||
{
|
||||
/**
|
||||
@ -35,8 +36,9 @@ class Filters extends BaseFilters
|
||||
'forcehttps' => ForceHTTPS::class,
|
||||
'pagecache' => PageCache::class,
|
||||
'performance' => PerformanceMetrics::class,
|
||||
'jwtAuth' => JwtAuthFilter::class,
|
||||
'signedUrl' => SignedUrlFilter::class,
|
||||
'jwtAuth' => JwtAuthFilter::class,
|
||||
'signedUrl' => SignedUrlFilter::class,
|
||||
'appSignature' => VerifyAppSignature::class,
|
||||
];
|
||||
|
||||
|
||||
|
||||
@ -16,21 +16,39 @@ $routes->post('acs', 'SamlController::acs');
|
||||
$routes->post('logout', 'SamlController::slo');
|
||||
$routes->get('metadata', 'SamlController::metadata');
|
||||
|
||||
$routes->get('auth/msRedirectionHandler', 'AuthController::msRedirectionHandler');
|
||||
|
||||
//login api
|
||||
$routes->group('api', ['filter' => 'appSignature'], function ($routes) {
|
||||
|
||||
// Login api
|
||||
$routes->post('auth/login', 'AuthController::login');
|
||||
$routes->get('auth/oauthClient', 'AuthController::oauthClient');
|
||||
$routes->post('auth/oauthlogin', 'AuthController::oauthlogin');
|
||||
$routes->get('auth/msRedirectionHandler', 'AuthController::msRedirectionHandler');
|
||||
|
||||
|
||||
// MS OAuth api's
|
||||
$routes->get('auth/mslogin', 'AuthController::mslogin');
|
||||
$routes->get('auth/verifyMSAuthUser', 'AuthController::verifyMSAuthUser');
|
||||
|
||||
// Google OAuth api's
|
||||
$routes->get('googleoauth', 'AuthController::receiveGoogleOAuthResponse');
|
||||
$routes->get('auth/googlelogin', 'AuthController::initiateGoogleOAuth');
|
||||
$routes->get('logout', 'AuthController::logout');
|
||||
|
||||
//forgot password
|
||||
$routes->post('forgotPassword/verifyUser', 'UserController::verifyUser');
|
||||
$routes->post('forgotPassword/changePassword', 'UserController::forgotChangePassword');
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//api's with token
|
||||
$routes->group('api', ['filter' => 'jwtAuth'], function ($routes) {
|
||||
$routes->group('api', ['filter' => ["jwtAuth","appSignature"] ], function ($routes) {
|
||||
|
||||
$routes->get('user/refreshUserToken', 'AuthController::refreshUserToken');
|
||||
|
||||
|
||||
//Organization
|
||||
@ -97,8 +115,8 @@ $routes->post('forgotPassword/changePassword', 'UserController::forgotChangePass
|
||||
$routes->get('plans/forexDownload', 'PlanController::forexDownload');
|
||||
$routes->get('plans/cancle_plan', 'PlanController::canclePlan');
|
||||
$routes->get('plans/get_plan_approval_status', 'PlanController::get_plan_approval_status');
|
||||
|
||||
$routes->get('plans/plan_pdf', 'PlanController::plan_pdf');
|
||||
$routes->get('plans/plan_policy_action_status', 'PlanController::plan_policy_action_status');
|
||||
|
||||
//Master
|
||||
$routes->get('getDropdownMaster', 'MasterController::getDropdownMaster');
|
||||
@ -128,6 +146,8 @@ $routes->post('forgotPassword/changePassword', 'UserController::forgotChangePass
|
||||
$routes->post('createForexPerdiem', 'MasterController::createForexPerdiem');
|
||||
$routes->get('findForexPerdiem', 'MasterController::findForexPerdiem');
|
||||
$routes->put('updateForexPerdiem/(:num)', 'MasterController::updateForexPerdiem/$1');
|
||||
$routes->post('forex_signature_upload', 'MasterController::forex_signature_upload');
|
||||
$routes->get('getForexSignaturePath', 'MasterController::getForexSignaturePath');
|
||||
// Hotels Master
|
||||
$routes->get('getHotels', 'MasterController::getHotels');
|
||||
$routes->post('createHotels', 'MasterController::createHotels');
|
||||
@ -163,15 +183,9 @@ $routes->get('review', 'PlanController::protectedPage', ['filter' => 'signedUrl'
|
||||
$routes->get('url', 'PlanController::url');
|
||||
|
||||
|
||||
// MS OAuth api's
|
||||
$routes->get('auth/mslogin', 'AuthController::mslogin');
|
||||
$routes->get('auth/verifyMSAuthUser', 'AuthController::verifyMSAuthUser');
|
||||
|
||||
|
||||
|
||||
$routes->get('googleoauth', 'AuthController::receiveGoogleOAuthResponse');
|
||||
$routes->get('auth/googlelogin', 'AuthController::initiateGoogleOAuth');
|
||||
$routes->get('logout', 'AuthController::logout');
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -324,5 +324,48 @@ class AuthController extends ResourceController
|
||||
}
|
||||
|
||||
|
||||
//re-Fetch token
|
||||
|
||||
public function refreshUserToken()
|
||||
{
|
||||
|
||||
|
||||
$user_id = $this->request->getGet();
|
||||
$user = $this->userModel->where('user_id', $user_id)->where('is_active',1)->first();
|
||||
// print_r($user);die;
|
||||
if (!$user) {
|
||||
return $this->failUnauthorized('Invalid User');
|
||||
}
|
||||
|
||||
|
||||
//get service for the organization
|
||||
$orgService = $this->organizationModel->find($user['org_id']);
|
||||
$user['service'] = json_decode($orgService['services_ids'],true);
|
||||
foreach ($user['service'] as $key => $value)
|
||||
{
|
||||
$serviceData = $this->serviceModel->find($value['service_id']);
|
||||
$user['service'][$key]['name'] = $serviceData['name'];
|
||||
$user['service'][$key]['icon'] = $serviceData['icon'];
|
||||
$user['service'][$key]['order'] = $serviceData['order'];
|
||||
}
|
||||
|
||||
//get role
|
||||
$user['role'] = $this->userModel->getRole($user['role_id']);
|
||||
|
||||
//find user has the all access
|
||||
$user['plan_action'] = getUserPlanCreationRestrictionStatus($user);
|
||||
|
||||
// Generate JWT Token
|
||||
$token = generateJWT($user);
|
||||
|
||||
|
||||
return $this->respond([
|
||||
'status' => 200,
|
||||
'message' => 'Login successful',
|
||||
'token' => $token
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ use App\Models\ForexPerdiemModel;
|
||||
use App\Models\HotelModel;
|
||||
use App\Models\CostCenterModel;
|
||||
use App\Models\AirlineModel;
|
||||
use App\Models\MailTemplateModel;
|
||||
|
||||
class MasterController extends ResourceController
|
||||
{
|
||||
@ -40,6 +41,7 @@ class MasterController extends ResourceController
|
||||
protected $hotelModel;
|
||||
protected $costCenterModel;
|
||||
protected $airlineModel;
|
||||
protected $mailTemplateModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
@ -60,6 +62,7 @@ class MasterController extends ResourceController
|
||||
$this->hotelModel = new HotelModel();
|
||||
$this->costCenterModel = new CostCenterModel();
|
||||
$this->airlineModel = new AirlineModel();
|
||||
$this->mailTemplateModel = new MailTemplateModel();
|
||||
}
|
||||
|
||||
|
||||
@ -162,20 +165,27 @@ class MasterController extends ResourceController
|
||||
$user_id = $this->request->getVar('user_id');
|
||||
|
||||
$user = $this->userModel->where('user_id', $user_id)->first();
|
||||
|
||||
$groupData = $this->groupModel->find($user['group_id']);
|
||||
|
||||
if($groupData)
|
||||
{
|
||||
if($trip_type == 1) { $policyId = $groupData['domestic_policy_id'];}else{ $policyId = $groupData['international_policy_id'];}
|
||||
// dd($policyId);
|
||||
if($policyId != null)
|
||||
{
|
||||
$minFlightClassKey = $this->policyDetailsModel->where('policy_id',$policyId)->where('service_id',1)->get()->getRow()->class;
|
||||
$minTrainClassKey = $this->policyDetailsModel->where('policy_id',$policyId)->where('service_id',2)->get()->getRow()->class;
|
||||
$minHotelClassKey = $this->policyDetailsModel->where('policy_id',$policyId)->where('service_id',5)->get()->getRow()->class;
|
||||
$minFlightRow = $this->policyDetailsModel->where('policy_id', $policyId)->where('service_id', 1)->get()->getRow();
|
||||
|
||||
$minTrainRow = $this->policyDetailsModel->where('policy_id', $policyId)->where('service_id', 2)->get()->getRow();
|
||||
|
||||
$minHotelRow = $this->policyDetailsModel->where('policy_id', $policyId)->where('service_id', 5)->get()->getRow();
|
||||
|
||||
$minFlightClassKey = $minFlightRow ? $minFlightRow->class : null;
|
||||
$minTrainClassKey = $minTrainRow ? $minTrainRow->class : null;
|
||||
$minHotelClassKey = $minHotelRow ? $minHotelRow->class : null;
|
||||
|
||||
}
|
||||
// echo "Flight 3 but ".$minFlightClassKey; //3
|
||||
// echo "\n train 1 but ".$minTrainClassKey; //1
|
||||
// echo "\n hotel 5 but ".$minHotelClassKey; //5
|
||||
// die;
|
||||
|
||||
|
||||
//flight
|
||||
$allFlightClass = $this->dropdownModel->where('dropdown', 'flight_class')->orderBy('dropdown_key','ASC')->findAll();
|
||||
@ -624,6 +634,90 @@ class MasterController extends ResourceController
|
||||
}
|
||||
|
||||
|
||||
public function forex_signature_upload()
|
||||
{
|
||||
|
||||
$data = $this->request->getPost();
|
||||
|
||||
// Handle file upload
|
||||
$file = $this->request->getFile('signature');
|
||||
if ($file && $file->isValid() && !$file->hasMoved()) {
|
||||
$newName = $file->getRandomName(); // Generate a unique name
|
||||
// $uploadPath = WRITEPATH.'uploads/signature';
|
||||
$uploadPath = FCPATH.'public/assets/images/signature';
|
||||
|
||||
// print_r( $uploadPath); die;
|
||||
|
||||
// Move file to the specified directory
|
||||
$file->move($uploadPath, $newName);
|
||||
|
||||
// Save file path in database
|
||||
$path = $uploadPath . '/' . $newName;
|
||||
} else {
|
||||
return $this->failValidationErrors(['passport_document' => 'Invalid file upload']);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
$this->mailTemplateModel->set(['image_location' => $newName])->where('template_name','forex')->update();
|
||||
|
||||
|
||||
return $this->respondCreated([
|
||||
'status' => 201,
|
||||
'message' => 'organization created successfully',
|
||||
'data' => $data
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return $this->failServerError('Failed to create organization: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// public function getForexSignaturePath()
|
||||
// {
|
||||
|
||||
// $data = $this->mailTemplateModel->where('template_name','forex')->first();
|
||||
|
||||
// return $this->respond([
|
||||
// 'status' => 200,
|
||||
// 'message' => 'success',
|
||||
// 'data' => $data
|
||||
|
||||
// ]);
|
||||
|
||||
// }
|
||||
|
||||
public function getForexSignaturePath()
|
||||
{
|
||||
$data = $this->mailTemplateModel->where('template_name', 'forex')->first();
|
||||
|
||||
if (!$data || empty($data['image_location'])) {
|
||||
return $this->respond([
|
||||
'status' => 404,
|
||||
'message' => 'Image not found',
|
||||
'url' => null
|
||||
]);
|
||||
}
|
||||
|
||||
// If the DB stores only the filename, adjust accordingly
|
||||
$fileName = basename($data['image_location']);
|
||||
|
||||
|
||||
$imageUrl = base_url('public/assets/images/signature/' . $fileName);
|
||||
|
||||
// Add both the URL and ready-made HTML tag
|
||||
$data['image_url'] = $imageUrl;
|
||||
$data['image_tag'] = '<img src="' . $imageUrl . '" alt="Signature" style="max-width:200px;">';
|
||||
|
||||
return $this->respond([
|
||||
'status' => 200,
|
||||
'message' => 'success',
|
||||
'url' => $imageUrl
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -112,8 +112,9 @@ class PlanController extends ResourceController
|
||||
$a1Data = $this->planStatusModel->select('plan_id')->where('a1_id',$user_id)->where('a1_action','Approval')->where('is_active',1)->findAll();
|
||||
$a2Data = $this->planStatusModel->select('plan_id')->where('a2_id',$user_id)->where('a2_action','Approval')->where('is_active',1)->findAll();
|
||||
$a3Data = $this->planStatusModel->select('plan_id')->where('a3_id',$user_id)->where('a3_action','Approval')->where('is_active',1)->findAll();
|
||||
$a4Data = $this->planStatusModel->select('plan_id')->where('a4_id',$user_id)->where('a4_action','Approval')->where('is_active',1)->findAll();
|
||||
|
||||
$mergedArray = array_merge($a1Data, $a2Data, $a3Data);
|
||||
$mergedArray = array_merge($a1Data, $a2Data, $a3Data, $a4Data);
|
||||
$planIds = array_unique(array_column($mergedArray, "plan_id"));
|
||||
$plans = [];
|
||||
if (count($planIds)) {
|
||||
@ -514,6 +515,12 @@ class PlanController extends ResourceController
|
||||
sendPlanUpdationMail($planId);
|
||||
}
|
||||
|
||||
// Send mail to agent if plan status is 3
|
||||
$plan = $this->planModel->where('plan_id', $planId)->where('status', 3)->first();
|
||||
if ($plan) {
|
||||
send_email_agent(env('ORG_id'), $planId);
|
||||
}
|
||||
|
||||
return $this->respond(['status' => 'success', 'plan_id' => $planId]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
@ -775,15 +782,27 @@ class PlanController extends ResourceController
|
||||
$status = true;
|
||||
}
|
||||
|
||||
//approver 4
|
||||
$a4Data = $this->planStatusModel->where('plan_id',$plan_id)->where('a4_id',$user_id)->where('a4_action','Approval')->where('is_active',1)->findAll();
|
||||
if($a4Data){
|
||||
$this->planStatusModel->set(['is_a4_action_done'=>1,'a4_action_done_on'=>date('Y-m-d H:i:s'),'a4_reject_reason'=>null,'a4_action_done_by'=>$actionDoneBy])
|
||||
->where('plan_id',$plan_id)
|
||||
->where('a4_id',$user_id)
|
||||
->where('a4_action','Approval')
|
||||
->where('is_active',1)
|
||||
->update();
|
||||
$status = true;
|
||||
}
|
||||
|
||||
|
||||
//response
|
||||
if($status)
|
||||
{
|
||||
//update pdf content
|
||||
$this->generatePlanPdf($plan_id);
|
||||
|
||||
//update plan status
|
||||
updatePlanStatus($plan_id);
|
||||
|
||||
//update pdf content
|
||||
$this->generatePlanPdf($plan_id);
|
||||
|
||||
//send approval mail
|
||||
sendPlanApprovalOrRejectMail($plan_id,'A');
|
||||
@ -791,6 +810,13 @@ class PlanController extends ResourceController
|
||||
//send parallel or Sequential mail
|
||||
sendPlanCreationMail($plan_id, 'send_mail_to_only_approver');
|
||||
|
||||
// Send mail to agent if plan status is 3
|
||||
$plan = $this->planModel->where('plan_id', $plan_id)->where('status', 3)->first();
|
||||
if ($plan) {
|
||||
send_email_agent(env('ORG_id'), $plan_id);
|
||||
}
|
||||
|
||||
|
||||
return $this->respond(['status' => 200, 'message' => 'success' ]);
|
||||
}else{
|
||||
return $this->respond(['status' => 404, 'message' => 'failed' ]);
|
||||
@ -859,6 +885,18 @@ class PlanController extends ResourceController
|
||||
$status = true;
|
||||
}
|
||||
|
||||
//approver 4
|
||||
$a4Data = $this->planStatusModel->where('plan_id',$plan_id)->where('a4_id',$user_id)->where('a4_action','Approval')->where('is_active',1)->findAll();
|
||||
if($a4Data){
|
||||
$this->planStatusModel->set(['is_a4_action_done'=>0, 'a4_reject_reason'=>$reason, 'a4_action_done_on'=>date('Y-m-d H:i:s'),'a4_action_done_by'=>$actionDoneBy])
|
||||
->where('plan_id',$plan_id)
|
||||
->where('a4_id',$user_id)
|
||||
->where('a4_action','Approval')
|
||||
->where('is_active',1)
|
||||
->update();
|
||||
$status = true;
|
||||
}
|
||||
|
||||
|
||||
//response
|
||||
if($status)
|
||||
@ -980,8 +1018,11 @@ class PlanController extends ResourceController
|
||||
|
||||
$todayStart = date('Y-m-d 00:00:00');
|
||||
$todayEnd = date('Y-m-d 23:59:59');
|
||||
$startOfWeek = date('Y-m-d 00:00:00', strtotime('monday this week'));
|
||||
$endOfWeek = date('Y-m-d 23:59:59', strtotime('sunday this week'));
|
||||
// $startOfWeek = date('Y-m-d 00:00:00', strtotime('monday this week'));
|
||||
// $endOfWeek = date('Y-m-d 23:59:59', strtotime('sunday this week'));
|
||||
$startOfWeek = date('Y-m-d 00:00:00', strtotime('-7 days'));
|
||||
$endOfWeek = date('Y-m-d 23:59:59'); // today
|
||||
|
||||
|
||||
$typeResultToday = [];
|
||||
$typeResultWeekly = [];
|
||||
@ -1177,7 +1218,7 @@ class PlanController extends ResourceController
|
||||
$plan['flight'] = $flights;
|
||||
|
||||
//get accomodation details
|
||||
$plan['accomodation'] = $this->accomodationModel->select('c_accomodation.* , C.dropdown_value as hotel_class')
|
||||
$plan['accomodation'] = $this->accomodationModel->select('c_accomodation.*, C.dropdown_value as hotel_class')
|
||||
->join('m_dropdown C', 'C.dropdown_key = c_accomodation.class AND C.dropdown = "hotel_class"', 'left')
|
||||
->where('c_accomodation.plan_id', $planId)
|
||||
->where('c_accomodation.is_active', 1)->findAll();
|
||||
@ -1240,6 +1281,11 @@ class PlanController extends ResourceController
|
||||
|
||||
$userId = $plan['user_id'] ?? $plan['traveller_id'];
|
||||
|
||||
//current plan status
|
||||
$status = getCurrentPlanStatus($planId);
|
||||
|
||||
$plan['status_details'] = $status;
|
||||
|
||||
//get user data
|
||||
$plan['user_data'] = $this->userModel->where('user_id', $userId)->first();
|
||||
$plan['view'] = $view;
|
||||
@ -1304,7 +1350,13 @@ class PlanController extends ResourceController
|
||||
->where('c_forex.forex_id', $forexId)->where('c_forex.is_active', 1)
|
||||
->first();
|
||||
$data['org_data'] = $this->organizationModel->where('org_id', $data['forexData']['org_id'])->where('is_active', 1)->first();
|
||||
$templateData = $this->mailTemplateModel->where('org_id', $data['forexData']['org_id'] )->where('template_name', 'forex' )->first();
|
||||
|
||||
|
||||
//placeholder data
|
||||
$logoFilename = basename($data['org_data']['logo']);
|
||||
$logo = base_url("assets/images/logo/" . $logoFilename);
|
||||
$data['forexData']['org_logo'] = '<img src="' . $logo . '" alt="org_logo" style="max-width:100px; max-height:100px;">';
|
||||
$data['forexData']['org_name'] = $data['org_data']['name'];
|
||||
$data['forexData']['forex_card_number'] = $data['forexData']['card_number'];
|
||||
$data['forexData']['passport_place_of_issue'] = $data['forexData']['place_of_issue'];
|
||||
@ -1314,9 +1366,9 @@ class PlanController extends ResourceController
|
||||
$data['forexData']['place_of_visit'] = $data['forexData']['country_name'];
|
||||
$data['forexData']['staying_duration'] = $data['forexData']['duration'];
|
||||
$data['forexData']['total_forex_exchange_amount'] = $data['forexData']['perdiem_amount'] + $data['forexData']['transport'] + $data['forexData']['accommodation'] + $data['forexData']['telephone'];
|
||||
|
||||
|
||||
$templateData = $this->mailTemplateModel->where('org_id', $data['forexData']['org_id'] )->where('template_name', 'forex' )->first();
|
||||
$signatuteFileName = basename($templateData['image_location']);
|
||||
$imageUrl = base_url('public/assets/images/signature/' . $signatuteFileName);
|
||||
$data['forexData']['signature_image'] = '<img src="' . $imageUrl . '" alt="Signature" style="max-width:250px;">';
|
||||
|
||||
//replace the placeholder
|
||||
foreach ($data['forexData'] as $key => $value) {
|
||||
@ -1324,6 +1376,8 @@ class PlanController extends ResourceController
|
||||
$templateData['body_html'] = str_replace($placeHolder, $value ?? '', $templateData['body_html']);
|
||||
}
|
||||
$html = $templateData['body_html'];
|
||||
|
||||
// echo $html; die;
|
||||
|
||||
// $html = view('forex',$data);
|
||||
|
||||
@ -1432,16 +1486,26 @@ class PlanController extends ResourceController
|
||||
|
||||
public function url()
|
||||
{
|
||||
// echo '<pre>';
|
||||
// $user = $this->userModel->where('email', 'pavithrakavi1100@gmail.com')->first();
|
||||
// echo getUserPlanCreationRestrictionStatus($user); die;
|
||||
// print_r(getPlanApproverAction(126)); die;
|
||||
|
||||
return $this->generatePlanPdf(136, true);
|
||||
die;
|
||||
|
||||
updatePlanStatus(57); die;
|
||||
palnStatusHandler(57, false); die;
|
||||
|
||||
|
||||
echo '<pre>';
|
||||
// sendPlanCreationMail(23);
|
||||
print_r(getPlanApproverAction(32)); die;
|
||||
// sendPlanCreationMail(39);
|
||||
|
||||
|
||||
// echo '<pre>';
|
||||
// print_r(getAllowedClassForUser(2,4)['hotel']); die;
|
||||
|
||||
return $this->generatePlanPdf(53, true);
|
||||
die;
|
||||
|
||||
|
||||
return send_email_agent(env('ORG_id') , 62);
|
||||
return updatePlanStatus(62);
|
||||
@ -1526,6 +1590,65 @@ class PlanController extends ResourceController
|
||||
}
|
||||
|
||||
|
||||
public function plan_policy_action_status()
|
||||
{
|
||||
$plan_id = $this->request->getGet('plan_id') ?? null;
|
||||
|
||||
|
||||
$planData = $this->planStatusModel->select('c_plan_status.* ,CONCAT_WS(a1.first_name," ",a1.last_name) as a1_user_name,CONCAT_WS(a2.first_name," ",a2.last_name) as a2_user_name,CONCAT_WS(a3.first_name," ",a3.last_name) as a3_user_name,CONCAT_WS(a4.first_name," ",a4.last_name) as a4_user_name')
|
||||
->join('m_users a1', 'a1.user_id = c_plan_status.a1_id ', 'left')
|
||||
->join('m_users a2', 'a2.user_id = c_plan_status.a2_id ', 'left')
|
||||
->join('m_users a3', 'a3.user_id = c_plan_status.a3_id ', 'left')
|
||||
->join('m_users a4', 'a4.user_id = c_plan_status.a4_id ', 'left')
|
||||
->where('c_plan_status.plan_id', $plan_id)
|
||||
->where('c_plan_status.is_active', 1)
|
||||
->first();
|
||||
|
||||
$data = [];
|
||||
|
||||
if($planData){
|
||||
|
||||
$a1 = [
|
||||
"action" => $planData['a1_action'],
|
||||
"approver" => $planData['a1_user_name'],
|
||||
"is_action_done" => $planData['is_a1_action_done'] == 1 ? 'Done' : 'Not Done',
|
||||
"action_on" => $planData['is_a1_action_done'] == 1 ? $planData['a1_action_done_on'] : '-'
|
||||
];
|
||||
if($planData['a1_action'] != 'None'){ array_push($data, $a1); }
|
||||
|
||||
$a2 = [
|
||||
"action" => $planData['a2_action'],
|
||||
"approver" => $planData['a2_user_name'],
|
||||
"is_action_done" => $planData['is_a2_action_done'] == 1 ? 'Done' : 'Not Done',
|
||||
"action_on" => $planData['is_a2_action_done'] == 1 ? $planData['a2_action_done_on'] : '-'
|
||||
];
|
||||
if($planData['a2_action'] != 'None'){ array_push($data, $a2); }
|
||||
|
||||
$a3 = [
|
||||
"action" => $planData['a3_action'],
|
||||
"approver" => $planData['a3_user_name'],
|
||||
"is_action_done" => $planData['is_a3_action_done'] == 1 ? 'Done' : 'Not Done',
|
||||
"action_on" => $planData['is_a3_action_done'] == 1 ? $planData['a3_action_done_on'] : '-'
|
||||
];
|
||||
if($planData['a3_action'] != 'None'){ array_push($data, $a3); }
|
||||
|
||||
$a4 = [
|
||||
"action" => $planData['a4_action'],
|
||||
"approver" => $planData['a4_user_name'],
|
||||
"is_action_done" => $planData['is_a4_action_done'] == 1 ? 'Done' : 'Not Done',
|
||||
"action_on" => $planData['is_a4_action_done'] == 1 ? $planData['a4_action_done_on'] : '-'
|
||||
];
|
||||
if($planData['a4_action'] != 'None'){ array_push($data, $a4); }
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return $this->respond(['status' => 200, 'message' => 'success', 'data' => $data ]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -656,7 +656,7 @@ public function userUpload()
|
||||
{
|
||||
|
||||
$predefinedHeaders = ['First Name', 'Last Name', 'Email', 'Mobile Number', 'Password' , 'Role' ,'Employee Code','Group Name',
|
||||
'First Approver Email','Second Approver Email','Third Approver Email','Exceptional Approver Email'];
|
||||
'First Approver Email','Second Approver Email','Third Approver Email','Fourth Approver Email'];
|
||||
|
||||
$uploadDir = WRITEPATH . 'uploads/userUploadFiles/';
|
||||
|
||||
@ -728,7 +728,7 @@ public function userUpload()
|
||||
$insertUsers = [];
|
||||
|
||||
$dbHeaders = ['first_name','last_name','email','mobile_no','password','role_id','employee_code','group_id',
|
||||
'first_approver_email','second_approver_email','third_approver_email','exceptional_approver_email'];
|
||||
'first_approver_email','second_approver_email','third_approver_email','fourth_approver_email'];
|
||||
|
||||
$rolesList = $this->userModel->getRolesList();
|
||||
|
||||
@ -781,9 +781,9 @@ public function userUpload()
|
||||
}
|
||||
|
||||
|
||||
if (!empty($user['exceptional_approver_email']) && !filter_var($user['exceptional_approver_email'], FILTER_VALIDATE_EMAIL)) {
|
||||
if (!empty($user['fourth_approver_email']) && !filter_var($user['fourth_approver_email'], FILTER_VALIDATE_EMAIL)) {
|
||||
$fail++;
|
||||
$failedUsers[] = ['data' => $user['first_name'].' '.$user['last_name'], 'reason' => 'Invalid exceptional_approver_email format' ];
|
||||
$failedUsers[] = ['data' => $user['first_name'].' '.$user['last_name'], 'reason' => 'Invalid fourth_approver_email format' ];
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -799,7 +799,7 @@ public function userUpload()
|
||||
$user['first_approver_email'] = filter_var($user['first_approver_email'], FILTER_SANITIZE_EMAIL);
|
||||
$user['second_approver_email'] = filter_var($user['second_approver_email'], FILTER_SANITIZE_EMAIL);
|
||||
$user['third_approver_email'] = filter_var($user['third_approver_email'], FILTER_SANITIZE_EMAIL);
|
||||
$user['exceptional_approver_email'] = filter_var($user['exceptional_approver_email'], FILTER_SANITIZE_EMAIL);
|
||||
$user['fourth_approver_email'] = filter_var($user['fourth_approver_email'], FILTER_SANITIZE_EMAIL);
|
||||
$user['role_id'] = $rolesList[$role] ?? 4;
|
||||
$user['group_id'] = $groupsList[$group] ?? null;
|
||||
$user['org_id'] = env('ORG_id');
|
||||
@ -841,7 +841,7 @@ public function userUpload()
|
||||
$this->userModel->updateApprover('first', $insertedIds);
|
||||
$this->userModel->updateApprover('second', $insertedIds);
|
||||
$this->userModel->updateApprover('third', $insertedIds);
|
||||
$this->userModel->updateApprover('exceptional', $insertedIds);
|
||||
$this->userModel->updateApprover('fourth', $insertedIds);
|
||||
|
||||
|
||||
return $this->response->setJSON([
|
||||
|
||||
36
app/Filters/VerifyAppSignature.php
Normal file
36
app/Filters/VerifyAppSignature.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filters;
|
||||
|
||||
use CodeIgniter\HTTP\RequestInterface;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use CodeIgniter\Filters\FilterInterface;
|
||||
|
||||
class VerifyAppSignature implements FilterInterface
|
||||
{
|
||||
public function before(RequestInterface $request, $arguments = null)
|
||||
{
|
||||
// Get the header sent by the Flutter app
|
||||
$clientSignature = $request->getHeaderLine('App-Signature');
|
||||
|
||||
// Load the server's expected signature from the .env
|
||||
$validSignature = getenv('APP_SIGNATURE');
|
||||
|
||||
// Check if signature is valid
|
||||
if ($clientSignature !== $validSignature) {
|
||||
return service('response')
|
||||
->setStatusCode(403)
|
||||
->setJSON([
|
||||
'status' => false,
|
||||
'message' => 'Forbidden: Invalid App Signature',
|
||||
]);
|
||||
}
|
||||
|
||||
// allow request to proceed
|
||||
}
|
||||
|
||||
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
|
||||
{
|
||||
// nothing to do after response
|
||||
}
|
||||
}
|
||||
@ -51,19 +51,55 @@ if (!function_exists('checkUserExist')) {
|
||||
if (!function_exists('getUserPlanCreationRestrictionStatus')) {
|
||||
function getUserPlanCreationRestrictionStatus($user)
|
||||
{
|
||||
if($user['group_id'] != null && ( $user['first_approver'] != null || $user['second_approver'] != null || $user['third_approver'] != null ) )
|
||||
if($user['group_id'] != null)
|
||||
{
|
||||
$groupModel = new GroupModel();
|
||||
$groupData = $groupModel->find($user['group_id']);
|
||||
if($groupData)
|
||||
{
|
||||
if($groupData['domestic_policy_id'] != null && $groupData['international_policy_id'] != null)
|
||||
return 'Both Type Plan Creation Allowed';
|
||||
else if($groupData['domestic_policy_id'] != null)
|
||||
return 'Only Domestic Plan Creation Allowed';
|
||||
else if($groupData['international_policy_id'] != null)
|
||||
return 'Only International Plan Creation Allowed';
|
||||
|
||||
$domesticPolicyId = $groupData['domestic_policy_id'];
|
||||
$internationalPolicyId = $groupData['international_policy_id'];
|
||||
$policyDetailsModel = new PolicyDetailsModel();
|
||||
|
||||
if($domesticPolicyId != null && $internationalPolicyId != null)
|
||||
{
|
||||
$domesticPolicy = $policyDetailsModel->where('policy_id',$domesticPolicyId)->where('service_id', 1)->find();
|
||||
$domesticCheck = checkApproverSetOrNotBasedOnPolicy($domesticPolicy,$user);
|
||||
$internationalPolicy = $policyDetailsModel->where('policy_id',$internationalPolicyId)->where('service_id', 1)->find();
|
||||
$internationalCheck = checkApproverSetOrNotBasedOnPolicy($internationalPolicy,$user);
|
||||
|
||||
if($domesticCheck == true && $internationalCheck == true)
|
||||
return 'Both Type Plan Creation Allowed';
|
||||
else
|
||||
return 'Plan Creation Not Allowed';
|
||||
|
||||
}
|
||||
else if($domesticPolicyId != null)
|
||||
{
|
||||
$domesticPolicy = $policyDetailsModel->where('policy_id',$domesticPolicyId)->where('service_id', 1)->find();
|
||||
$check = checkApproverSetOrNotBasedOnPolicy($domesticPolicy,$user);
|
||||
$internationalPolicy = $policyDetailsModel->where('policy_id',$domesticPolicyId)->where('service_id', 1)->find();
|
||||
$check = checkApproverSetOrNotBasedOnPolicy($internationalPolicy,$user);
|
||||
|
||||
if($check == true)
|
||||
return 'Only Domestic Plan Creation Allowed';
|
||||
else
|
||||
return 'Plan Creation Not Allowed';
|
||||
|
||||
}
|
||||
else if($internationalPolicyId != null)
|
||||
{
|
||||
|
||||
$internationalPolicy = $policyDetailsModel->where('policy_id',$internationalPolicyId)->where('service_id', 1)->find();
|
||||
$check = checkApproverSetOrNotBasedOnPolicy($internationalPolicy,$user);
|
||||
|
||||
if($check == true)
|
||||
return 'Only International Plan Creation Allowed';
|
||||
else
|
||||
return 'Plan Creation Not Allowed';
|
||||
|
||||
}
|
||||
|
||||
|
||||
}else{
|
||||
return 'Plan Creation Not Allowed';
|
||||
@ -77,6 +113,50 @@ if (!function_exists('getUserPlanCreationRestrictionStatus')) {
|
||||
}
|
||||
}
|
||||
|
||||
function checkApproverSetOrNotBasedOnPolicy($Policy,$user)
|
||||
{
|
||||
// Step 1: Determine required approver levels (a1 to a4)
|
||||
$requiredApprovers = [];
|
||||
|
||||
foreach (['', '_exceptional', '_amendment'] as $type) {
|
||||
for ($i = 1; $i <= 4; $i++) {
|
||||
$key = "a{$i}{$type}_action";
|
||||
if (isset($Policy[0][$key]) && $Policy[0][$key] === 'Approval') {
|
||||
$requiredApprovers[] = $i; // add level (1 to 4)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove duplicates (in case multiple types require same level)
|
||||
$requiredApprovers = array_unique($requiredApprovers);
|
||||
|
||||
// Step 2: Check user profile for each required approver level
|
||||
$missingApprovers = [];
|
||||
|
||||
foreach ($requiredApprovers as $level) {
|
||||
$profileKey = match ($level) {
|
||||
1 => 'first_approver',
|
||||
2 => 'second_approver',
|
||||
3 => 'third_approver',
|
||||
4 => 'fourth_approver',
|
||||
};
|
||||
|
||||
if (empty($user[$profileKey]) || $user[$profileKey] == 0) {
|
||||
$missingApprovers[] = $profileKey;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3: Final check
|
||||
if (!empty($missingApprovers)) {
|
||||
// One or more approvers missing
|
||||
// echo "Missing approvers in user profile: " . implode(', ', $missingApprovers);
|
||||
return false;
|
||||
} else {
|
||||
// echo "All required approvers are set in user profile.";
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!function_exists('isDataChanged')) {
|
||||
function isDataChanged($model, $id, array $newData): bool
|
||||
@ -131,7 +211,10 @@ if (!function_exists('isFlightTripDataChanged')) {
|
||||
}
|
||||
|
||||
// Step 1: Fetch old data from the model
|
||||
$oldData = $model->whereIn('flight_id', $flightIds)->where('is_active', 1)->findAll();
|
||||
if(!empty($flightIds))
|
||||
$oldData = $model->whereIn('flight_id', $flightIds)->where('is_active', 1)->findAll();
|
||||
else
|
||||
$oldData = [];
|
||||
|
||||
|
||||
if (!$oldData) {
|
||||
@ -208,9 +291,17 @@ function getDelegatedPlans($org_id, $id)
|
||||
->where('created_on >=', $startDate)
|
||||
->where('created_on <=', $endDate)
|
||||
->findAll();
|
||||
|
||||
$a4Data = $planStatusModel->select('plan_id,a4_id as user_id')
|
||||
->where('a4_id',$userId)
|
||||
->where('a4_action','Approval')
|
||||
->where('is_active',1)
|
||||
->where('created_on >=', $startDate)
|
||||
->where('created_on <=', $endDate)
|
||||
->findAll();
|
||||
|
||||
// Merge results (each record has plan_id + user_id)
|
||||
$merged = array_merge($a1Data, $a2Data, $a3Data);
|
||||
$merged = array_merge($a1Data, $a2Data, $a3Data, $a4Data);
|
||||
|
||||
// Merge into final array
|
||||
$allPlanData = array_merge($allPlanData, $merged);
|
||||
@ -218,9 +309,9 @@ function getDelegatedPlans($org_id, $id)
|
||||
}
|
||||
|
||||
//get already approved data in delegated flow
|
||||
$a1 = $planStatusModel->select('plan_id,a1_id as user_id')->where('a1_action_done_by',$id)->where('a1_action','Approval')->where('is_active',1)->findAll();
|
||||
$a2 = $planStatusModel->select('plan_id,a2_id as user_id')->where('a2_action_done_by',$id)->where('a2_action','Approval')->where('is_active',1)->findAll();
|
||||
$a3 = $planStatusModel->select('plan_id,a3_id as user_id')->where('a3_action_done_by',$id)->where('a3_action','Approval')->where('is_active',1)->findAll();
|
||||
// $a1 = $planStatusModel->select('plan_id,a1_id as user_id')->where('a1_action_done_by',$id)->where('a1_action','Approval')->where('is_active',1)->findAll();
|
||||
// $a2 = $planStatusModel->select('plan_id,a2_id as user_id')->where('a2_action_done_by',$id)->where('a2_action','Approval')->where('is_active',1)->findAll();
|
||||
// $a3 = $planStatusModel->select('plan_id,a3_id as user_id')->where('a3_action_done_by',$id)->where('a3_action','Approval')->where('is_active',1)->findAll();
|
||||
|
||||
//need to discuss with sir
|
||||
// $mergedApprovedArray = array_merge($a1, $a2, $a3);
|
||||
@ -299,172 +390,92 @@ if (!function_exists('format_date_for_client')) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// if (!function_exists('palnStatusHandler')) {
|
||||
// function palnStatusHandler($plan_id, $service_id, $action)
|
||||
// {
|
||||
|
||||
|
||||
// $planModel = new PlanModel();
|
||||
// $planStatusModel = new PlanStatusModel();
|
||||
// $userModel = new UserModel();
|
||||
// $groupModel = new GroupModel();
|
||||
// $policyModel = new PolicyModel();
|
||||
// $policyDetailsModel = new PolicyDetailsModel();
|
||||
|
||||
// if($action == 'DEL')
|
||||
// {
|
||||
// // Delete status
|
||||
// $planStatusModel->set(['is_active' => 0])->where('plan_id',$plan_id)->where('service_id',$service_id)->where('is_active',1)->update();
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// if($action == 'ADD')
|
||||
// {
|
||||
// //check already created
|
||||
// $status = $planStatusModel->where('plan_id',$plan_id)->where('service_id',$service_id)->where('is_active',1)->first();
|
||||
// if ($status) { return false; }
|
||||
// }
|
||||
|
||||
|
||||
// // Fetch plan data
|
||||
// $planData = $planModel->where('plan_id', $plan_id)->first();
|
||||
// if (!$planData) { return false; }
|
||||
// $userId = $planData['user_id'] ?? $planData['traveller_id'];
|
||||
|
||||
// // Fetch user data
|
||||
// $userData = $userModel->where('user_id', $userId)->first();
|
||||
// if (!$userData) { return false; }
|
||||
// $groupId = $userData['group_id'];
|
||||
// $a1Id = $userData['first_approver'];
|
||||
// $a2Id = $userData['second_approver'];
|
||||
// $a3Id = $userData['third_approver'];
|
||||
|
||||
// // Fetch group data
|
||||
// $groupData = $groupModel->where('group_id', $groupId)->first();
|
||||
// if (!$groupData) { return false; }
|
||||
// $policyId = ($planData['trip_type'] == 1) ? $groupData['domestic_policy_id'] : $groupData['international_policy_id'];
|
||||
|
||||
// // Fetch policy service data
|
||||
// $policyServiceData = $policyDetailsModel->where('policy_id', $policyId)->where('service_id', $service_id)->first();
|
||||
// if (!$policyServiceData) {return false; }
|
||||
// $policyA1Action = $policyServiceData['a1_action'];
|
||||
// $policyA2Action = $policyServiceData['a2_action'];
|
||||
// $policyA3Action = $policyServiceData['a3_action'];
|
||||
// $policyParallelAction = $policyServiceData['parallel_process_from'];
|
||||
|
||||
|
||||
// if($action == 'ADD')
|
||||
// {
|
||||
// $data['plan_id'] = $plan_id;
|
||||
// $data['service_id'] = $service_id;
|
||||
// $data['a1_id'] = $a1Id;
|
||||
// $data['a1_action'] = $policyA1Action;
|
||||
// $data['a2_id'] = $a2Id;
|
||||
// $data['a2_action'] = $policyA2Action;
|
||||
// $data['a3_id'] = $a3Id;
|
||||
// $data['a3_action'] = $policyA3Action;
|
||||
// $data['parallel_process_from'] = $policyParallelAction;
|
||||
// // Insert Status
|
||||
// $planStatusModel->insert($data);
|
||||
// }
|
||||
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
if (!function_exists('isValidUploadedFile')) {
|
||||
function isValidUploadedFile($file): bool
|
||||
{
|
||||
return $file && $file->isValid();
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('isAllowedExtension')) {
|
||||
function isAllowedExtension($file, array $allowedExtensions = [] ): bool
|
||||
{
|
||||
$ext = strtolower($file->getClientExtension());
|
||||
|
||||
$result = in_array($ext, $allowedExtensions);
|
||||
|
||||
$result = empty($allowedExtensions) ? true : $result ;
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!function_exists('isExcelNotEmpty')) {
|
||||
function isExcelNotEmpty(array $sheetData): bool
|
||||
{
|
||||
return !empty($sheetData) && count($sheetData) >= 2;
|
||||
}
|
||||
}
|
||||
|
||||
if(!function_exists('createDirectoryWith0777Permission')){
|
||||
|
||||
function createDirectoryWith0777Permission( $uploadDir)
|
||||
{
|
||||
if (!is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0777, true); // recursive creation with full permission
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function getAllowedClassForUser($trip_type,$user_id)
|
||||
if (!function_exists('isValidUploadedFile')) {
|
||||
function isValidUploadedFile($file): bool
|
||||
{
|
||||
return $file && $file->isValid();
|
||||
}
|
||||
}
|
||||
|
||||
$userModel = new UserModel();
|
||||
$groupModel = new GroupModel();
|
||||
$policyDetailsModel = new PolicyDetailsModel();
|
||||
$policyDetailsModel = new PolicyDetailsModel();
|
||||
if (!function_exists('isAllowedExtension')) {
|
||||
function isAllowedExtension($file, array $allowedExtensions = [] ): bool
|
||||
{
|
||||
$ext = strtolower($file->getClientExtension());
|
||||
|
||||
$user = $userModel->where('user_id', $user_id)->first();
|
||||
$groupData = $groupModel->find($user['group_id']);
|
||||
|
||||
if($groupData)
|
||||
{
|
||||
if($trip_type == 1) { $policyId = $groupData['domestic_policy_id'];}else{ $policyId = $groupData['international_policy_id'];}
|
||||
if($policyId != null)
|
||||
{
|
||||
$allowedFlightClass = $policyDetailsModel->select('c_policy_details.class, m_dropdown.dropdown_value as allowed_class')
|
||||
->join('m_dropdown', 'dropdown_key = c_policy_details.class AND dropdown = "flight_class"', 'left')
|
||||
->where('policy_id',$policyId)
|
||||
->where('service_id',1)
|
||||
->first();
|
||||
$data['flight'] = $allowedFlightClass['allowed_class'];
|
||||
$result = in_array($ext, $allowedExtensions);
|
||||
|
||||
$allowedTrainClass = $policyDetailsModel->select('c_policy_details.class, m_dropdown.dropdown_value as allowed_class')
|
||||
->join('m_dropdown', 'dropdown_key = c_policy_details.class AND dropdown = "train_class"', 'left')
|
||||
->where('policy_id',$policyId)
|
||||
->where('service_id',2)
|
||||
->first();
|
||||
$data['train'] = $allowedTrainClass['allowed_class'];
|
||||
$result = empty($allowedExtensions) ? true : $result ;
|
||||
|
||||
$allowedHotelClass = $policyDetailsModel->select('c_policy_details.class, m_dropdown.dropdown_value as allowed_class')
|
||||
->join('m_dropdown', 'dropdown_key = c_policy_details.class AND dropdown = "hotel_class"', 'left')
|
||||
->where('policy_id',$policyId)
|
||||
->where('service_id',5)
|
||||
->first();
|
||||
$data['hotel'] = $allowedHotelClass['allowed_class'];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('isExcelNotEmpty')) {
|
||||
function isExcelNotEmpty(array $sheetData): bool
|
||||
{
|
||||
return !empty($sheetData) && count($sheetData) >= 2;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
if(!function_exists('createDirectoryWith0777Permission')){
|
||||
|
||||
function createDirectoryWith0777Permission( $uploadDir)
|
||||
{
|
||||
if (!is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0777, true); // recursive creation with full permission
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getAllowedClassForUser($trip_type,$user_id)
|
||||
{
|
||||
|
||||
$userModel = new UserModel();
|
||||
$groupModel = new GroupModel();
|
||||
$policyDetailsModel = new PolicyDetailsModel();
|
||||
$policyDetailsModel = new PolicyDetailsModel();
|
||||
|
||||
$user = $userModel->where('user_id', $user_id)->first();
|
||||
$groupData = $groupModel->find($user['group_id']);
|
||||
|
||||
if($groupData)
|
||||
{
|
||||
if($trip_type == 1) { $policyId = $groupData['domestic_policy_id'];}else{ $policyId = $groupData['international_policy_id'];}
|
||||
if($policyId != null)
|
||||
{
|
||||
$allowedFlightClass = $policyDetailsModel->select('c_policy_details.class, m_dropdown.dropdown_value as allowed_class')
|
||||
->join('m_dropdown', 'dropdown_key = c_policy_details.class AND dropdown = "flight_class"', 'left')
|
||||
->where('policy_id',$policyId)
|
||||
->where('service_id',1)
|
||||
->first();
|
||||
$data['flight'] = $allowedFlightClass['allowed_class'];
|
||||
|
||||
$allowedTrainClass = $policyDetailsModel->select('c_policy_details.class, m_dropdown.dropdown_value as allowed_class')
|
||||
->join('m_dropdown', 'dropdown_key = c_policy_details.class AND dropdown = "train_class"', 'left')
|
||||
->where('policy_id',$policyId)
|
||||
->where('service_id',2)
|
||||
->first();
|
||||
$data['train'] = $allowedTrainClass['allowed_class'];
|
||||
|
||||
$allowedHotelClass = $policyDetailsModel->select('c_policy_details.class, m_dropdown.dropdown_value as allowed_class')
|
||||
->join('m_dropdown', 'dropdown_key = c_policy_details.class AND dropdown = "hotel_class"', 'left')
|
||||
->where('policy_id',$policyId)
|
||||
->where('service_id',5)
|
||||
->first();
|
||||
$data['hotel'] = $allowedHotelClass['allowed_class'];
|
||||
}
|
||||
|
||||
|
||||
return $data;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -45,16 +45,24 @@ if (!function_exists('sendPlanCreationMail')) {
|
||||
if ($value['is_action_done'] == 1) { continue; }
|
||||
// Skip if action is None
|
||||
if ($value['action'] === 'None') { continue; }
|
||||
// mail success check
|
||||
if ($value['is_mail_send'] == 1) { continue; }
|
||||
// skip with below condition
|
||||
if($mailOn == 'send_mail_to_only_approver' && $action['parallel_process_from'] == 1){ continue; }
|
||||
|
||||
|
||||
|
||||
if($value['action'] == 'Approval'){ $template = 'plan_creation_approval_notification_to_approver'; }else if($value['action'] == 'Notification'){ $template = 'plan_creation_notification_to_approver'; }
|
||||
|
||||
$userData = $userModel->where('user_id', $value['user_id'])->first();
|
||||
|
||||
$url = urlButton($planId, $value['user_id']);
|
||||
|
||||
send_email($userData['org_id'] , $userData['email'], $template , $userData , $planData, $url);
|
||||
$res = send_email($userData['org_id'] , $userData['email'], $template , $userData , $planData, $url);
|
||||
if($res['status'] = 'success')
|
||||
{
|
||||
$planStatusModel->set([ $value['mail_send_key'] => 1 ])->where('plan_id', $planId)->where('is_active', 1)->update();
|
||||
}
|
||||
|
||||
// if action is notification update the action status as 1 (done)
|
||||
$parallelProcessValue = $action['parallel_process_from'];
|
||||
@ -70,7 +78,11 @@ if (!function_exists('sendPlanCreationMail')) {
|
||||
{
|
||||
sendPlanCreationMail($planId , 'send_mail_to_only_approver');
|
||||
}
|
||||
if($parallelProcessValue == 3)
|
||||
if($parallelProcessValue == 3 && ($value['action_key'] == 'a1_action' || $value['action_key'] == 'a2_action') )
|
||||
{
|
||||
sendPlanCreationMail($planId , 'send_mail_to_only_approver');
|
||||
}
|
||||
if($parallelProcessValue == 4 && ($value['action_key'] == 'a1_action' || $value['action_key'] == 'a2_action' || $value['action_key'] == 'a3_action'))
|
||||
{
|
||||
sendPlanCreationMail($planId , 'send_mail_to_only_approver');
|
||||
}
|
||||
@ -142,6 +154,10 @@ if (!function_exists('sendPlanApprovalOrRejectMail')) {
|
||||
if (isset($value['a3_status'])) {
|
||||
$statusHtml .= '<li style="margin-bottom: 5px;"><strong>Approver 3:</strong> ' . $value['a3_status'] . '</li>';
|
||||
}
|
||||
|
||||
if (isset($value['a4_status'])) {
|
||||
$statusHtml .= '<li style="margin-bottom: 5px;"><strong>Approver 4:</strong> ' . $value['a4_status'] . '</li>';
|
||||
}
|
||||
}
|
||||
$statusHtml .= '</ul>';
|
||||
$userData['status_details'] = $statusHtml;
|
||||
@ -179,7 +195,6 @@ if (!function_exists('sendPlanUpdationMail')) {
|
||||
// Fetch user data
|
||||
$userData = $userModel->where('user_id', $userId)->first();
|
||||
|
||||
|
||||
// send mail to traveller
|
||||
send_email($planData['org_id'] , $userData['email'], 'plan_updation_notification_to_traveller' , $userData , $planData);
|
||||
|
||||
@ -194,6 +209,8 @@ if (!function_exists('sendPlanUpdationMail')) {
|
||||
if ($value['is_action_done'] == 1) { continue; }
|
||||
// Skip if action is None
|
||||
if ($value['action'] === 'None') { continue; }
|
||||
// mail success check
|
||||
if ($value['is_mail_send'] === 1) { continue; }
|
||||
|
||||
if($value['action'] == 'Approval'){ $template = 'plan_updation_approval_notification_to_approver'; }else if($value['action'] == 'Notification'){ $template = 'plan_updation_notification_to_approver'; }
|
||||
|
||||
@ -201,7 +218,11 @@ if (!function_exists('sendPlanUpdationMail')) {
|
||||
|
||||
$url = urlButton($planId, $value['user_id']);
|
||||
|
||||
send_email($userData['org_id'] , $userData['email'], $template , $userData , $planData, $url);
|
||||
$res = send_email($userData['org_id'] , $userData['email'], $template , $userData , $planData, $url);
|
||||
if($res['status'] = 'success')
|
||||
{
|
||||
$planStatusModel->set([ $value['mail_send_key'] => 1 ])->where('plan_id', $planId)->where('is_active', 1)->update();
|
||||
}
|
||||
|
||||
// if action is notification update the action status as 1 (done)
|
||||
$parallelProcessValue = $action['parallel_process_from'];
|
||||
@ -217,7 +238,11 @@ if (!function_exists('sendPlanUpdationMail')) {
|
||||
{
|
||||
sendPlanCreationMail($planId , 'send_mail_to_only_approver');
|
||||
}
|
||||
if($parallelProcessValue == 3)
|
||||
if($parallelProcessValue == 3 && ($value['action_key'] == 'a1_action' || $value['action_key'] == 'a2_action') )
|
||||
{
|
||||
sendPlanCreationMail($planId , 'send_mail_to_only_approver');
|
||||
}
|
||||
if($parallelProcessValue == 4 && ($value['action_key'] == 'a1_action' || $value['action_key'] == 'a2_action' || $value['action_key'] == 'a3_action'))
|
||||
{
|
||||
sendPlanCreationMail($planId , 'send_mail_to_only_approver');
|
||||
}
|
||||
@ -268,37 +293,89 @@ if (!function_exists('sendUserCreationMail')) {
|
||||
$html = $templateData['body_html'];
|
||||
$toEmailId = $mailData['email'];
|
||||
|
||||
$email = \Config\Services::email();
|
||||
$email->initialize([
|
||||
'protocol' => 'smtp',
|
||||
'SMTPHost' => $orgData['mail_host'],
|
||||
'SMTPUser' => $orgData['mail_user_name'],
|
||||
'SMTPPass' => $orgData['mail_password'],
|
||||
'SMTPPort' => (int)$orgData['mail_port'],
|
||||
'mailType' => 'html'
|
||||
]);
|
||||
$email->setFrom($orgData['sender_email'], $orgData['name']);
|
||||
$email->setTo($toEmailId);
|
||||
$email->setSubject($subject);
|
||||
$email->setMessage($html);
|
||||
|
||||
// Set up ZeptoMail API request
|
||||
$endpoint = "https://api.zeptomail.com/v1.1/email";
|
||||
$apiKey = env('ZOHO_API_KEY');
|
||||
$sender = env('ZOHO_SENDER_MAIL');
|
||||
|
||||
$payload = [
|
||||
"from" => [
|
||||
"address" => $sender,
|
||||
"name" => $orgData['name'] ?? "TripApprovalTool"
|
||||
],
|
||||
"to" => [
|
||||
["email_address" => ["address" => $toEmailId]]
|
||||
],
|
||||
"subject" => $subject,
|
||||
"htmlbody" => $html,
|
||||
];
|
||||
|
||||
$headers = [
|
||||
"Content-Type: application/json",
|
||||
"Authorization: Zoho-enczapikey " . $apiKey
|
||||
];
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $endpoint);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
if (curl_errno($ch)) {
|
||||
$error_msg = curl_error($ch);
|
||||
log_message('error', "[EMAIL ERROR] Curl failed: {$error_msg}");
|
||||
return ['status' => 'failed', 'code' => 500, 'message' => 'Curl error', 'error' => $error_msg];
|
||||
}
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
$resp = json_decode($response, true);
|
||||
|
||||
if ($httpCode === 200 && isset($resp['request_id'])) {
|
||||
log_message('info', "[EMAIL SENT] To: {$toEmailId}, Template: {$mailData['template']}");
|
||||
return ['status' => 'success', 'code' => 200, 'message' => 'Email sent successfully', 'data' => $toEmailId];
|
||||
} else {
|
||||
log_message('error', "[EMAIL FAILED] HTTP: {$httpCode}, Response: {$response}");
|
||||
return ['status' => 'failed', 'code' => $httpCode, 'message' => 'Email sending failed', 'response' => $response];
|
||||
}
|
||||
|
||||
|
||||
// $email = \Config\Services::email();
|
||||
// $email->initialize([
|
||||
// 'protocol' => 'smtp',
|
||||
// 'SMTPHost' => $orgData['mail_host'],
|
||||
// 'SMTPUser' => $orgData['mail_user_name'],
|
||||
// 'SMTPPass' => $orgData['mail_password'],
|
||||
// 'SMTPPort' => (int)$orgData['mail_port'],
|
||||
// 'mailType' => 'html'
|
||||
// ]);
|
||||
// $email->setFrom($orgData['sender_email'], $orgData['name']);
|
||||
// $email->setTo($toEmailId);
|
||||
// $email->setSubject($subject);
|
||||
// $email->setMessage($html);
|
||||
|
||||
|
||||
|
||||
if ($email->send()) {
|
||||
// if ($email->send()) {
|
||||
|
||||
log_message('debug', 'Email Success to ' . $toEmailId);
|
||||
return ['status' => 'success', 'code' => 200, 'message' => 'Email Sent Successfully...', 'data' => $toEmailId];
|
||||
} else {
|
||||
log_message('debug', 'Email sending failed: ' . $email->printDebugger(['headers']));
|
||||
return ['status' => 'failed', 'code' => 404, 'message' => 'Email Sent Failed...', 'data' => $toEmailId];
|
||||
}
|
||||
// log_message('debug', 'Email Success to ' . $toEmailId);
|
||||
// return ['status' => 'success', 'code' => 200, 'message' => 'Email Sent Successfully...', 'data' => $toEmailId];
|
||||
// } else {
|
||||
// log_message('debug', 'Email sending failed: ' . $email->printDebugger(['headers']));
|
||||
// return ['status' => 'failed', 'code' => 404, 'message' => 'Email Sent Failed...', 'data' => $toEmailId];
|
||||
// }
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('send_email')) {
|
||||
// if (!function_exists('send_email')) {
|
||||
// function send_email($org_id , $toEmailId, $template , $userData , $planData = null, $url = null)
|
||||
// {
|
||||
// try {
|
||||
@ -400,113 +477,253 @@ if (!function_exists('send_email')) {
|
||||
// }
|
||||
|
||||
|
||||
if (!function_exists('send_email')) {
|
||||
function send_email($org_id, $toEmailId, $template, $userData, $planData = null, $url = null)
|
||||
{
|
||||
try {
|
||||
// Load models
|
||||
$organizationModel = new \App\Models\OrganizationModel();
|
||||
$mailTemplateModel = new \App\Models\MailTemplateModel();
|
||||
// if (!function_exists('send_email')) {
|
||||
// function send_email($org_id, $toEmailId, $template, $userData, $planData = null, $url = null)
|
||||
// {
|
||||
// try {
|
||||
// // Load models
|
||||
// $organizationModel = new \App\Models\OrganizationModel();
|
||||
// $mailTemplateModel = new \App\Models\MailTemplateModel();
|
||||
|
||||
// Fetch organization & template
|
||||
$orgData = $organizationModel->where('org_id', $org_id)->first();
|
||||
$templateData = $mailTemplateModel->where('org_id', $org_id)->where('template_name', $template)->first();
|
||||
// // Fetch organization & template
|
||||
// $orgData = $organizationModel->where('org_id', $org_id)->first();
|
||||
// $templateData = $mailTemplateModel->where('org_id', $org_id)->where('template_name', $template)->first();
|
||||
|
||||
if (!$orgData || !$templateData) {
|
||||
log_message('error', "[EMAIL ERROR] Missing org/template data for org_id={$org_id}, template={$template}");
|
||||
return ['status' => 'failed', 'code' => 404, 'message' => 'Missing organization or template data'];
|
||||
}
|
||||
// if (!$orgData || !$templateData) {
|
||||
// log_message('error', "[EMAIL ERROR] Missing org/template data for org_id={$org_id}, template={$template}");
|
||||
// return ['status' => 'failed', 'code' => 404, 'message' => 'Missing organization or template data'];
|
||||
// }
|
||||
|
||||
// Replace placeholders from user data
|
||||
foreach ($userData as $key => $value) {
|
||||
$templateData['body_html'] = str_replace('%' . $key . '%', $value ?? '', $templateData['body_html']);
|
||||
}
|
||||
// // Replace placeholders from user data
|
||||
// foreach ($userData as $key => $value) {
|
||||
// $templateData['body_html'] = str_replace('%' . $key . '%', $value ?? '', $templateData['body_html']);
|
||||
// }
|
||||
|
||||
// Replace placeholders from plan data
|
||||
if (!empty($planData)) {
|
||||
foreach ($planData as $key => $value) {
|
||||
$templateData['body_html'] = str_replace('%' . $key . '%', $value ?? '', $templateData['body_html']);
|
||||
}
|
||||
// // Replace placeholders from plan data
|
||||
// if (!empty($planData)) {
|
||||
// foreach ($planData as $key => $value) {
|
||||
// $templateData['body_html'] = str_replace('%' . $key . '%', $value ?? '', $templateData['body_html']);
|
||||
// }
|
||||
|
||||
// Exceptional reason block
|
||||
if (!empty($planData['exceptional_plan_reason'])) {
|
||||
$reasonHtml = '
|
||||
<table style="width:100%; border-collapse:collapse; font-family:Arial, sans-serif;">
|
||||
<tr>
|
||||
<td style="text-align:left;background-color:#ffdbdb;color:#960000;padding:7px 15px;font-weight:bold;border-top-left-radius:5px;border-top-right-radius:5px;border-bottom:1px solid #c65e56;">
|
||||
Reason for travel policy exception
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:left;background-color:#fff5f5;color:#960000ab;padding:10px 15px;border-bottom-left-radius:5px;border-bottom-right-radius:5px;">
|
||||
' . esc($planData['exceptional_plan_reason']) . '
|
||||
</td>
|
||||
</tr>
|
||||
</table>';
|
||||
$templateData['body_html'] .= $reasonHtml;
|
||||
}
|
||||
}
|
||||
// // Exceptional reason block
|
||||
// if (!empty($planData['exceptional_plan_reason'])) {
|
||||
// $reasonHtml = '
|
||||
// <table style="width:100%; border-collapse:collapse; font-family:Arial, sans-serif;">
|
||||
// <tr>
|
||||
// <td style="text-align:left;background-color:#ffdbdb;color:#960000;padding:7px 15px;font-weight:bold;border-top-left-radius:5px;border-top-right-radius:5px;border-bottom:1px solid #c65e56;">
|
||||
// Reason for travel policy exception
|
||||
// </td>
|
||||
// </tr>
|
||||
// <tr>
|
||||
// <td style="text-align:left;background-color:#fff5f5;color:#960000ab;padding:10px 15px;border-bottom-left-radius:5px;border-bottom-right-radius:5px;">
|
||||
// ' . esc($planData['exceptional_plan_reason']) . '
|
||||
// </td>
|
||||
// </tr>
|
||||
// </table>';
|
||||
// $templateData['body_html'] .= $reasonHtml;
|
||||
// }
|
||||
// }
|
||||
|
||||
// Add review URL if present
|
||||
if ($url !== null) {
|
||||
$templateData['body_html'] = str_replace('%trip_review_link%', $url, $templateData['body_html']);
|
||||
}
|
||||
// // Add review URL if present
|
||||
// if ($url !== null) {
|
||||
// $templateData['body_html'] = str_replace('%trip_review_link%', $url, $templateData['body_html']);
|
||||
// }
|
||||
|
||||
// Initialize email
|
||||
$email = \Config\Services::email(false);
|
||||
$email->initialize([
|
||||
'protocol' => 'smtp',
|
||||
'SMTPHost' => $orgData['mail_host'],
|
||||
'SMTPUser' => $orgData['mail_user_name'],
|
||||
'SMTPPass' => $orgData['mail_password'], // Use app password if Gmail
|
||||
'SMTPPort' => (int) $orgData['mail_port'],
|
||||
'SMTPCrypto' => 'tls', // ensure STARTTLS
|
||||
'mailType' => 'html',
|
||||
'charset' => 'utf-8',
|
||||
'newline' => "\r\n",
|
||||
'wordWrap' => true,
|
||||
]);
|
||||
// // Initialize email
|
||||
// $email = \Config\Services::email(false);
|
||||
// $email->initialize([
|
||||
// 'protocol' => 'smtp',
|
||||
// 'SMTPHost' => $orgData['mail_host'],
|
||||
// 'SMTPUser' => $orgData['mail_user_name'],
|
||||
// 'SMTPPass' => $orgData['mail_password'],
|
||||
// 'SMTPPort' => (int) $orgData['mail_port'],
|
||||
// // 'SMTPCrypto' => 'tls', // ensure STARTTLS
|
||||
// 'mailType' => 'html',
|
||||
// 'charset' => 'utf-8',
|
||||
// 'newline' => "\r\n",
|
||||
// 'wordWrap' => true,
|
||||
// ]);
|
||||
|
||||
$email->setFrom($orgData['sender_email'], $orgData['name'] ?? 'TripApprovalTool');
|
||||
$email->setTo($toEmailId);
|
||||
$email->setSubject($templateData['subject']);
|
||||
$email->setMessage($templateData['body_html']);
|
||||
// $email->setFrom($orgData['sender_email'], $orgData['name'] ?? 'TripApprovalTool');
|
||||
// $email->setTo($toEmailId);
|
||||
// $email->setSubject($templateData['subject']);
|
||||
// $email->setMessage($templateData['body_html']);
|
||||
|
||||
// Attach file if exists
|
||||
// if (!empty($planData['pdf_file_path']) && file_exists($planData['pdf_file_path'])) {
|
||||
// $email->attach($planData['pdf_file_path']);
|
||||
// }
|
||||
// // Attach file if exists
|
||||
// // if (!empty($planData['pdf_file_path']) && file_exists($planData['pdf_file_path'])) {
|
||||
// // $email->attach($planData['pdf_file_path']);
|
||||
// // }
|
||||
// // $filePath = WRITEPATH . 'pdf/trips/trip_' . $planData['plan_id'] . '.pdf';
|
||||
// // if (!empty($filePath) && file_exists($filePath) && is_readable($filePath)) {
|
||||
|
||||
if (!empty($planData['pdf_file_path']) && file_exists($planData['pdf_file_path']) && is_readable($planData['pdf_file_path'])) {
|
||||
$email->attach(
|
||||
$planData['pdf_file_path'],
|
||||
'attachment',
|
||||
basename($planData['pdf_file_path']),
|
||||
'application/pdf'
|
||||
);
|
||||
} else {
|
||||
log_message('error', "[EMAIL] PDF file not attached. Path: {$planData['pdf_file_path']}");
|
||||
}
|
||||
// // $email->attach($filePath, 'attachment', basename($filePath), 'application/pdf');
|
||||
|
||||
// // } else {
|
||||
// // log_message('error', "[EMAIL] PDF file not attached. Path: {$filePath}");
|
||||
// // }
|
||||
|
||||
// $filePath = WRITEPATH . 'pdf/trips/trip_' . $planData['plan_id'] . '.pdf';
|
||||
|
||||
// if (!empty($filePath) && file_exists($filePath) && is_readable($filePath)) {
|
||||
// // Read the file content
|
||||
// $fileContent = file_get_contents($filePath);
|
||||
|
||||
// if ($fileContent === false) {
|
||||
// log_message('error', "[EMAIL] Failed to read PDF file content. Path: {$filePath}");
|
||||
// // Handle error: perhaps skip attachment or throw an exception
|
||||
// } else {
|
||||
// // Attach the file content directly
|
||||
// $email->attach($fileContent, 'attachment', basename($filePath), 'application/pdf');
|
||||
// log_message('info', "[EMAIL] PDF file attached successfully. Path: {$filePath}");
|
||||
// }
|
||||
// } else {
|
||||
// log_message('error', "[EMAIL] PDF file not attached. Path: {$filePath}");
|
||||
// }
|
||||
|
||||
|
||||
// Send email
|
||||
if ($email->send()) {
|
||||
log_message('info', "[EMAIL SENT] To: {$toEmailId}, Template: {$template}");
|
||||
return ['status' => 'success', 'code' => 200, 'message' => 'Email sent successfully', 'data' => $toEmailId];
|
||||
} else {
|
||||
// Log full debugger info
|
||||
$debug = $email->printDebugger(['headers', 'subject', 'body']);
|
||||
log_message('error', "[EMAIL FAILED] To: {$toEmailId}, Template: {$template}\n" . strip_tags($debug));
|
||||
return ['status' => 'failed', 'code' => 500, 'message' => 'Email sending failed', 'debug' => strip_tags($debug)];
|
||||
}
|
||||
// // Send email
|
||||
// if ($email->send()) {
|
||||
// log_message('info', "[EMAIL SENT] To: {$toEmailId}, Template: {$template}");
|
||||
// $email->clear(true); // 'true' clears attachments as well
|
||||
// return ['status' => 'success', 'code' => 200, 'message' => 'Email sent successfully', 'data' => $toEmailId];
|
||||
// } else {
|
||||
// // Log full debugger info
|
||||
// $debug = $email->printDebugger(['headers', 'subject', 'body']);
|
||||
// log_message('error', "[EMAIL FAILED] To: {$toEmailId}, Template: {$template}\n" . strip_tags($debug));
|
||||
// $email->clear(true); // 'true' clears attachments as well
|
||||
// return ['status' => 'failed', 'code' => 500, 'message' => 'Email sending failed', 'debug' => strip_tags($debug)];
|
||||
// }
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
log_message('critical', "[EMAIL EXCEPTION] To: {$toEmailId}, Error: " . $e->getMessage() . ' on line ' . $e->getLine());
|
||||
return ['status' => 'failed', 'code' => 500, 'message' => 'Exception: ' . $e->getMessage()];
|
||||
// } catch (\Throwable $e) {
|
||||
// log_message('critical', "[EMAIL EXCEPTION] To: {$toEmailId}, Error: " . $e->getMessage() . ' on line ' . $e->getLine());
|
||||
// return ['status' => 'failed', 'code' => 500, 'message' => 'Exception: ' . $e->getMessage()];
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// }
|
||||
|
||||
|
||||
// zoho api service
|
||||
if (!function_exists('send_email')) {
|
||||
function send_email($org_id, $toEmailId, $template, $userData, $planData = null, $url = null)
|
||||
{
|
||||
try {
|
||||
$organizationModel = new \App\Models\OrganizationModel();
|
||||
$mailTemplateModel = new \App\Models\MailTemplateModel();
|
||||
|
||||
$orgData = $organizationModel->where('org_id', $org_id)->first();
|
||||
$templateData = $mailTemplateModel->where('org_id', $org_id)->where('template_name', $template)->first();
|
||||
|
||||
if (!$orgData || !$templateData) {
|
||||
log_message('error', "[EMAIL ERROR] Missing org/template data for org_id={$org_id}, template={$template}");
|
||||
return ['status' => 'failed', 'code' => 404, 'message' => 'Missing organization or template data'];
|
||||
}
|
||||
|
||||
// Replace placeholders
|
||||
foreach ($userData as $key => $value) {
|
||||
$templateData['body_html'] = str_replace('%' . $key . '%', $value ?? '', $templateData['body_html']);
|
||||
}
|
||||
|
||||
if (!empty($planData)) {
|
||||
foreach ($planData as $key => $value) {
|
||||
$templateData['body_html'] = str_replace('%' . $key . '%', $value ?? '', $templateData['body_html']);
|
||||
}
|
||||
|
||||
if (!empty($planData['exceptional_plan_reason'])) {
|
||||
$templateData['body_html'] .= '
|
||||
<table style="width:100%; border-collapse:collapse; font-family:Arial, sans-serif;">
|
||||
<tr>
|
||||
<td style="text-align:left;background-color:#ffdbdb;color:#960000;padding:7px 15px;font-weight:bold;">
|
||||
Reason for travel policy exception
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:left;background-color:#fff5f5;color:#960000ab;padding:10px 15px;">
|
||||
' . esc($planData['exceptional_plan_reason']) . '
|
||||
</td>
|
||||
</tr>
|
||||
</table>';
|
||||
}
|
||||
}
|
||||
|
||||
if ($url !== null) {
|
||||
$templateData['body_html'] = str_replace('%trip_review_link%', $url, $templateData['body_html']);
|
||||
}
|
||||
|
||||
// Set up ZeptoMail API request
|
||||
$endpoint = "https://api.zeptomail.com/v1.1/email";
|
||||
$apiKey = env('ZOHO_API_KEY');
|
||||
$sender = env('ZOHO_SENDER_MAIL');
|
||||
|
||||
$attachments = [];
|
||||
|
||||
if (!empty($planData)) {
|
||||
$filePath = WRITEPATH . 'pdf/trips/trip_' . $planData['plan_id'] . '.pdf';
|
||||
if (!empty($filePath) && file_exists($filePath) && is_readable($filePath)) {
|
||||
$attachments[] = [
|
||||
"content" => base64_encode(file_get_contents($filePath)),
|
||||
"mime_type" => "application/pdf",
|
||||
"name" => basename($filePath)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$payload = [
|
||||
"from" => [
|
||||
"address" => $sender,
|
||||
"name" => $orgData['name'] ?? "TripApprovalTool"
|
||||
],
|
||||
"to" => [
|
||||
["email_address" => ["address" => $toEmailId]]
|
||||
],
|
||||
"subject" => $templateData['subject'],
|
||||
"htmlbody" => $templateData['body_html'],
|
||||
];
|
||||
|
||||
if (!empty($attachments)) {
|
||||
$payload["attachments"] = $attachments;
|
||||
}
|
||||
|
||||
$headers = [
|
||||
"Content-Type: application/json",
|
||||
"Authorization: Zoho-enczapikey " . $apiKey
|
||||
];
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $endpoint);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
if (curl_errno($ch)) {
|
||||
$error_msg = curl_error($ch);
|
||||
log_message('error', "[EMAIL ERROR] Curl failed: {$error_msg}");
|
||||
return ['status' => 'failed', 'code' => 500, 'message' => 'Curl error', 'error' => $error_msg];
|
||||
}
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
$resp = json_decode($response, true);
|
||||
|
||||
if ($httpCode === 200 && isset($resp['request_id'])) {
|
||||
log_message('info', "[EMAIL SENT] To: {$toEmailId}, Template: {$template}");
|
||||
return ['status' => 'success', 'code' => 200, 'message' => 'Email sent successfully', 'data' => $toEmailId];
|
||||
} else {
|
||||
log_message('error', "[EMAIL FAILED] HTTP: {$httpCode}, Response: {$response}");
|
||||
return ['status' => 'failed', 'code' => $httpCode, 'message' => 'Email sending failed', 'response' => $response];
|
||||
}
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
log_message('critical', "[EMAIL EXCEPTION] To: {$toEmailId}, Error: " . $e->getMessage() . ' on line ' . $e->getLine());
|
||||
return ['status' => 'failed', 'code' => 500, 'message' => 'Exception: ' . $e->getMessage()];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!function_exists('send_email_agent')) {
|
||||
@ -552,15 +769,7 @@ if (!function_exists('send_email_agent')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$email = \Config\Services::email();
|
||||
$email->initialize([
|
||||
'protocol' => 'smtp',
|
||||
'SMTPHost' => $orgData['mail_host'],
|
||||
'SMTPUser' => $orgData['mail_user_name'],
|
||||
'SMTPPass' => $orgData['mail_password'],
|
||||
'SMTPPort' => (int)$orgData['mail_port'],
|
||||
'mailType' => 'html'
|
||||
]);
|
||||
|
||||
|
||||
foreach ($userData as $key => $value) {
|
||||
$jsonString = $value['agent_supported_service_ids'];
|
||||
@ -578,35 +787,118 @@ if (!function_exists('send_email_agent')) {
|
||||
|
||||
if (!empty($common)) {
|
||||
|
||||
//send mail to agent
|
||||
$placeHolderData['agent_name'] = $value['first_name'].' '.$value['last_name'];
|
||||
// Create a fresh copy of template for each user
|
||||
$htmlTemplate = $templateData['body_html'];
|
||||
|
||||
foreach ($placeHolderData as $placeHolderkey => $placeHoldervalue) {
|
||||
|
||||
//send mail to agent
|
||||
$placeHolderData = [
|
||||
'agent_name' => $value['first_name'].' '.$value['last_name']
|
||||
];
|
||||
|
||||
foreach ($placeHolderData as $placeHolderkey => $placeHoldervalue) {
|
||||
$placeHolder = '%'.$placeHolderkey.'%';
|
||||
$templateData['body_html'] = str_replace($placeHolder, $placeHoldervalue ?? '', $templateData['body_html']);
|
||||
$htmlTemplate = str_replace($placeHolder, $placeHoldervalue ?? '', $htmlTemplate);
|
||||
}
|
||||
|
||||
$subject = $templateData['subject'];
|
||||
$html = $templateData['body_html'];
|
||||
$html = $htmlTemplate;
|
||||
|
||||
//trigger_email_to agent
|
||||
$email->setFrom($orgData['sender_email'], $orgData['name']);
|
||||
$email->setTo($value['email']);
|
||||
$email->setSubject($subject);
|
||||
$email->setMessage($html);
|
||||
|
||||
if(!empty($planData)){
|
||||
$email->attach($planData['pdf_file_path']);
|
||||
|
||||
// Set up ZeptoMail API request
|
||||
$endpoint = "https://api.zeptomail.com/v1.1/email";
|
||||
$apiKey = env('ZOHO_API_KEY');
|
||||
$sender = env('ZOHO_SENDER_MAIL');
|
||||
|
||||
$attachments = [];
|
||||
|
||||
$filePath = WRITEPATH . 'pdf/trips/trip_' . $planData['plan_id'] . '.pdf';
|
||||
if (!empty($filePath) && file_exists($filePath) && is_readable($filePath)) {
|
||||
$attachments[] = [
|
||||
"content" => base64_encode(file_get_contents($filePath)),
|
||||
"mime_type" => "application/pdf",
|
||||
"name" => basename($filePath)
|
||||
];
|
||||
}
|
||||
|
||||
if ($email->send()) {
|
||||
|
||||
$payload = [
|
||||
"from" => [
|
||||
"address" => $sender,
|
||||
"name" => $orgData['name'] ?? "TripApprovalTool"
|
||||
],
|
||||
"to" => [
|
||||
["email_address" => ["address" => $value['email']]]
|
||||
],
|
||||
"subject" => $subject,
|
||||
"htmlbody" => $html,
|
||||
];
|
||||
|
||||
if (!empty($attachments)) {
|
||||
$payload["attachments"] = $attachments;
|
||||
}
|
||||
|
||||
$headers = [
|
||||
"Content-Type: application/json",
|
||||
"Authorization: Zoho-enczapikey " . $apiKey
|
||||
];
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $endpoint);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
if (curl_errno($ch)) {
|
||||
$error_msg = curl_error($ch);
|
||||
log_message('error', "[EMAIL ERROR] Curl failed: {$error_msg}");
|
||||
return ['status' => 'failed', 'code' => 500, 'message' => 'Curl error', 'error' => $error_msg];
|
||||
}
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
$resp = json_decode($response, true);
|
||||
|
||||
if ($httpCode === 200 && isset($resp['request_id'])) {
|
||||
log_message('debug', 'Email Success to agent plan_id = ' .$plan_id.'email = ' . $value['email']);
|
||||
|
||||
} else {
|
||||
log_message('debug', 'Email sending failed: agent plan_id = ' .$plan_id.'email = ' . $value['email'].'error = '.$email->printDebugger(['headers']));
|
||||
|
||||
log_message('error', "[EMAIL FAILED] plan_id = {$plan_id}, email = {$value['email']}, HTTP: {$httpCode}, Response: {$response}");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// $email = \Config\Services::email();
|
||||
// $email->initialize([
|
||||
// 'protocol' => 'smtp',
|
||||
// 'SMTPHost' => $orgData['mail_host'],
|
||||
// 'SMTPUser' => $orgData['mail_user_name'],
|
||||
// 'SMTPPass' => $orgData['mail_password'],
|
||||
// 'SMTPPort' => (int)$orgData['mail_port'],
|
||||
// 'mailType' => 'html'
|
||||
// ]);
|
||||
|
||||
// //trigger_email_to agent
|
||||
// $email->setFrom($orgData['sender_email'], $orgData['name']);
|
||||
// $email->setTo($value['email']);
|
||||
// $email->setSubject($subject);
|
||||
// $email->setMessage($html);
|
||||
|
||||
// if(!empty($planData)){
|
||||
// $email->attach($planData['pdf_file_path']);
|
||||
// }
|
||||
|
||||
// if ($email->send()) {
|
||||
|
||||
// log_message('debug', 'Email Success to agent plan_id = ' .$plan_id.'email = ' . $value['email']);
|
||||
|
||||
// } else {
|
||||
// log_message('debug', 'Email sending failed: agent plan_id = ' .$plan_id.'email = ' . $value['email'].'error = '.$email->printDebugger(['headers']));
|
||||
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -53,6 +53,7 @@ if (!function_exists('palnStatusHandler')) {
|
||||
$a1Id = $userData['first_approver'];
|
||||
$a2Id = $userData['second_approver'];
|
||||
$a3Id = $userData['third_approver'];
|
||||
$a4Id = $userData['fourth_approver'];
|
||||
|
||||
$groupData = $groupModel->where('group_id', $groupId)->first();
|
||||
if (!$groupData) {
|
||||
@ -110,25 +111,29 @@ if (!function_exists('palnStatusHandler')) {
|
||||
log_message('error', "Policy service details not found for service_id: {$topPriorityService['service_id']}, policy_id: {$policyId}");
|
||||
return false;
|
||||
}
|
||||
|
||||
// dd($policyServiceDetails);
|
||||
|
||||
|
||||
$isExceptional = $planData['exceptional_plan_reason'] !== null && $planData['exceptional_plan_reason'] !== '';
|
||||
// dd($isExceptional);
|
||||
|
||||
if ($isExceptional) {
|
||||
$policyA1Action = $policyServiceDetails['a1_exceptional_action'];
|
||||
$policyA2Action = $policyServiceDetails['a2_exceptional_action'];
|
||||
$policyA3Action = $policyServiceDetails['a3_exceptional_action'];
|
||||
$policyA4Action = $policyServiceDetails['a4_exceptional_action'];
|
||||
$policyParallelAction = $policyServiceDetails['exceptional_parallel_process_from'];
|
||||
} else if ($is_data_edited) {
|
||||
$policyA1Action = $policyServiceDetails['a1_amendment_action'];
|
||||
$policyA2Action = $policyServiceDetails['a2_amendment_action'];
|
||||
$policyA3Action = $policyServiceDetails['a3_amendment_action'];
|
||||
$policyA4Action = $policyServiceDetails['a4_amendment_action'];
|
||||
$policyParallelAction = $policyServiceDetails['amendment_parallel_process_from'];
|
||||
} else {
|
||||
$policyA1Action = $policyServiceDetails['a1_action'];
|
||||
$policyA2Action = $policyServiceDetails['a2_action'];
|
||||
$policyA3Action = $policyServiceDetails['a3_action'];
|
||||
$policyA4Action = 'None';
|
||||
$policyParallelAction = $policyServiceDetails['parallel_process_from'];
|
||||
}
|
||||
|
||||
@ -145,9 +150,14 @@ if (!function_exists('palnStatusHandler')) {
|
||||
'a3_id' => $a3Id,
|
||||
'a3_action' => $policyA3Action,
|
||||
'is_a3_action_done' => ($policyA3Action == 'None') ? 1 : 0,
|
||||
'a4_id' => $a4Id,
|
||||
'a4_action' => $policyA4Action,
|
||||
'is_a4_action_done' => ($policyA4Action == 'None') ? 1 : 0,
|
||||
'parallel_process_from' => $policyParallelAction
|
||||
];
|
||||
|
||||
// dd($data);
|
||||
|
||||
if ($is_data_edited == false) {
|
||||
log_message('info', "Creating new plan status for plan_id: {$plan_id}");
|
||||
$planStatusModel->insert($data);
|
||||
@ -345,17 +355,25 @@ if (!function_exists('updatePlanStatus')) {
|
||||
$a3ApproveCount = count($a3);
|
||||
}
|
||||
|
||||
$a4 = $planStatusModel->where('plan_id',$plan_id)->where('a4_action','Approval')->where('is_active',1)->findAll();
|
||||
$a4ApproveSum = 0;
|
||||
$a4ApproveCount = 0;
|
||||
if(count($a4))
|
||||
{
|
||||
$a4ApproveSum = array_sum(array_column($a4, 'is_a4_action_done'));
|
||||
$a4ApproveCount = count($a4);
|
||||
}
|
||||
|
||||
|
||||
$count = ( $a1ApproveCount + $a2ApproveCount + $a3ApproveCount + $a4ApproveCount);
|
||||
$sum = ( $a1ApproveSum + $a2ApproveSum + $a3ApproveSum + $a4ApproveSum);
|
||||
|
||||
$count = ( $a1ApproveCount + $a2ApproveCount + $a3ApproveCount);
|
||||
$sum = ( $a1ApproveSum + $a2ApproveSum + $a3ApproveSum);
|
||||
|
||||
|
||||
if($count == $sum)
|
||||
{
|
||||
// Approved
|
||||
$planModel->set(['status'=>3])->where('plan_id',$plan_id)->update();
|
||||
//send main to agent
|
||||
send_email_agent(env('ORG_id') , $plan_id);
|
||||
|
||||
}else if($count != $sum && $sum > 0)
|
||||
{
|
||||
//Partially Approved
|
||||
@ -466,6 +484,34 @@ if (!function_exists('getCurrentPlanStatus')) {
|
||||
}
|
||||
}
|
||||
|
||||
$a4 = $planStatusModel->where('plan_id',$plan_id)->where('a4_action','Approval')->where('is_active',1)->findAll();
|
||||
if(count($a4))
|
||||
{
|
||||
$user4 = $userModel->where('user_id', $a4[0]['a4_action_done_by'])->first();
|
||||
if(!$user4){
|
||||
$user4 = $userModel->where('user_id', $a4[0]['a4_id'])->first();
|
||||
}
|
||||
$hasRejectReason = !empty(array_filter($a4, fn($row) => !empty($row['a4_reject_reason'])));
|
||||
if($user4)
|
||||
{
|
||||
$userId = $user4['user_id'];
|
||||
|
||||
$a4ApproveSum = array_sum(array_column($a4, 'is_a4_action_done'));
|
||||
$a4ApproveCount = count($a4);
|
||||
|
||||
$a4Status['a4_id'] = $userId;
|
||||
if($a4ApproveSum == $a4ApproveCount)
|
||||
{
|
||||
$a4Status['a4_status'] = 'Plan approved by '.$user4['first_name'].' '.$user4['last_name'];
|
||||
}else if($hasRejectReason){
|
||||
$a4Status['a4_status'] = 'Plan rejected by '.$user4['first_name'].' '.$user4['last_name'].', Reason-'.$a4[0]['a4_reject_reason'];
|
||||
}else{
|
||||
$a4Status['a4_status'] = 'Plan approval pending from '.$user4['first_name'].' '.$user4['last_name'];
|
||||
}
|
||||
array_push($currentStatus,$a4Status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $currentStatus;
|
||||
|
||||
@ -473,6 +519,7 @@ if (!function_exists('getCurrentPlanStatus')) {
|
||||
}
|
||||
|
||||
if (!function_exists('getPlanApproverAction')) {
|
||||
// initially written code without parallel , sequential
|
||||
// function getPlanApproverAction($plan_id , )
|
||||
// {
|
||||
|
||||
@ -578,33 +625,129 @@ if (!function_exists('getPlanApproverAction')) {
|
||||
|
||||
// }
|
||||
|
||||
// 3 level of parallel , sequential
|
||||
// function getPlanApproverAction($plan_id)
|
||||
// {
|
||||
// $planStatusModel = new PlanStatusModel();
|
||||
// $userModel = new UserModel();
|
||||
// $result = ['approver_data' => []];
|
||||
// $serviceIds = [];
|
||||
|
||||
// // A1, A2, A3 - handle all same way
|
||||
// $approverAction = [
|
||||
// ['key' => 'a1', 'approver' => 1],
|
||||
// ['key' => 'a2', 'approver' => 2],
|
||||
// ['key' => 'a3', 'approver' => 3],
|
||||
// ];
|
||||
|
||||
// foreach ($approverAction as $stage) {
|
||||
// $field = $stage['key'];
|
||||
// $approverNumber = $stage['approver'];
|
||||
// $actionField = "{$field}_action";
|
||||
// $idField = "{$field}_id";
|
||||
// $doneField = "is_{$field}_action_done";
|
||||
|
||||
// $record = $planStatusModel->where('plan_id', $plan_id)
|
||||
// ->whereIn($actionField, ['Approval', 'Notification', 'None'])
|
||||
// ->where('is_active', 1)
|
||||
// ->first();
|
||||
|
||||
// if ($record) {
|
||||
// $user = $userModel->where('user_id', $record[$idField])->first();
|
||||
// if ($user) {
|
||||
// $result['approver_data'][] = [
|
||||
// 'approver' => $approverNumber,
|
||||
// 'user_id' => $record[$idField],
|
||||
// 'email' => $user['email'],
|
||||
// 'action' => $record[$actionField],
|
||||
// 'is_action_done' => $record[$doneField],
|
||||
// 'where_key' => $idField,
|
||||
// 'action_key' => $actionField,
|
||||
// 'action_done_key' => $doneField,
|
||||
// ];
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Get parallel process value
|
||||
// $statusData = $planStatusModel->where('plan_id', $plan_id)->where('is_active', 1)->first();
|
||||
// $result['parallel_process_from'] = $statusData['parallel_process_from'] ?? null;
|
||||
|
||||
|
||||
// $parallelFrom = (int) $result['parallel_process_from'];
|
||||
|
||||
// foreach ($result['approver_data'] as $key => &$approver) {
|
||||
// $approver['status'] = 'pending'; // default
|
||||
|
||||
// if ($parallelFrom === 1) {
|
||||
// // All parallel
|
||||
// $approver['status'] = 'active';
|
||||
// } elseif ($parallelFrom === 2) {
|
||||
// if ($approver['approver'] === 1) {
|
||||
// $approver['status'] = 'active';
|
||||
// } elseif (in_array($approver['approver'], [2, 3])) {
|
||||
// // Check if approver 1 is done
|
||||
// $a1Done = false;
|
||||
// foreach ($result['approver_data'] as $a) {
|
||||
// if ($a['approver'] === 1 && $a['is_action_done']) {
|
||||
// $a1Done = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// $approver['status'] = $a1Done ? 'active' : 'waiting';
|
||||
// }
|
||||
// } elseif ($parallelFrom === 3) {
|
||||
// // Sequential: 1 -> 2 -> 3
|
||||
// $a1Done = false;
|
||||
// $a2Done = false;
|
||||
|
||||
// foreach ($result['approver_data'] as $a) {
|
||||
// if ($a['approver'] === 1 && $a['is_action_done']) $a1Done = true;
|
||||
// if ($a['approver'] === 2 && $a['is_action_done']) $a2Done = true;
|
||||
// }
|
||||
|
||||
// if ($approver['approver'] === 1) {
|
||||
// $approver['status'] = 'active';
|
||||
// } elseif ($approver['approver'] === 2) {
|
||||
// $approver['status'] = $a1Done ? 'active' : 'waiting';
|
||||
// } elseif ($approver['approver'] === 3) {
|
||||
// $approver['status'] = ($a1Done && $a2Done) ? 'active' : 'waiting';
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// unset($approver); // best practice when using & reference in foreach
|
||||
|
||||
|
||||
// return $result;
|
||||
// }
|
||||
|
||||
|
||||
// latest 4 level of parallel , sequential
|
||||
function getPlanApproverAction($plan_id)
|
||||
{
|
||||
$planStatusModel = new PlanStatusModel();
|
||||
$userModel = new UserModel();
|
||||
$result = ['approver_data' => []];
|
||||
$serviceIds = [];
|
||||
|
||||
// A1, A2, A3 - handle all same way
|
||||
|
||||
$approverAction = [
|
||||
['key' => 'a1', 'approver' => 1],
|
||||
['key' => 'a2', 'approver' => 2],
|
||||
['key' => 'a3', 'approver' => 3],
|
||||
['key' => 'a4', 'approver' => 4],
|
||||
];
|
||||
|
||||
|
||||
foreach ($approverAction as $stage) {
|
||||
$field = $stage['key'];
|
||||
$approverNumber = $stage['approver'];
|
||||
$actionField = "{$field}_action";
|
||||
$idField = "{$field}_id";
|
||||
$doneField = "is_{$field}_action_done";
|
||||
|
||||
$mailField = "is_{$field}_mail_send";
|
||||
|
||||
$record = $planStatusModel->where('plan_id', $plan_id)
|
||||
->whereIn($actionField, ['Approval', 'Notification', 'None'])
|
||||
->where('is_active', 1)
|
||||
->first();
|
||||
|
||||
->whereIn($actionField, ['Approval', 'Notification', 'None'])
|
||||
->where('is_active', 1)
|
||||
->first();
|
||||
if ($record) {
|
||||
$user = $userModel->where('user_id', $record[$idField])->first();
|
||||
if ($user) {
|
||||
@ -617,62 +760,70 @@ if (!function_exists('getPlanApproverAction')) {
|
||||
'where_key' => $idField,
|
||||
'action_key' => $actionField,
|
||||
'action_done_key' => $doneField,
|
||||
'mail_send_key' => $mailField,
|
||||
'is_mail_send' => $record[$mailField],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get parallel process value
|
||||
|
||||
$statusData = $planStatusModel->where('plan_id', $plan_id)->where('is_active', 1)->first();
|
||||
$result['parallel_process_from'] = $statusData['parallel_process_from'] ?? null;
|
||||
|
||||
|
||||
$parallelFrom = (int) $result['parallel_process_from'];
|
||||
|
||||
foreach ($result['approver_data'] as $key => &$approver) {
|
||||
foreach ($result['approver_data'] as &$approver) {
|
||||
$approver['status'] = 'pending'; // default
|
||||
|
||||
// Flags
|
||||
$a1Done = $a2Done = $a3Done = false;
|
||||
foreach ($result['approver_data'] as $a) {
|
||||
if ($a['approver'] === 1 && $a['is_action_done']) $a1Done = true;
|
||||
if ($a['approver'] === 2 && $a['is_action_done']) $a2Done = true;
|
||||
if ($a['approver'] === 3 && $a['is_action_done']) $a3Done = true;
|
||||
}
|
||||
|
||||
if ($parallelFrom === 1) {
|
||||
// All parallel
|
||||
// All approvers active
|
||||
$approver['status'] = 'active';
|
||||
|
||||
} elseif ($parallelFrom === 2) {
|
||||
if ($approver['approver'] === 1) {
|
||||
$approver['status'] = 'active';
|
||||
} elseif (in_array($approver['approver'], [2, 3])) {
|
||||
// Check if approver 1 is done
|
||||
$a1Done = false;
|
||||
foreach ($result['approver_data'] as $a) {
|
||||
if ($a['approver'] === 1 && $a['is_action_done']) {
|
||||
$a1Done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} elseif (in_array($approver['approver'], [2, 3, 4])) {
|
||||
$approver['status'] = $a1Done ? 'active' : 'waiting';
|
||||
}
|
||||
} elseif ($parallelFrom === 3) {
|
||||
// Sequential: 1 -> 2 -> 3
|
||||
$a1Done = false;
|
||||
$a2Done = false;
|
||||
|
||||
foreach ($result['approver_data'] as $a) {
|
||||
if ($a['approver'] === 1 && $a['is_action_done']) $a1Done = true;
|
||||
if ($a['approver'] === 2 && $a['is_action_done']) $a2Done = true;
|
||||
} elseif ($parallelFrom === 3) {
|
||||
if ($approver['approver'] === 1) {
|
||||
$approver['status'] = 'active';
|
||||
} elseif ($approver['approver'] === 2) {
|
||||
$approver['status'] = $a1Done ? 'active' : 'waiting';
|
||||
} elseif (in_array($approver['approver'], [3, 4])) {
|
||||
$approver['status'] = ($a1Done && $a2Done) ? 'active' : 'waiting';
|
||||
}
|
||||
|
||||
} elseif ($parallelFrom === 4) {
|
||||
if ($approver['approver'] === 1) {
|
||||
$approver['status'] = 'active';
|
||||
} elseif ($approver['approver'] === 2) {
|
||||
$approver['status'] = $a1Done ? 'active' : 'waiting';
|
||||
} elseif ($approver['approver'] === 3) {
|
||||
$approver['status'] = ($a1Done && $a2Done) ? 'active' : 'waiting';
|
||||
} elseif ($approver['approver'] === 4) {
|
||||
$approver['status'] = ($a1Done && $a2Done && $a3Done) ? 'active' : 'waiting';
|
||||
}
|
||||
} else {
|
||||
$approver['status'] = 'pending'; // fallback
|
||||
}
|
||||
}
|
||||
unset($approver); // best practice when using & reference in foreach
|
||||
unset($approver); // clean reference
|
||||
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -735,6 +886,23 @@ if (!function_exists('getApproverCurrentAction')) {
|
||||
}
|
||||
}
|
||||
|
||||
$a4 = $planStatusModel->where('plan_id',$plan_id)->where('a4_id',$user_id)->where('a4_action','Approval')->where('is_active',1)->findAll();
|
||||
if(count($a4))
|
||||
{
|
||||
$hasRejectReason = !empty(array_filter($a4, fn($row) => !empty($row['a4_reject_reason'])));
|
||||
$a4ApproveSum = array_sum(array_column($a4, 'is_a4_action_done'));
|
||||
$a4ApproveCount = count($a4);
|
||||
|
||||
if($a4ApproveSum == $a4ApproveCount)
|
||||
{
|
||||
return 'Approved';
|
||||
}else if($hasRejectReason){
|
||||
return 'Rejected';
|
||||
}else{
|
||||
return 'Approval pending';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -17,6 +17,7 @@ class MailTemplateModel extends Model
|
||||
'template_name',
|
||||
'subject',
|
||||
'body_html',
|
||||
'image_location',
|
||||
'created_by',
|
||||
'updated_by',
|
||||
'is_active',
|
||||
|
||||
@ -46,7 +46,8 @@ class PlanModel extends Model
|
||||
IB.dropdown_value as is_billable_value,
|
||||
POT.dropdown_value as purpose_of_travel_value,
|
||||
FD.dropdown_value as functional_department_value,
|
||||
Dep.name as cost_center_value'
|
||||
Dep.name as cost_center_value,
|
||||
Forex.forex_id'
|
||||
)
|
||||
->join('m_users U', 'U.user_id = m_plan.user_id ', 'left')
|
||||
->join('m_users C', 'C.user_id = m_plan.created_by ', 'left')
|
||||
@ -57,6 +58,7 @@ class PlanModel extends Model
|
||||
->join('m_dropdown POT', 'POT.dropdown_key = m_plan.purpose_of_travel AND POT.dropdown = "plan_purpose_of_travel"', 'left')
|
||||
->join('m_dropdown FD', 'FD.dropdown_key = m_plan.functional_department AND FD.dropdown = "plan_functional_department"', 'left')
|
||||
->join('m_department Dep', 'Dep.department_id = m_plan.cost_center_id ', 'left')
|
||||
->join('c_forex Forex', 'Forex.plan_id = m_plan.plan_id ', 'left')
|
||||
->where('m_plan.is_active', 1)->where('m_plan.org_id', $org_id);
|
||||
|
||||
if($getBy == 'ALL' || $getBy == null)
|
||||
|
||||
@ -12,9 +12,10 @@ class PlanStatusModel extends Model
|
||||
protected $allowedFields = [
|
||||
'plan_id',
|
||||
'service_id',
|
||||
'a1_id', 'a1_action', 'is_a1_action_done', 'a1_reject_reason', 'a1_action_done_on','a1_action_done_by',
|
||||
'a2_id', 'a2_action', 'is_a2_action_done', 'a2_reject_reason', 'a2_action_done_on','a2_action_done_by',
|
||||
'a3_id', 'a3_action', 'is_a3_action_done', 'a3_reject_reason', 'a3_action_done_on','a3_action_done_by',
|
||||
'a1_id', 'a1_action', 'is_a1_action_done', 'a1_reject_reason', 'a1_action_done_on','a1_action_done_by','is_a1_mail_send',
|
||||
'a2_id', 'a2_action', 'is_a2_action_done', 'a2_reject_reason', 'a2_action_done_on','a2_action_done_by','is_a2_mail_send',
|
||||
'a3_id', 'a3_action', 'is_a3_action_done', 'a3_reject_reason', 'a3_action_done_on','a3_action_done_by','is_a3_mail_send',
|
||||
'a4_id', 'a4_action', 'is_a4_action_done', 'a4_reject_reason', 'a4_action_done_on','a4_action_done_by','is_a4_mail_send',
|
||||
'parallel_process_from',
|
||||
'is_active',
|
||||
'created_on', 'created_by'
|
||||
|
||||
@ -29,6 +29,7 @@ class PolicyDetailsModel extends Model
|
||||
'a1_amendment_action',
|
||||
'a2_amendment_action',
|
||||
'a3_amendment_action',
|
||||
'a4_amendment_action',
|
||||
'amendment_parallel_process_from',
|
||||
'is_active',
|
||||
'created_on',
|
||||
|
||||
@ -74,6 +74,7 @@ class ReportsModel extends Model
|
||||
GROUP BY plan_id
|
||||
) AS al ON m_plan.plan_id = al.plan_id
|
||||
|
||||
|
||||
WHERE
|
||||
mts.is_active = 1
|
||||
AND mts.status_value = 'Approved'
|
||||
@ -415,8 +416,11 @@ class ReportsModel extends Model
|
||||
|
||||
JOIN m_plan mp ON cf.plan_id = mp.plan_id
|
||||
|
||||
WHERE cf.created_on >= DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY)
|
||||
AND cf.created_on < DATE_ADD(DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY), INTERVAL 7 DAY)
|
||||
WHERE cf.created_on >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
|
||||
AND cf.created_on < DATE_ADD(CURDATE(), INTERVAL 1 DAY)
|
||||
|
||||
-- WHERE cf.created_on >= DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY)
|
||||
-- AND cf.created_on < DATE_ADD(DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY), INTERVAL 7 DAY)
|
||||
|
||||
-- previous week
|
||||
-- WHERE cf.created_on >= DATE_SUB(CURDATE(), INTERVAL (WEEKDAY(CURDATE()) + 7) DAY)
|
||||
@ -482,8 +486,11 @@ class ReportsModel extends Model
|
||||
|
||||
JOIN m_plan mp ON ca.plan_id = mp.plan_id
|
||||
|
||||
WHERE ca.created_on >= DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY)
|
||||
AND ca.created_on < DATE_ADD(DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY), INTERVAL 7 DAY)
|
||||
WHERE ca.created_on >= DATE_SUB(CURDATE(), INTERVAL 6 DAY)
|
||||
AND ca.created_on < DATE_ADD(CURDATE(), INTERVAL 1 DAY)
|
||||
|
||||
-- WHERE ca.created_on >= DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY)
|
||||
-- AND ca.created_on < DATE_ADD(DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY), INTERVAL 7 DAY)
|
||||
|
||||
-- previous week
|
||||
-- WHERE cf.created_on >= DATE_SUB(CURDATE(), INTERVAL (WEEKDAY(CURDATE()) + 7) DAY)
|
||||
@ -547,8 +554,11 @@ class ReportsModel extends Model
|
||||
|
||||
JOIN m_plan mp ON cf.plan_id = mp.plan_id
|
||||
|
||||
WHERE cf.created_on >= DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY)
|
||||
AND cf.created_on < DATE_ADD(DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY), INTERVAL 7 DAY)
|
||||
WHERE cf.created_on >= DATE_SUB(CURDATE(), INTERVAL 6 DAY)
|
||||
AND cf.created_on < DATE_ADD(CURDATE(), INTERVAL 1 DAY)
|
||||
|
||||
-- WHERE cf.created_on >= DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY)
|
||||
-- AND cf.created_on < DATE_ADD(DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY), INTERVAL 7 DAY)
|
||||
|
||||
-- previous week
|
||||
-- WHERE cf.created_on >= DATE_SUB(CURDATE(), INTERVAL (WEEKDAY(CURDATE()) + 7) DAY)
|
||||
|
||||
@ -10,7 +10,7 @@ class UserModel extends Model
|
||||
protected $primaryKey = 'user_id'; // Primary key
|
||||
|
||||
// Fields that can be mass assigned
|
||||
protected $allowedFields = ['first_name','last_name','password','email','mobile_no','alternate_mobile_no','date_of_birth','address','gender','postal_code','country_code','employee_code','role_id','department_id','group_id','first_approver','first_approver_email','second_approver','second_approver_email','third_approver','third_approver_email','exceptional_approver','exceptional_approver_email','user_type','passport_number','place_of_issue','passport_document','passport_firstname','passport_middlename','passport_lastname','nationality','date_of_issue','date_of_expiry','created_on','created_by','updated_on','updated_by','is_active','org_id', 'temp_password', 'forex_pre_paid_card_number', 'emergency_contact_number', 'd_seat_preference', 'd_meal_preference', 'i_seat_preference', 'i_meal_preference', 'agent_supported_service_ids', 'd_additonalInfo', 'i_additonalInfo', 'forex_expiry_date', 'delegated_to_user_id', 'delegation_start_date', 'delegation_end_date','last_login_at','company_name'];
|
||||
protected $allowedFields = ['first_name','last_name','password','email','mobile_no','alternate_mobile_no','date_of_birth','address','gender','postal_code','country_code','employee_code','role_id','department_id','group_id','first_approver','first_approver_email','second_approver','second_approver_email','third_approver','third_approver_email','fourth_approver','fourth_approver_email','user_type','passport_number','place_of_issue','passport_document','passport_firstname','passport_middlename','passport_lastname','nationality','date_of_issue','date_of_expiry','created_on','created_by','updated_on','updated_by','is_active','org_id', 'temp_password', 'forex_pre_paid_card_number', 'emergency_contact_number', 'd_seat_preference', 'd_meal_preference', 'i_seat_preference', 'i_meal_preference', 'agent_supported_service_ids', 'd_additonalInfo', 'i_additonalInfo', 'forex_expiry_date', 'delegated_to_user_id', 'delegation_start_date', 'delegation_end_date','last_login_at','company_name'];
|
||||
|
||||
// Specify the return type of the results
|
||||
protected $returnType = 'array';
|
||||
@ -91,10 +91,9 @@ public function updateApprover(string $approverType, array $insertedIds)
|
||||
'first' => ['column' => 'first_approver', 'email' => 'first_approver_email'],
|
||||
'second' => ['column' => 'second_approver', 'email' => 'second_approver_email'],
|
||||
'third' => ['column' => 'third_approver', 'email' => 'third_approver_email'],
|
||||
'exceptional' => ['column' => 'exceptional_approver', 'email' => 'exceptional_approver_email']
|
||||
'fourth' => ['column' => 'fourth_approver', 'email' => 'fourth_approver_email']
|
||||
];
|
||||
|
||||
|
||||
$column = $validTypes[$approverType]['column'];
|
||||
$emailCol = $validTypes[$approverType]['email'];
|
||||
|
||||
|
||||
@ -174,6 +174,7 @@
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="invoice-content-table" >
|
||||
<tr class="invoice-section">
|
||||
<td class="quotation-company">
|
||||
@ -340,6 +341,43 @@
|
||||
</table>
|
||||
|
||||
|
||||
<?php if (count($data['status_details'])) {
|
||||
|
||||
$statusHtml = '<h4 style="margin-bottom: 10px;">Trip Status:</h4>';
|
||||
$statusHtml .= '<ul style="
|
||||
list-style: none;
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 6px;
|
||||
background-color: #f9f9f9;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
||||
">';
|
||||
|
||||
foreach ($data['status_details'] as $key => $value) {
|
||||
|
||||
if (isset($value['a1_status'])) {
|
||||
$statusHtml .= '<li style="margin-bottom: 8px;"><strong>Approver 1:</strong> ' . $value['a1_status'] . '</li>';
|
||||
}
|
||||
|
||||
if (isset($value['a2_status'])) {
|
||||
$statusHtml .= '<li style="margin-bottom: 8px;"><strong>Approver 2:</strong> ' . $value['a2_status'] . '</li>';
|
||||
}
|
||||
|
||||
if (isset($value['a3_status'])) {
|
||||
$statusHtml .= '<li style="margin-bottom: 8px;"><strong>Approver 3:</strong> ' . $value['a3_status'] . '</li>';
|
||||
}
|
||||
|
||||
if (isset($value['a4_status'])) {
|
||||
$statusHtml .= '<li style="margin-bottom: 8px;"><strong>Approver 4:</strong> ' . $value['a4_status'] . '</li>';
|
||||
}
|
||||
}
|
||||
|
||||
$statusHtml .= '</ul>';
|
||||
|
||||
echo $statusHtml;
|
||||
} ?>
|
||||
|
||||
|
||||
|
||||
<!--- Flight --->
|
||||
|
||||
@ -412,7 +450,6 @@
|
||||
</td>
|
||||
<td class="quo-heading1">
|
||||
<div class="qsub-heading" style="color: #6b7577; margin-bottom: 5px;">Class</div>
|
||||
<div class="qsub-desc"><?= esc($trainvalue['train_class']) ?></div>
|
||||
<span <?php if($trainvalue['is_this_exceptional'] == 1){ ?> style="color: #960000;" <?php } ?> ><?= esc($trainvalue['train_class']) ?></span> <br/>
|
||||
<?php if($trainvalue['is_this_exceptional'] == 1){ ?> <span style="font-size: 12px"> allowed for <?= $data['allowed_class']['train'] ?> </span><?php } ?>
|
||||
</td>
|
||||
@ -514,17 +551,10 @@
|
||||
<div class="qsub-heading" style="color: #6b7577; margin-bottom: 5px;">City</div>
|
||||
<div class="qsub-desc"><?= esc($accomodationvalue['destination_city']) ?></div>
|
||||
</td>
|
||||
<td class="quo-heading1">
|
||||
<td class="quo-heading1" width="25%">
|
||||
<div class="qsub-heading" style="color: #6b7577; margin-bottom: 5px;">Hotel Name</div>
|
||||
<div class="qsub-desc"><?= esc($accomodationvalue['hotel_name']) ?><br/></div>
|
||||
</td>
|
||||
<td class="quo-heading1">
|
||||
<div class="qsub-heading" style="color: #6b7577; margin-bottom: 5px;" >Category</div>
|
||||
<div class="qsub-desc" >
|
||||
<span <?php if($accomodationvalue['is_this_exceptional'] == 1){ ?> style="color: #960000;" <?php } ?> ><?= esc($accomodationvalue['hotel_class']) ?></span> <br/>
|
||||
<?php if($accomodationvalue['is_this_exceptional'] == 1){ ?> <span style="font-size: 12px"> allowed for <?= $data['allowed_class']['hotel'] ?> </span><?php } ?>
|
||||
</div>
|
||||
</td>
|
||||
<td class="quo-heading1">
|
||||
<div class="qsub-heading" style="color: #6b7577; margin-bottom: 5px;">Checkin Date & Time</div>
|
||||
<div class="qsub-desc"><?= date('d, M y', strtotime($accomodationvalue['checkin_date'])) ?> <?= date('h:i A', strtotime($accomodationvalue['checkin_time'])) ?> </div>
|
||||
@ -533,6 +563,13 @@
|
||||
<div class="qsub-heading" style="color: #6b7577; margin-bottom: 5px;">Checkout Date & Time</div>
|
||||
<div class="qsub-desc"><?= date('d, M y', strtotime($accomodationvalue['checkout_date'])) ?> <?= date('h:i A', strtotime($accomodationvalue['checkout_time'])) ?> </div>
|
||||
</td>
|
||||
<td class="quo-heading1">
|
||||
<div class="qsub-heading" style="color: #6b7577; margin-bottom: 5px;" >Category</div>
|
||||
<div class="qsub-desc" >
|
||||
<span <?php if($accomodationvalue['is_this_exceptional'] == 1){ ?> style="color: #960000;" <?php } ?> ><?= esc($accomodationvalue['hotel_class']) ?></span> <br/>
|
||||
<?php if($accomodationvalue['is_this_exceptional'] == 1){ ?> <span style="font-size: 12px"> allowed for <?= $data['allowed_class']['hotel'] ?> </span><?php } ?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</table></div>
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 9.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 9.4 KiB |
BIN
writable/pdf/trips/trip_35.pdf
Normal file
BIN
writable/pdf/trips/trip_35.pdf
Normal file
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user