Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 21
CRAP
0.00% covered (danger)
0.00%
0 / 579
CustomApplicationService
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 21
9120.00
0.00% covered (danger)
0.00%
0 / 579
 __construct
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 3
 __clone
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 2
 getInstance
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 5
 getAllAssignedApplicationsToStudent
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 33
 getAllStudentApplicationsAssignedToStaff
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 22
 getAllApplicationsForReport
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 17
 getNotAppliedStudentsList
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 40
 getAppliedStudents
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 25
 getApplicationDetails
0.00% covered (danger)
0.00%
0 / 1
72.00
0.00% covered (danger)
0.00%
0 / 46
 getAssignedApplicationDetails
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 40
 checkApplicationIsAssignedToStudentBatch
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 21
 saveApplicationResponse
0.00% covered (danger)
0.00%
0 / 1
72.00
0.00% covered (danger)
0.00%
0 / 45
 updateCustomApplication
0.00% covered (danger)
0.00%
0 / 1
156.00
0.00% covered (danger)
0.00%
0 / 78
 deleteCustomApplication
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 createCustomApplicationLog
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 14
 createCustomApplicationWorkFlowInstance
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 14
 approveOrRejectApplication
0.00% covered (danger)
0.00%
0 / 1
462.00
0.00% covered (danger)
0.00%
0 / 72
 processCustomApplicationReject
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 36
 processCustomApplicationApproval
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 36
 updateCustomApplicationLog
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 updateApplicationLog
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
<?php
/**
 * Created By: jithinvijayan
 * Date: 05/12/19
 */
namespace com\linways\core\ams\professional\service;
use com\linways\workflow\api\Workflow;
use com\linways\workflow\api\WorkflowInstance;
use com\linways\core\ams\professional\util\CommonUtil;
use com\linways\workflow\api\constants\WorkflowActions;
use com\linways\core\ams\professional\constant\Messages;
use com\linways\core\ams\professional\constant\UserType;
use com\linways\core\ams\professional\dto\CustomApplication;
use com\linways\core\ams\professional\constant\StatusConstants;
use com\linways\core\ams\professional\dto\CustomApplicationLog;
use com\linways\workflow\api\request\MoveToNextStateApiRequest;
use com\linways\core\ams\professional\constant\CreatedWorkFlows;
use com\linways\core\ams\professional\exception\ProfessionalException;
use com\linways\core\ams\professional\request\UpdateCustomApplicationLog;
use com\linways\core\ams\professional\mapper\CustomApplicationServiceMapper;
use com\linways\core\ams\professional\request\SaveApplicationResponseRequest;
use com\linways\core\ams\professional\request\UpdateCustomApplicationRequest;
use com\linways\core\ams\professional\response\NotAppliedStudentListResponse;
use com\linways\core\ams\professional\request\GetNotAppliedStudentsListRequest;
use com\linways\core\ams\professional\request\CreateCustomApplicationLogRequest;
use com\linways\workflow\api\request\UpdateAllPendingTransitionAssigneesRequest;
use com\linways\core\ams\professional\request\GetCustomApplicationDetailsRequest;
use com\linways\core\ams\professional\request\ApproveOrRejectCustomApplicationRequest;
class CustomApplicationService extends BaseService
{
    /**
     * Presence of a static member variable
     *
     * @var null
     */
    private static $_instance = null;
    /**
     * Mapper variable
     * @var array
     */
    private $mapper = [];
    /**
     * Initialise mapper, logger, hooks here
     *
     * ReportGenderService constructor.
     */
    private function __construct()
    {
        $this->mapper = CustomApplicationServiceMapper::getInstance()->getMapper();
    }
    /**
     * Prevent any object or instance of that class to be cloned
     */
    private function __clone()
    {
    }
    /**
     * Have a single globally accessible static method
     *
     * @return CustomApplicationService|null
     */
    public static function getInstance()
    {
        if (!is_object(self::$_instance))
            self::$_instance = new self ();
        return self::$_instance;
    }
    /**
     * @param $studentId
     * @param null $applicationId
     * @return Object
     * @throws ProfessionalException
     * @author jithinvijayan
     */
    public function getAllAssignedApplicationsToStudent($studentId, $applicationId = null)
    {
        $studentId = (int)$this->realEscapeString($studentId);
        if (empty($studentId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_STUDENT_ID, "Invalid request sent");
        }
        $userType = UserType::STUDENT;
        $dateObject = new \DateTime();
        $date = $dateObject->format("Y-m-d H:i:s");
        $sql = "SELECT ca.id,ca.name,ca.description,car.id as registrationId,car.status,
                DATE_FORMAT(ca.start_date,'%d-%m-%Y %h:%i %p') as startDate,
                DATE_FORMAT(ca.end_date,'%d-%m-%Y %h:%i %p') as endDate,
                IF (DATE_FORMAT(CURRENT_TIMESTAMP(),'%Y-%m-%d %H:%i:%s')>=ca.start_date 
                AND DATE_FORMAT(CURRENT_TIMESTAMP(),'%Y-%m-%d %H:%i:%s')<=ca.end_date,false,true) as isExpired
                FROM application_types at  
                INNER JOIN custom_applications ca ON ca.application_type_id = at.id
                INNER JOIN custom_application_fields caf ON ca.id = caf.custom_application_id
                INNER JOIN custom_application_assigned_batches caab ON ca.id = caab.custom_application_id
                INNER JOIN batches b ON b.batchID = caab.batch_id
                INNER JOIN studentaccount sa ON sa.batchID =b.batchID AND sa.studentID = $studentId
                LEFT JOIN custom_application_response car ON ca.id = car.custom_application_id 
                AND car.user_type  ='" . $userType . "' AND car.user_id=sa.studentID
                WHERE 1=1 ";
//                DATE_FORMAT(CURRENT_TIMESTAMP(),'%Y-%m-%d %H:%i:%s')>=ca.start_date
//                AND DATE_FORMAT(CURRENT_TIMESTAMP(),'%Y-%m-%d %H:%i:%s')<=ca.end_date";
        try {
            if (!empty($applicationId)) {
                $sql .= " ca.id=$applicationId";
                return $this->executeQueryForObject($sql);
            } else {
                return $this->executeQueryForList($sql);
            }
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @param $staffId
     * @return Object
     * @throws ProfessionalException
     * @author jithinvijayan
     */
    public function getAllStudentApplicationsAssignedToStaff($staffId)
    {
        $staffId = (int)$this->realEscapeString($staffId);
        if (empty($staffId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_STAFF_ID, "Invalid request sent");
        }
        $userType = UserType::STUDENT;
        $sql = "SELECT ca.id,ca.name,ca.description,COUNT(DISTINCT car.id) as totalRegisteredStudents
                FROM application_types at  
                INNER JOIN custom_applications ca ON ca.application_type_id = at.id
                INNER JOIN custom_application_fields caf ON ca.id = caf.custom_application_id
                INNER JOIN custom_application_assigned_batches caab ON ca.id = caab.custom_application_id
                INNER JOIN batches b ON b.batchID = caab.batch_id
                INNER JOIN custom_application_response car ON ca.id = car.custom_application_id 
                AND car.user_type  ='" . $userType . "' AND JSON_EXTRACT(car.response,'$.staff')='$staffId'
                INNER JOIN studentaccount sa ON sa.batchID =b.batchID AND sa.studentID = car.user_id
                GROUP BY ca.id";
        try {
            return $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @return Object
     * @throws ProfessionalException
     * @author jithinvijayan
     */
    public function getAllApplicationsForReport()
    {
        $userType = UserType::STUDENT;
        $sql = "SELECT ca.id,ca.name,ca.description,COUNT(DISTINCT car.id) as totalRegisteredStudents
                FROM application_types at  
                INNER JOIN custom_applications ca ON ca.application_type_id = at.id
                INNER JOIN custom_application_fields caf ON ca.id = caf.custom_application_id
                INNER JOIN custom_application_assigned_batches caab ON ca.id = caab.custom_application_id
                INNER JOIN batches b ON b.batchID = caab.batch_id
                INNER JOIN custom_application_response car ON ca.id = car.custom_application_id 
                AND car.user_type  ='" . $userType . "'
                GROUP BY ca.id";
        try {
            return $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @param GetNotAppliedStudentsListRequest $request
     * @return Object|NotAppliedStudentListResponse
     * @throws ProfessionalException
     * @author jithinvijayan
     */
    public function getNotAppliedStudentsList(GetNotAppliedStudentsListRequest $request)
    {
        $request = $this->realEscapeObject($request);
        $applicationId = (int)$request->applicationId;
        $response = new NotAppliedStudentListResponse();
        if (empty($applicationId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_CUSTOM_APPLICATION_ID, "Invalid application details given");
        }
        $userType = UserType::STUDENT;
        $limitSql = "";
        if ($request->startIndex !== null && !empty($request->endIndex)) {
            $limitSql = "  LIMIT $request->startIndex,$request->endIndex ";
        }
        $sql = "SELECT DISTINCT sa.studentID AS student_id, sa.studentName as student_name, sa.regNo AS register_number,b.batchName,
                ca.name AS application_name,ca.description AS application_description,ca.id as application_id,
                b.batchName as batch_name
                FROM application_types at 
                INNER JOIN custom_applications ca ON at.id = ca.application_type_id
                INNER JOIN custom_application_assigned_batches caab ON ca.id = caab.custom_application_id 
                LEFT JOIN studentaccount sa ON sa.batchID = caab.batch_id
                LEFT JOIN custom_application_response car ON sa.studentID=car.user_id AND car.user_type='$userType
                AND car.custom_application_id =ca.id
                LEFT JOIN batches b ON b.batchID=sa.batchID
                WHERE ca.id = $applicationId AND car.id IS NULL $limitSql";
        $totalSql = "SELECT COUNT(DISTINCT sa.studentID) as totalRecords
                FROM application_types at 
                INNER JOIN custom_applications ca ON at.id = ca.application_type_id
                INNER JOIN custom_application_assigned_batches caab ON ca.id = caab.custom_application_id 
                LEFT JOIN studentaccount sa ON sa.batchID = caab.batch_id
                LEFT JOIN custom_application_response car ON sa.studentID=car.user_id AND car.user_type='$userType
                AND car.custom_application_id =ca.id
                LEFT JOIN batches b ON b.batchID=sa.batchID
                WHERE ca.id = $applicationId AND car.id IS NULL";
        try {
            $response->totalRecords = $this->executeQueryForObject($totalSql)->totalRecords;
            $response->application = $this->executeQueryForObject($sql, false, $this->mapper[CustomApplicationServiceMapper::GET_NOT_APPLIED_STUDENTS_LIST]);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $response;
    }
    /**
     * @param $applicationId
     * @param $staffId
     * @return Object
     * @throws ProfessionalException
     * @author jithinvijayan
     */
    public function getAppliedStudents($applicationId, $staffId)
    {
        $staffId = (int)$this->realEscapeString($staffId);
        if (empty($staffId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_STAFF_ID, "Invalid request sent");
        }
        if (empty($applicationId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_CUSTOM_APPLICATION_ID, "Invalid application details given");
        }
        $userType = UserType::STUDENT;
        $sql = "SELECT sa.studentID as studentId,sa.studentName,b.batchName,sa.regNo as registerNumber,
                car.id,car.status
                FROM application_types at  
                INNER JOIN custom_applications ca ON ca.application_type_id = at.id
                INNER JOIN custom_application_fields caf ON ca.id = caf.custom_application_id
                INNER JOIN custom_application_assigned_batches caab ON ca.id = caab.custom_application_id
                INNER JOIN batches b ON b.batchID = caab.batch_id
                INNER JOIN custom_application_response car ON ca.id = car.custom_application_id 
                AND car.user_type  ='" . $userType . "' AND JSON_EXTRACT(response,'$.staff')='$staffId'
                INNER JOIN studentaccount sa ON sa.batchID =b.batchID AND sa.studentID = car.user_id and ca.id = '$applicationId'";
        try {
            return $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     *
     * @param GetCustomApplicationDetailsRequest $request
     * @return Object|CustomApplication
     * @throws ProfessionalException
     * @author jithinvijayan
     */
    public function getApplicationDetails(GetCustomApplicationDetailsRequest $request)
    {
        $request = $this->realEscapeObject($request);
        if (empty($request->userId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_USER_ID, "This is an invalid request sent.");
        }
        if (empty($request->userType)) {
            throw new ProfessionalException(ProfessionalException::INVALID_USER_TYPE, "This is an invalid request sent.");
        }
        if (empty($request->registrationId) && empty($request->applicationId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_REQUEST, "Invalid request sent");
        }
        $sql = "SELECT ca.id,ca.name,ca.description,
                at.id as application_type_id,at.form_name as application_type_name,
                at.code as application_type_coed,
                caf.id as application_filed_id,caf.available_fields,
                car.id as registration_id,car.processed_by,car.response,car.remarks,car.workflow_instance_id,
                car.status,car.remarks,
                cal.id as application_log_id,cal.log,
                st.staffID,st.staffName,
                d.deptID,d.deptName,
                IF (DATE_FORMAT(CURRENT_TIMESTAMP(),'%Y-%m-%d %H:%i:%s')>=ca.start_date 
                AND DATE_FORMAT(CURRENT_TIMESTAMP(),'%Y-%m-%d %H:%i:%s')<=ca.end_date,false,true) as is_expired
                FROM application_types at  
                INNER JOIN custom_applications ca ON ca.application_type_id = at.id
                INNER JOIN custom_application_fields caf ON ca.id = caf.custom_application_id
                INNER JOIN custom_application_assigned_batches caab ON ca.id = caab.custom_application_id
                INNER JOIN batches b ON b.batchID = caab.batch_id
                INNER JOIN studentaccount sa ON sa.batchID =b.batchID AND sa.studentID = $request->userId
                LEFT JOIN custom_application_response car ON ca.id = car.custom_application_id AND car.user_id = $request->userId
                LEFT JOIN staffaccounts st ON st.staffID = car.processed_by
                LEFT JOIN department d ON d.deptID = st.deptID 
                LEFT JOIN custom_application_log cal ON cal.application_response_id = car.id
                AND car.user_type  ='" . $request->userType . "' 
                WHERE 1=1 ";
        if (!empty($request->registrationId)) {
            $sql .= " AND car.id = $request->registrationId";
        }
        if (!empty($request->applicationId)) {
            $sql .= " AND ca.id =$request->applicationId ";
        }
        try {
            return $this->executeQueryForObject($sql, false, $this->mapper[CustomApplicationServiceMapper::GET_APPLICATION_DETAILS]);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @param $registrationId
     * @param $staffId
     * @return Object|CustomApplication
     * @throws ProfessionalException
     * @author jithinvijayan
     */
    public function getAssignedApplicationDetails($registrationId, $staffId)
    {
        $registrationId = $this->realEscapeString($registrationId);
        $staffId = $this->realEscapeString($staffId);
        if (empty($registrationId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_CUSTOM_APPLICATION_ID, "Invalid application details given.");
        }
        if (empty($staffId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_STAFF_ID, "This is an invalid request sent.");
        }
        $userType = UserType::STUDENT;
        $sql = "SELECT ca.id,ca.name,ca.description,
                at.id as application_type_id,at.form_name as application_type_name,
                at.code as application_type_coed,
                caf.id as application_filed_id,caf.available_fields,
                car.id as registration_id,car.processed_by,car.response,car.remarks,car.workflow_instance_id,
                car.status,
                cal.id as application_log_id,cal.log,
                st.staffID,st.staffName,
                d.deptID,d.deptName,
                sa.studentName as student_name,
                sb.batchName as batch_name
                FROM application_types at  
                INNER JOIN custom_applications ca ON ca.application_type_id = at.id
                INNER JOIN custom_application_fields caf ON ca.id = caf.custom_application_id
                INNER JOIN custom_application_assigned_batches caab ON ca.id = caab.custom_application_id
                INNER JOIN batches b ON b.batchID = caab.batch_id
                INNER JOIN custom_application_response car ON ca.id = car.custom_application_id AND car.id=$registrationId
                AND JSON_EXTRACT(response,'$.staff')='$staffId'
                INNER JOIN studentaccount sa ON sa.batchID =b.batchID AND sa.studentID = car.user_id
                INNER JOIN batches sb ON sb.batchID = sa.batchID
                LEFT JOIN staffaccounts st ON st.staffID = car.processed_by
                LEFT JOIN department d ON d.deptID = st.deptID 
                LEFT JOIN custom_application_log cal ON cal.application_response_id = car.id
                AND car.user_type  ='" . $userType . "'";
        try {
            return $this->executeQueryForObject($sql, false, $this->mapper[CustomApplicationServiceMapper::GET_APPLICATION_DETAILS_FOR_STAFF]);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @param $applicationId
     * @param $studentId
     * @return integer
     * @throws ProfessionalException
     * @author jithinvijayan
     */
    public function checkApplicationIsAssignedToStudentBatch($applicationId, $studentId)
    {
        $applicationId = $this->realEscapeString($applicationId);
        $studentId = $this->realEscapeString($studentId);
        if (empty($studentId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_USER_ID, "This is an invalid request sent.");
        }
        if (empty($applicationId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_CUSTOM_APPLICATION_ID, "This is an invalid request");
        }
        $sql = "SELECT ca.id FROM custom_applications ca 
                INNER JOIN custom_application_fields caf on ca.id = caf.custom_application_id 
                INNER JOIN custom_application_assigned_batches caab on ca.id = caab.custom_application_id 
                INNER JOIN batches b on caab.batch_id = b.batchID
                INNER JOIN studentaccount s on b.batchID = s.batchID
                WHERE ca.id =$applicationId AND s.studentID=$studentId";
        try {
            return $this->executeQueryForObject($sql)->id;
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @param SaveApplicationResponseRequest $request
     * @throws ProfessionalException
     * @author jithinvijayan
     */
    public function saveApplicationResponse(SaveApplicationResponseRequest $request)
    {
        $registrationId = null;
        if (empty($request->applicationId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_CUSTOM_APPLICATION_ID, "The given application details not found");
        }
        if (empty($request->userId) || empty($request->userType)) {
            throw new ProfessionalException(ProfessionalException::INVALID_USER_ID, "Invalid request sent");
        }
        $status = StatusConstants::PENDING;
        $response = CommonUtil::realEscapeVariable(json_decode($request->response));
        $responseJson = json_encode($response);
        $workFlowInstanceId = $this->createCustomApplicationWorkFlowInstance($request->createdBy, $request->userType, $response->staff);
        $sql = "INSERT INTO custom_application_response (user_id, user_type, custom_application_id, response, 
             workflow_instance_id, status, created_by, created_date, updated_by, updated_date) 
             VALUES($request->userId,'$request->userType',$request->applicationId,'$responseJson',
                    $workFlowInstanceId,'$status',$request->createdBy,UTC_TIMESTAMP(),$request->updatedBy,UTC_TIMESTAMP())";
        try {
            $registrationId = $this->executeQueryForObject($sql, true);
            $userName = "";
            if ($request->userType === "STAFF") {
                $userName = StaffService::getInstance()->getStaffNameById($request->userId);
            } else if ($request->userType === "STUDENT") {
                $userName = StudentService::getInstance()->getStudentNameById($request->userId);
            }
            $log = new CustomApplicationLog();
            $log->status = $status;
            $log->createdBy = $request->createdBy;
            $log->updatedBy = $request->updatedBy;
            $log->appliedUserName = $userName;
            $log->actionTakenTime = date("Y-m-d h:i A");
            $log->message = Messages::APPLIED;
            $log->response = $request->response;
            $logRequest = new CreateCustomApplicationLogRequest();
            $logRequest->applicationRegistrationId = $registrationId;
            $logRequest->updatedBy = $request->updatedBy;
            $logRequest->createdBy = $request->createdBy;
            $logRequest->log = json_encode([$log]);
            $this->createCustomApplicationLog($logRequest);
        } catch (\Exception $e) {
            if ($registrationId) {
                $this->deleteCustomApplication($registrationId);
            }
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @param UpdateCustomApplicationRequest $request
     * @throws ProfessionalException
     * @author jithinvijayan
     */
    public function updateCustomApplication(UpdateCustomApplicationRequest $request)
    {
        if (empty($request->registrationId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_CUSTOM_APPLICATION_REGISTRATION_ID, "The given application registration details not found");
        }
        if (empty($request->userId) || empty($request->userType)) {
            throw new ProfessionalException(ProfessionalException::INVALID_USER_ID, "Invalid request sent");
        }
        $status = StatusConstants::RE_APPLIED;
        $applicationRequest = new GetCustomApplicationDetailsRequest();
        $applicationRequest->registrationId = $request->registrationId;
        $applicationRequest->userId = $request->userId;
        $applicationRequest->userType = $request->userType;
        $applicationDetails = $this->getApplicationDetails($applicationRequest);
        $applicationDetails->isExpired = (int)$applicationDetails->isExpired;
        if ($applicationDetails->status === StatusConstants::APPROVED) {
            throw new ProfessionalException(ProfessionalException::APPLICATION_ALREADY_APPROVED, "This application already approved. You cannot edit this application");
        }
        if ($applicationDetails->isExpired){
            throw new ProfessionalException(ProfessionalException::APPLICATION_EXPIRED, "This application expired. You can't apply/edit fot this application");
        }
        try {
            $response = json_decode($request->response);
            $workflowInstance = new WorkflowInstance(WorkflowActions::GET, $applicationDetails->workflowInstanceId, $request->userId, $request->userType, $response->staff);
            if (empty($workflowInstance)) {
                throw new ProfessionalException(ProfessionalException::INTERNAL_SERVICE_FAILURE, "Error occurred while re-applying application. Contact the system administrator");
            }
            $previousResponse = json_decode($applicationDetails->applicationResponse->response);
            /**
             * Initialising log
             */
            $customApplicationLog = new CustomApplicationLog();
            $customApplicationLog->status = StatusConstants::EDITED;
            $customApplicationLog->message = $applicationDetails->applicationType->name . " is " . Messages::EDITED;
            /**
             * this will work only if workflow state is rejected. Otherwise workflow stated will not change
             */
            if (strtoupper($workflowInstance->getCurrentState()->name) === strtoupper(StatusConstants::REJECTED)) {
                $possibleNextStates = $workflowInstance->getAllPossibleNextStates();
                foreach ($possibleNextStates as $state) {
                    if (strtoupper($state->name) === StatusConstants::RE_APPLIED) {
                        $moveToNextStateApiRequest = new MoveToNextStateApiRequest();
                        $moveToNextStateApiRequest->approverId = $request->userId;
                        $moveToNextStateApiRequest->approverType = $request->userType;
                        $moveToNextStateApiRequest->nextStateId = $state->id;
                        $moveToNextStateApiRequest->transitionUserId = $response->staff;
                        $workflowInstance->moveToNextState($moveToNextStateApiRequest);
                        break;
                    }
                }
                $customApplicationLog->status = StatusConstants::RE_APPLIED;
                $customApplicationLog->message = $applicationDetails->applicationType->name . " is " . Messages::RE_APPLIED;
            } elseif ((int)$previousResponse->staff !== (int)$response->staff) {
                /**
                 * if assigned staff changed, then we need to update all pending transition assignees
                 */
                $updateRequest = new UpdateAllPendingTransitionAssigneesRequest();
                $updateRequest->newUserType = UserType::STAFF;
                $updateRequest->newUserId = $response->staff;
                $updateRequest->oldUserId = $previousResponse->staff;
                $updateRequest->oldUserType = UserType::STAFF;
                $updateRequest->updatedBy = $request->updatedBy;
                $updateRequest->workflowInstanceId = $applicationDetails->workflowInstanceId;
                $workflowInstance->updateAllPendingTransitionAssignees($updateRequest);
            }
            $responseJson = json_encode(CommonUtil::realEscapeVariable($response));
            $sql = "UPDATE custom_application_response SET  response='$responseJson', 
                    status='$status', updated_by=$request->updatedBy, updated_date=UTC_TIMESTAMP()
                    WHERE id = $request->registrationId";
            $this->executeQuery($sql);
            $log = json_decode($applicationDetails->applicationResponse->log);
            $customApplicationLog->updatedBy = $request->updatedBy;
            $customApplicationLog->createdBy = $request->createdBy;
            $customApplicationLog->actionTakenTime = date("Y-m-d h:i A");
            $customApplicationLog->updatedByUserType = $request->userType;
            $customApplicationLog->response = $response;
            $customApplicationLog->appliedBy = $request->userId;
            $customApplicationLog->processedByUserName = StudentService::getInstance()->getStudentNameById($request->userId);
            array_push($log, $customApplicationLog);
            $updateLog = new UpdateCustomApplicationLog();
            $updateLog->log = json_encode($log);
            $updateLog->registrationId = $request->registrationId;
            $updateLog->updatedBy = $request->updatedBy;
            $this->updateCustomApplicationLog($updateLog);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @param $registrationId
     * @throws ProfessionalException
     * @author jithinvijayan
     */
    private function deleteCustomApplication($registrationId)
    {
        $logSql = "DELETE FROM custom_application_log WHERE application_response_id = $registrationId";
        $sql = "DELETE FROM custom_application_response WHERE id = $registrationId";
        try {
            $this->executeQuery($logSql);
            $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @param CreateCustomApplicationLogRequest $request
     * @throws ProfessionalException
     * @author jithinvijayan
     */
    public function createCustomApplicationLog(CreateCustomApplicationLogRequest $request)
    {
        $request->applicationRegistrationId = $this->realEscapeString($request->applicationRegistrationId);
        if (empty($request->applicationRegistrationId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_CUSTOM_APPLICATION_REGISTRATION_ID, "Invalid application registration details given");
        }
        $request->log = addslashes($request->log);
        $sql = "INSERT INTO custom_application_log (application_response_id, log, created_by, created_date, updated_by, updated_date) 
                VALUES ($request->applicationRegistrationId,'$request->log',$request->createdBy,UTC_TIMESTAMP(),$request->updatedBy,UTC_TIMESTAMP())";
        try {
            $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @param $createdUser
     * @param $userType
     * @param $assignedTo
     * @return int|void
     * @throws ProfessionalException
     */
    protected function createCustomApplicationWorkFlowInstance($createdUser, $userType, $assignedTo)
    {
        $codeOrId = CreatedWorkFlows::CUSTOM_APPLICATION_WORKFLOW;
        $requesterUserType = $userType;
        try {
            $workflow = new Workflow($codeOrId);
            if (empty($workflow->getId())) {
                return fault("Failed to apply for this application. Faculties not assigned for this application approval. Contact your class tutor/mentor");
            }
            $workflowInstance = new WorkflowInstance(WorkflowActions::CREATE, $codeOrId, $createdUser, $requesterUserType, $assignedTo);
            return $workflowInstance->getId();
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @param ApproveOrRejectCustomApplicationRequest $request
     * @throws ProfessionalException
     * @author jithinvijayan
     */
    public function approveOrRejectApplication(ApproveOrRejectCustomApplicationRequest $request)
    {
        $request = $this->realEscapeObject($request);
        if (empty($request->registrationId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_CUSTOM_APPLICATION_REGISTRATION_ID, "Invalid application registration or application registration doesn't exist");
        }
        if (empty($request->status)) {
            throw new ProfessionalException(ProfessionalException::INVALID_REQUEST, "Couldn't process application request");
        }
        try {
            $applicationDetails = null;
            /**
             * Fetching custom  application details
             */
            $applicationDetails = $this->getAssignedApplicationDetails($request->registrationId, $request->processedBy);
            if (empty($applicationDetails)) {
                throw new ProfessionalException(ProfessionalException::INVALID_CUSTOM_APPLICATION_REGISTRATION_ID, "Application doesn't exist");
            }
            $user = $request->processedBy;
            $userType = $request->processedUserType;
            $workFlowObject = new WorkflowInstance(WorkflowActions::GET, $applicationDetails->workflowInstanceId, $user, $userType);
            $currentState = $workFlowObject->getCurrentState()->name;
            switch (strtoupper($currentState)) {
                /**
                 * If current state is approved state, then tutor can move this application to rejected state
                 */
                case StatusConstants::APPROVED:
                    if ($request->status === StatusConstants::REJECTED) {
                        $possibleNextStates = $workFlowObject->getAllPossibleNextStates();
                        foreach ($possibleNextStates as $state) {
                            if (strtoupper($state->name) === StatusConstants::REJECTED) {
                                $this->processCustomApplicationReject($applicationDetails, $state, $workFlowObject, $request);
                                break;
                            }
                        }
                    } else {
                        throw new ProfessionalException(ProfessionalException::APPLICATION_ALREADY_APPROVED, "Application already approved by " . $applicationDetails->applicationResponse->processedBy->name);
                    }
                    break;
                /**
                 * If current state is rejected, then next state is approved state
                 */
                case StatusConstants::REJECTED:
                    /**
                     * Checking requested transition state is approved state,else throwing errors
                     */
                    if ($request->status === StatusConstants::APPROVED) {
                        $possibleNextStates = $workFlowObject->getAllPossibleNextStates();
                        foreach ($possibleNextStates as $state) {
                            if (strtoupper($state->name) === StatusConstants::APPROVED) {
                                $this->processCustomApplicationApproval($applicationDetails, $state, $workFlowObject, $request);
                                break;
                            }
                        }
                    } else {
                        throw new ProfessionalException(ProfessionalException::APPLICATION_ALREADY_REJECTED, "Application already rejected by " . $applicationDetails->applicationResponse->processedBy->name);
                    }
                    break;
                /**
                 * If current state is applied or re-applied state, then tutor can moe this
                 * application to rejected/approved state only
                 */
                case StatusConstants::APPLIED:
                case StatusConstants::RE_APPLIED:
                    if ($request->status === StatusConstants::REJECTED) {
                        $possibleNextStates = $workFlowObject->getAllPossibleNextStates();
                        foreach ($possibleNextStates as $state) {
                            if (strtoupper($state->name) === StatusConstants::REJECTED) {
                                $this->processCustomApplicationReject($applicationDetails, $state, $workFlowObject, $request);
                                break;
                            }
                        }
                    } else if ($request->status === StatusConstants::APPROVED) {
                        $possibleNextStates = $workFlowObject->getAllPossibleNextStates();
                        foreach ($possibleNextStates as $state) {
                            if (strtoupper($state->name) === StatusConstants::APPROVED) {
                                $this->processCustomApplicationApproval($applicationDetails, $state, $workFlowObject, $request);
                                break;
                            }
                        }
                    }
                    break;
                default:
                    throw new ProfessionalException(ProfessionalException::INVALID_OPERATION, "You performed an invalid operation. You cannot do this action try again with valid credentials");
            }
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @param CustomApplication $applicationDetails
     * @param $state
     * @param $workFlowObject
     * @param ApproveOrRejectCustomApplicationRequest $request
     * @throws ProfessionalException
     */
    private function processCustomApplicationReject($applicationDetails, $state, $workFlowObject, ApproveOrRejectCustomApplicationRequest $request)
    {
        try {
            $userType = $request->processedUserType;
            $status = StatusConstants::REJECTED;
            $response = json_decode($applicationDetails->applicationResponse->response);
            $moveToNextStateApiRequest = new MoveToNextStateApiRequest();
            $moveToNextStateApiRequest->approverId = $request->processedBy;
            $moveToNextStateApiRequest->approverType = $request->processedUserType;
            $moveToNextStateApiRequest->transitionUserId = $response->staff;
            $moveToNextStateApiRequest->nextStateId = $state->id;
            $workFlowObject->moveToNextState($moveToNextStateApiRequest);
            $sql = "UPDATE custom_application_response 
                    SET status= '$status',remarks='$request->remarks', updated_by =$request->updatedBy,
                    updated_date=UTC_TIMESTAMP(), processed_by=$request->processedBy WHERE id =$request->registrationId";
            $this->executeQuery($sql);
            /**
             * Adding the custom application log
             */
            $log = json_decode($applicationDetails->applicationResponse->log);
            $customApplicationLog = new CustomApplicationLog();
            $customApplicationLog->status = StatusConstants::REJECTED;
            $customApplicationLog->updatedBy = $request->updatedBy;
            $customApplicationLog->createdBy = $request->createdBy;
            $customApplicationLog->processedByUserName = StaffService::getInstance()->getStaffNameById($request->processedBy);
            $customApplicationLog->actionTakenTime = date("Y-m-d h:i A");
            $customApplicationLog->updatedByUserType = $userType;
            $customApplicationLog->message = $applicationDetails->applicationType->name . " is " . Messages::REJECTED;
            $customApplicationLog->appliedBy = $request->processedBy;
            $customApplicationLog->remarks = $request->remarks;
            array_push($log, $customApplicationLog);
            $updateLog = new UpdateCustomApplicationLog();
            $updateLog->log = json_encode($log);
            $updateLog->registrationId = $request->registrationId;
            $updateLog->updatedBy = $request->processedBy;
            $this->updateCustomApplicationLog($updateLog);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @param CustomApplication $applicationDetails
     * @param $state
     * @param $workFlowObject
     * @param ApproveOrRejectCustomApplicationRequest $request
     * @throws ProfessionalException
     * @author jithinvijayan
     */
    private function processCustomApplicationApproval($applicationDetails, $state, $workFlowObject, ApproveOrRejectCustomApplicationRequest $request)
    {
        $userType = $request->processedUserType;
        try {
            $status = StatusConstants::APPROVED;
            $response = json_decode($applicationDetails->applicationResponse->response);
            $sql = "UPDATE custom_application_response 
                    SET status= '$status',remarks='$request->remarks', updated_by =$request->updatedBy,
                    updated_date=UTC_TIMESTAMP(), processed_by=$request->processedBy WHERE id =$request->registrationId";
            $this->executeQuery($sql);
            $moveToNextStateApiRequest = new MoveToNextStateApiRequest();
            $moveToNextStateApiRequest->approverId = $request->processedBy;
            $moveToNextStateApiRequest->transitionUserId = $response->staff;
            $moveToNextStateApiRequest->approverType = $request->processedUserType;
            $moveToNextStateApiRequest->nextStateId = $state->id;
            $workFlowObject->moveToNextState($moveToNextStateApiRequest);
            /**
             * Adding the custom application log
             */
            $log = json_decode($applicationDetails->applicationResponse->log);
            $customApplicationLog = new CustomApplicationLog();
            $customApplicationLog->status = StatusConstants::APPROVED;
            $customApplicationLog->updatedBy = $request->updatedBy;
            $customApplicationLog->createdBy = $request->createdBy;
            $customApplicationLog->processedByUserName = StaffService::getInstance()->getStaffNameById($request->processedBy);
            $customApplicationLog->actionTakenTime = date("Y-m-d h:i A");
            $customApplicationLog->updatedByUserType = $userType;
            $customApplicationLog->message = $applicationDetails->applicationType->name . " is " . Messages::APPROVED;
            $customApplicationLog->appliedBy = $request->processedBy;
            $customApplicationLog->remarks = $request->remarks;
            array_push($log, $customApplicationLog);
            $updateLog = new UpdateCustomApplicationLog();
            $updateLog->log = json_encode($log);
            $updateLog->registrationId = $request->registrationId;
            $updateLog->updatedBy = $request->processedBy;
            $this->updateCustomApplicationLog($updateLog);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @param UpdateCustomApplicationLog $request
     * @throws ProfessionalException
     * @author jithinvijayan
     */
    private function updateCustomApplicationLog(UpdateCustomApplicationLog $request)
    {
        $request->log = addslashes($request->log);
        $sql = "UPDATE custom_application_log SET log='$request->log',updated_by = $request->updatedBy,
                updated_date =UTC_TIMESTAMP() WHERE application_response_id =$request->registrationId";
        try {
            $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @param UpdateCustomApplicationLog $request
     * @throws ProfessionalException
     * @author jithinvijayan
     */
    private function updateApplicationLog(UpdateCustomApplicationLog $request)
    {
        $request->log = addslashes($request->log);
        $sql = "UPDATE custom_application_log SET log='$request->log',updated_by = $request->updatedBy,
                updated_date =UTC_TIMESTAMP() WHERE application_response_id =$request->registrationId";
        try {
            $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
}