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 / 51
CRAP
0.00% covered (danger)
0.00%
0 / 2062
StaffLeaveService
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 51
175142.00
0.00% covered (danger)
0.00%
0 / 2062
 __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 / 1
 getInstance
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 5
 getStaffLeaveReportForAGivenDateRange
0.00% covered (danger)
0.00%
0 / 1
272.00
0.00% covered (danger)
0.00%
0 / 50
 getRecomendedOrApprovelStaffsByDesignationIDAndSectionID
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 20
 getShiftChangeRequestDetailsByID
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 getAllStaffLeaveTypes
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 24
 checkGrace
0.00% covered (danger)
0.00%
0 / 1
5550.00
0.00% covered (danger)
0.00%
0 / 324
 returnApproveLeavesTakenByStaff
0.00% covered (danger)
0.00%
0 / 1
306.00
0.00% covered (danger)
0.00%
0 / 75
 heOrShePresent
0.00% covered (danger)
0.00%
0 / 1
4830.00
0.00% covered (danger)
0.00%
0 / 358
 getStaffDayDetails
0.00% covered (danger)
0.00%
0 / 1
3540.00
0.00% covered (danger)
0.00%
0 / 219
 graceCalculator1
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 6
 graceCalculator2
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 6
 getPunchTimeDifferenceInMinutes
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 11
 getActualPunchTimeDifferenceInMinutes
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 11
 validateLeaveRespectingLeaveDuration
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 18
 validateLeave
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 20
 payRollCalculation
0.00% covered (danger)
0.00%
0 / 1
210.00
0.00% covered (danger)
0.00%
0 / 97
 showStaffAttendanceDetails
0.00% covered (danger)
0.00%
0 / 1
342.00
0.00% covered (danger)
0.00%
0 / 72
 getLeaveDetails
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 12
 getStaffPayrollDetailsWithPayrollId
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 16
 updatePayrollDetails
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 15
 insertPayrollDetails
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 15
 getStaffPayrollPeriods
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 18
 updatePayrollPeriod
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 getStaffLeaveDetails
0.00% covered (danger)
0.00%
0 / 1
90.00
0.00% covered (danger)
0.00%
0 / 54
 staffLeaveCertificationCount
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 getHrSectionDetailBySectionID
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 19
 getStaffNumberOfLeaveApplicationLimit
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 getReportRulesOfLeaveTypes
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 11
 getStaffLeaveApplicationByGroupID
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 getApplicationSanctionDetailsByApplicationID
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 getHrApplicationSanctionCertificatesByGroupID
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 deleteNewLeaveApplicationAndInsertOld
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 24
 whyAbsent
0.00% covered (danger)
0.00%
0 / 1
210.00
0.00% covered (danger)
0.00%
0 / 45
 getAllStaffWithInaSection
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 19
 getPayRollPeriodByStartDateAndEndDate
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 10
 getStaffUpdatePunchTimeRequestByPayRollPeriodID
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 getLeaveDetailsByLeaveCode
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 getDayDetailsByDayCode
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 updateleaveViaScript
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 99
 getEscalationDetailsOfStaff
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 17
 getCurrentDateLeaves
0.00% covered (danger)
0.00%
0 / 1
72.00
0.00% covered (danger)
0.00%
0 / 68
 updateLeaveEscalation
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 46
 checkForEscalationStatus
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 45
 getstaffLeaveDetailsByApplicationID
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 22
 getPayrollPeriodByDate
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 getPayrollProcessedStatus
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 17
 updateLeaveByApplicationID
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 35
 getSessionTimeFromLeaveApplicationID
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 checkForExistingLeave
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 17
<?php
namespace com\linways\core\ams\professional\service\hr;
use com\linways\common\core\service\CommonService as ServiceCommonService;
use com\linways\core\ams\professional\constant\SettingsConstants;
use com\linways\core\ams\professional\dto\SettingsConstents;
use com\linways\core\ams\professional\service\BaseService;
use com\linways\core\ams\professional\mapper\StaffLeaveServiceMapper;
use com\linways\core\ams\professional\exception\ProfessionalException;
use com\linways\core\ams\professional\request\hr\ConsolidatedStaffLeaveReport;
use com\linways\core\ams\professional\service\CalendarService;
use com\linways\core\ams\professional\service\CommonService;
use com\linways\core\ams\professional\util\CommonUtil;
use DateTime;
use stdClass;
class StaffLeaveService extends BaseService
{
    // /Condition 1 - Presence of a static member variable
    private static $_instance = null;
    // /Condition 2 - Locked down the constructor
    private function __construct()
    {
        $this->mapper = StaffLeaveServiceMapper::getInstance()->getMapper();
    }
    // Prevent any oustide instantiation of this class
    
    // /Condition 3 - Prevent any object or instance of that class to be cloned
    private function __clone()
    {}
    // Prevent any copy of this object
    
    // /Condition 4 - Have a single globally accessible static method
    public static function getInstance()
    {
        if (! is_object(self::$_instance)) // or if( is_null(self::$_instance) ) or if( self::$_instance == null )
            self::$_instance = new self();
        
        return self::$_instance;
    }
    /**
     * This  function returns a list of staffs with details of their attendance for 
     * a date and applied leaves for an attendance date if any.
     *
     * @return void
     */
    public function getStaffLeaveReportForAGivenDateRange($request){
        $sql = "";
        $request = $this->realEscapeObject($request);
        if(in_array('all', $request->staffIds)){
            $request->staffIds = [];
        }
        if(!empty($request->staffIds)){
            $request->staffIds = implode(',', $request->staffIds);
        }
        if(in_array('ALL', $request->deptIds)){
            $request->deptIds = [];
        }
        if(!empty($request->deptIds)){
            $request->deptIds = implode(',', $request->deptIds);
        }
        $sectionIds = in_array("",$request->sectionID)?false:implode(",",$request->sectionID);
        $sectionCondition = $sectionIds?" AND hrla.sectionID IN (".$sectionIds.")":"";
        $sql = "SELECT 
                    sta.staffID, sta.staffAccount, sta.staffName, sta.deptID, dept.deptName, dept.departmentDesc, satt.punchDate, satt.punchIn, satt.punchOut, satt.actualpunchIn, satt.actualpunchOut, hlt.leaveID as leaveTypeId, hlt.leaveName as leaveTypeName, hlt.leaveDesc as leaveTypeDescription, hrla.applicationID, hrla.startDate, hrla.endDate, hrla.appliedDate, sta.dateOfJoining,
                    CASE
                        WHEN hrla.rejected = 1 THEN 'REJECTED'
                        WHEN hrla.approved = 1 THEN 'APPROVED'
                        WHEN hrla.confirmed = 1 THEN 'CONFIRMED'
                        ELSE 'PENDING'
                    END AS leaveStatus,
                    hld.daytypeID, hld.daytypeName, hld.daytypeDesc, hld.noofleaves,hld.dayspan,hld.duration_of_leave_in_minutes
                FROM
                    staffaccounts sta
                INNER JOIN department dept on dept.deptID = sta.deptID
                LEFT JOIN staff_attendance satt ON satt.staffAccount = sta.staffAccount
                LEFT JOIN hr_leave_applications hrla ON sta.staffID = hrla.staffID AND satt.punchDate BETWEEN hrla.startDate AND hrla.endDate
                LEFT JOIN hr_leavetypes hlt ON hlt.leaveID = hrla.leaveID
                LEFT JOIN hr_leave_daytype hld ON hld.daytypeID = hrla.daytypeID 
                LEFT JOIN hr_sections sec ON sec.sectionID = hrla.sectionID $sectionCondition
                WHERE 1=1";
            $sql .= (!empty($request->staffIds))?" AND sta.staffID IN ($request->staffIds)":"";
            $sql .= (!empty($request->staffID))&& empty($request->staffIds)?" AND sta.staffID = $request->staffID ":"";
            $sql .= (!empty($request->startDate))?" AND satt.punchDate >= '$request->startDate'":"";
            $sql .= (!empty($request->endDate))?" AND satt.punchDate <= '$request->endDate'":"";
            $sql .= (!empty($request->deptIds))?" AND sta.deptID IN ($request->deptIds":"";
            $sql .= (!$request->resignedStaffs)?" AND sta.isResigned = 0 ":"";
            $sql .= (!empty($request->sortBy))?" order by $request->sortBy $request->sortOrder":"";
        try 
        {
            $staffList = $this->executeQueryForList($sql, $this->mapper[StaffLeaveServiceMapper::GET__STAFF_LEAVE_REPORT_FOR_A_GIVEN_DATE_RANGE]);
        } 
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffList;
    }
    /**
     * get All Recommendation staffs by designationID and sectionID 
     * if there is no Recommendation staffs then it will return staffs those who can approve the leave 
     * 
     * @param $designationID
     * @param $sectionID
     * 
     * @return $staffList
     */
    public function getRecomendedOrApprovelStaffsByDesignationIDAndSectionID($designationID,$sectionID,$getRecommendedStaffs)
    {
        $designationID = $this->realEscapeString($designationID);
        $sectionID = $this->realEscapeString($sectionID);
        $sql = "select lv.staffID, lv.confirm, lv.approve, sa.staffName, sa.staffEmail, sa.staffPhone from hr_leave_confirm_approve lv INNER JOIN staffaccounts sa ON sa.staffID = lv.staffID  where lv.designationID=\"$designationID\" and lv.sectionID=\"$sectionID\" ";
        try {
            if($getRecommendedStaffs)
            {
                $condition = " AND lv.confirm = 1";
                $staffList = $this->executeQueryForList($sql.$condition);
            }
            if(!$staffList)
            {
                $condition = " AND lv.approve = 1";
                $staffList = $this->executeQueryForList($sql.$condition);
            }
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffList;
    }
    /**
     * get shift change request by shiftchange request ID
     *
     * @param [type] $shiftChangeRequestId
     * @return $shiftChangeDetails
     */
    public function getShiftChangeRequestDetailsByID($shiftChangeRequestId)
    {
        $shiftChangeRequestId = $this->realEscapeString($shiftChangeRequestId);
        $sql = "select id, staffID, punchDate, punchIn, punchOut, actualpunchIn, actualpunchOut, punchtime_shiftchange, appliedDate, confirmed, conf_rejected, approved, rejected from staffpunchtime_shiftchange_updaterequest where id = '$shiftChangeRequestId';";
        try {
                $shiftChangeDetails = $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $shiftChangeDetails;
    }
    
    public function getAllStaffLeaveTypes($request)
    {
        $request = $this->realEscapeObject($request);
        if(in_array('all', $request->staffIds)){
            $request->staffIds = [];
        }
        if(!empty($request->staffIds)){
            $request->staffIds = implode(',', $request->staffIds);
        }
        $sql = "select distinct hr.leaveID, hrlt.leaveName, hrlt.leaveDesc from hr_leave_applications hr inner join hr_leavetypes hrlt on hrlt.leaveID = hr.leaveID";
        
        if(!empty($request->staffIds)){
            $sql .= " AND hr.staffID IN ($request->staffIds)";
        }
        if(!empty($request->startDate)){
            $sql .= " AND hr.startDate >= '$request->startDate'";
        }
        if(!empty($request->endDate)){
            $sql .= " AND hr.endDate <= '$request->endDate'";
        }
        
        try {
            return $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Used in staff leave report
     * for calculating staffs late time  
     */
    public function checkGrace($attendance, $settings, $staffProperty)
    {
        global $graceTime;
        $grace = 0;
        $lateComeInMinutes = 0;
        $earlyGoingInMinutes = 0;
        foreach ($attendance->appliedLeave as $appliedLeave)
        {
            $case = $appliedLeave->dayType->dayspan;
            if (in_array($appliedLeave->leaveStatus, $settings->leaveTypesToBeConsidered))
            {
                $staffProperty->isleave = true;
                $staffProperty->numberOfLeave += $appliedLeave->dayType->numberOfLeaves < .5 ? 0 : $appliedLeave->dayType->numberOfLeaves;
                
                switch ($case)
                {
                    case "1":
                        if($appliedLeave->dayType->numberOfLeaves < .5)
                        {
                            //$staffProperty->LeaveArray[]=$appliedLeave->dayType->name;
                            $staffProperty->isLatecome = true;
                            //$lateComeInMinutes += $appliedLeave->dayType->timeSpan;
                            $isLateCome = new stdClass;
                            $isLateCome->LeaveArray[] = $appliedLeave->dayType->name;
                            $isLateCome->smallLeaveCount += $appliedLeave->dayType->numberOfLeaves;
                            $isLateCome->lateComeInMinutes += $appliedLeave->dayType->timeSpan;
                            $isLateCome->singleDayLeaveAndLeaveTypes[$appliedLeave->leaveType->name] = $appliedLeave->dayType->numberOfLeaves;
                            $isLateComeArray[] = $isLateCome;
                            //$isLateCome->smallLeaveCount += $appliedLeave->dayType->numberOfLeaves;
                        }
                        else
                        {
                            $staffProperty->singleDayLeaveAndLeaveTypes[$appliedLeave->leaveType->name] = $appliedLeave->dayType->numberOfLeaves;
                            $staffProperty->LeaveArray[]= $appliedLeave->leaveType->name . " " . $appliedLeave->dayType->name;
                            $staffProperty->fornoonLeave = true;
                        }
                        break;
                    case "2":
                        if($appliedLeave->dayType->numberOfLeaves < .5)
                        {
                            //$staffProperty->LeaveArray[]=$appliedLeave->dayType->name;
                            $staffProperty->isEarlyGoing = true;
                            //$staffProperty->smallLeaveCount += $appliedLeave->dayType->numberOfLeaves;
                            $isEarlyGoing = new stdClass;
                            $isEarlyGoing->earlyGoingInMinutes = $appliedLeave->dayType->timeSpan;
                            $isEarlyGoing->LeaveArray[] = $appliedLeave->dayType->name;
                            $isEarlyGoing->smallLeaveCount += $appliedLeave->dayType->numberOfLeaves;
                            $isEarlyGoing->singleDayLeaveAndLeaveTypes[$appliedLeave->leaveType->name] = $appliedLeave->dayType->numberOfLeaves;
                            $isEarlyGoingArray[] = $isEarlyGoing;
                        }
                        else
                        {
                            $staffProperty->singleDayLeaveAndLeaveTypes[$appliedLeave->leaveType->name] = $appliedLeave->dayType->numberOfLeaves;
                            $staffProperty->LeaveArray[]= $appliedLeave->leaveType->name . " " . $appliedLeave->dayType->name;
                            $staffProperty->afternoonLeave = true;
                        }
                        break;
                    case "3":
                        $staffProperty->singleDayLeaveAndLeaveTypes[$appliedLeave->leaveType->name] = $appliedLeave->dayType->numberOfLeaves;
                        $staffProperty->LeaveArray[]= $appliedLeave->leaveType->name . " " . $appliedLeave->dayType->name;
                        $staffProperty->isFulldayLeave = true;
                        break;
                }
            }
        }
        if($staffProperty->isFulldayLeave)
        {
            $staffProperty->graceNow = 0;
            $staffProperty->totalGrace = $graceTime[$attendance->staffId];
            return $staffProperty;
        }
        $punchInTime = date_format(new DateTime($attendance->inTime), 'H:i:s');
        $punchOutTime = date_format(new DateTime($attendance->outTime), 'H:i:s');
        if($settings->ActualHalfTime)
        {
            $ActualHalfTime = date_format(new DateTime($settings->ActualHalfTime), 'H:i:s');
        }
        else
        {
            $actualWorkingHalfTimeInMinutes = ((strtotime($attendance->actualPunchOut) - strtotime($attendance->actualPunchIn))/60)/2;
            $ActualHalfTime = date('H:i:s',strtotime('+'.$actualWorkingHalfTimeInMinutes.' minutes',strtotime($attendance->actualPunchIn)));
        }
        $startDuration = date_format(new DateTime($attendance->actualPunchIn), 'H:i:s');
        $stopDuration = date_format(new DateTime($attendance->actualPunchOut), 'H:i:s');
        
        if($staffProperty->isleave)
        {
            if ($staffProperty->fornoonLeave)
            {
                $startDuration = $ActualHalfTime;
                if ($settings->graceTimeInMinutes && $staffProperty->isEarlyGoing)
                {
                    $startDuration = date("H:i:s",strtotime("+".$settings->graceTimeInMinutes." minute ", strtotime($startDuration)));
                    if(strtotime($startDuration) < strtotime($punchInTime))
                    {
                        $staffProperty->exceedDailyGraceTime = true;
                    }
                }
            }
            if ($staffProperty->afternoonLeave)
            {
                $stopDuration = $ActualHalfTime;
                if ($settings->graceTimeInMinutes && $staffProperty->isLatecome)
                {
                    $stopDuration = date("H:i:s",strtotime("-".$settings->graceTimeInMinutes." minute ", strtotime($stopDuration)));
                    if(strtotime($stopDuration) > strtotime($punchOutTime))
                    {
                        $staffProperty->exceedDailyGraceTime = true;
                    }
                }
            } 
            if($staffProperty->holiday && !$settings->considerHolidayAsFirstPriority)
            {
                if($staffProperty->fullDayHoliday)
                {
                    $punchInTime = $startDuration;
                    $punchOutTime = $stopDuration;
                }
                else
                {
                    if($staffProperty->fornoonHoliday)
                    {
                        $startDuration = $ActualHalfTime;
                    }
                    elseif($staffProperty->afternoonHoliday)
                    {
                        $stopDuration = $ActualHalfTime;
                    }
                }
            }
            if ($staffProperty->isLatecome)
            {
                if($settings->considerLeaveApplyDuration)
                {
                    $checkLatecome = false;
                    foreach($isLateComeArray as $LateComeLeave)
                    {
                        //get diffrence between actual punch in and punch in 
                        $validLeave = $this->validateLeave($startDuration,$punchInTime,$settings,1,0);
                        if($validLeave)
                        {
                            $checkLatecome = true;
                            foreach($LateComeLeave->LeaveArray as $leaveArray)
                            {
                                $staffProperty->LeaveArray[]= $leaveArray;
                            }
                            $validLeave = false;
                            $lateComeInMinutes = $LateComeLeave->lateComeInMinutes;
                            $startDuration = date("H:i", strtotime('+' . $lateComeInMinutes . ' minutes', strtotime($startDuration)));
                            foreach($LateComeLeave->singleDayLeaveAndLeaveTypes as $key=>$singleDayLeaveAndLeaveTypes)
                            {
                                $staffProperty->smallLeaveCount +=$singleDayLeaveAndLeaveTypes;
                                $staffProperty->singleDayLeaveAndLeaveTypes[$key] = $staffProperty->singleDayLeaveAndLeaveTypes[$key]?$staffProperty->singleDayLeaveAndLeaveTypes[$key]+$singleDayLeaveAndLeaveTypes:$singleDayLeaveAndLeaveTypes;
                            }
                        }
                        else
                        {
                            $startDuration = date("H:i", strtotime('+' . $LateComeLeave->lateComeInMinutes . ' minutes', strtotime($startDuration)));
                        }
                    } 
                }
                else
                {
                    $checkLatecome = true;
                    foreach($LateComeLeave->LeaveArray as $leaveArray)
                    {
                        $staffProperty->LeaveArray[]= $leaveArray;
                    }
                    $validLeave = false;
                    $lateComeInMinutes = $LateComeLeave->lateComeInMinutes;
                    $startDuration = date("H:i", strtotime('+' . $lateComeInMinutes . ' minutes', strtotime($startDuration)));
                    foreach($LateComeLeave->singleDayLeaveAndLeaveTypes as $key=>$singleDayLeaveAndLeaveTypes)
                    {
                        $staffProperty->smallLeaveCount +=$singleDayLeaveAndLeaveTypes;
                        $staffProperty->singleDayLeaveAndLeaveTypes[$key] = $staffProperty->singleDayLeaveAndLeaveTypes[$key]?$staffProperty->singleDayLeaveAndLeaveTypes[$key]+$singleDayLeaveAndLeaveTypes:$singleDayLeaveAndLeaveTypes;
                    }
                }
                $staffProperty->isLatecome = $checkLatecome?true:false;
            }
            
            if ($staffProperty->isEarlyGoing)
            {
                if($settings->considerLeaveApplyDuration)
                {
                    $checkLatecome = false;
                    foreach($isEarlyGoingArray as $isEarlyGoing)
                    {
                        $validLeave = $this->validateLeave($stopDuration,$punchOutTime,$settings,0,1);
                        if($validLeave)
                        {
                            $checkLatecome = true;
                            foreach($isEarlyGoing->LeaveArray as $leaveArray)
                            {
                                $staffProperty->LeaveArray[]= $leaveArray;
                            }
                            $validLeave = true;
                            $earlyGoingInMinutes = $isEarlyGoing->earlyGoingInMinutes;
                            $stopDuration = date("H:i", strtotime('-' . $earlyGoingInMinutes . ' minutes', strtotime($stopDuration)));
                            foreach($isEarlyGoing->singleDayLeaveAndLeaveTypes as $key=>$singleDayLeaveAndLeaveTypes)
                            {
                                $staffProperty->singleDayLeaveAndLeaveTypes[$key] = $staffProperty->singleDayLeaveAndLeaveTypes[$key]?$staffProperty->singleDayLeaveAndLeaveTypes[$key]+$singleDayLeaveAndLeaveTypes:$singleDayLeaveAndLeaveTypes;
                                $staffProperty->smallLeaveCount +=$singleDayLeaveAndLeaveTypes;
                            }                            
                        }
                        else
                        {
                            $stopDuration = date("H:i", strtotime('-' . $isEarlyGoing->earlyGoingInMinutes . ' minutes', strtotime($stopDuration)));
                        }
                    }
                }
                else
                {
                    $checkLatecome = true;
                    foreach($isEarlyGoing->LeaveArray as $leaveArray)
                    {
                        $staffProperty->LeaveArray[]= $leaveArray;
                    }
                    $validLeave = true;
                    $earlyGoingInMinutes = $isEarlyGoing->earlyGoingInMinutes;
                    $stopDuration = date("H:i", strtotime('-' . $earlyGoingInMinutes . ' minutes', strtotime($stopDuration)));
                    foreach($isEarlyGoing->singleDayLeaveAndLeaveTypes as $key=>$singleDayLeaveAndLeaveTypes)
                    {
                        $staffProperty->singleDayLeaveAndLeaveTypes[$key] = $staffProperty->singleDayLeaveAndLeaveTypes[$key]?$staffProperty->singleDayLeaveAndLeaveTypes[$key]+$singleDayLeaveAndLeaveTypes:$singleDayLeaveAndLeaveTypes;
                        $staffProperty->smallLeaveCount +=$singleDayLeaveAndLeaveTypes;
                    }
                }
                $staffProperty->isEarlyGoing = $checkLatecome?true:false;
            }
            if($staffProperty->fornoonLeave || $staffProperty->isEarlyGoing || $staffProperty->isLatecome || $staffProperty->afternoonLeave || $staffProperty->isFulldayLeave )
            {
                $staffProperty->isleave = true;
            }
            else
            {
                $staffProperty->isleave = false;
            }
            
            if ($punchInTime <= $startDuration && $punchOutTime >= $stopDuration)
            {
                // he is in time
                $staffProperty->graceNow = 0;
                $staffProperty->ispresent =true;
                $staffProperty->inTime = true;
                if($staffProperty->numberOfLeave >= .5 && $staffProperty->numberOfLeave < 1)
                {
                    //to do
                    $staffProperty->isHalfdayLeave = true;
                }
                elseif($staffProperty->numberOfLeave >= 1)
                {
                    $staffProperty->isFulldayLeave = true;
                }
                return $staffProperty;
            }
            else
            {
                $staffProperty->notInTime = true;
                if($staffProperty->exceedDailyGraceTime)
                {
                    $staffProperty->graceNow = 0;
                }
                else
                {
                    $grace += $this->graceCalculator1($punchInTime, $startDuration);
                    $grace += $this->graceCalculator2($punchOutTime, $stopDuration);
                    $staffProperty->graceNow = $grace;
                }
                if($staffProperty->notInTime && $staffProperty->numberOfLeave > 0)
                {
                    $grace = 0;
                }
                $totalGraceTime = empty($graceTime[$attendance->staffId]) ? $grace : ($graceTime[$attendance->staffId] + $grace);
                $graceTime[$attendance->staffId] = $totalGraceTime;
                $staffProperty->totalGrace = $graceTime[$attendance->staffId];
                
                if ($graceTime[$attendance->staffId] > $settings->graceTimePerMonthInMin)
                {
                    //he is not in time 
                    if($settings->useLOPThresholdTime)
                    {
                        if($grace > $settings->LOPThersholdTime)
                        {
                            $staffProperty->exceedThersholdTime = true;
                        }
                    }
                    $staffProperty->isHalfdayAbsent = true;
                    $staffProperty->graceTimeExeeded = true;
                    $staffProperty->ispresent = true;
                    if($staffProperty->numberOfLeave >= .5 && $staffProperty->numberOfLeave < 1)
                    {
                        $staffProperty->isHalfdayLeave = true;
                    }
                    elseif($staffProperty->numberOfLeave >= 1)
                    {
                        $staffProperty->isFulldayLeave = true;
                    }
                }
                else
                 {
                    //he is in time 
                    if($staffProperty->numberOfLeave >= .5 && $staffProperty->numberOfLeave < 1)
                    {
                        $staffProperty->isHalfdayLeave = true;
                    }
                    elseif($staffProperty->numberOfLeave >= 1)
                    {
                        $staffProperty->isFulldayLeave = true;
                    }
                }
            }
        }
        else
        {
            $staffProperty->notInTime = true;
            $totalGraceTime = empty($graceTime[$attendance->staffId]) ? $grace : ($graceTime[$attendance->staffId] + $grace);
            $graceTime[$attendance->staffId] = $totalGraceTime;
            $staffProperty->totalGrace = $graceTime[$attendance->staffId];
            
            if ($graceTime[$attendance->staffId] > $settings->graceTimePerMonthInMin)
            {
                //grace time exeeded
                $staffProperty->graceTimeExeeded = true;
                $staffProperty->isHalfDayPresent = true;
                $staffProperty->isHalfdayAbsent = true;
                if($settings->useLOPThresholdTime)
                {
                    $exeedTime = $this->getPunchTimeDifferenceInMinutes($attendance);
                    if($exeedTime > $settings->LOPThersholdTime)
                    {
                        $staffProperty->exceedThersholdTime = true;
                    }
                }
                return $staffProperty;
            }
            else
            {
                // he is not in time but grace time not exeeded
                $staffProperty->ispresent = true;
                return $staffProperty;
            }
        }
        return $staffProperty;
    }
    public function returnApproveLeavesTakenByStaff($attendance, $settings, $staffProperty)
    {
        foreach ($attendance->appliedLeave as $appliedLeave) {
            if (in_array($appliedLeave->leaveStatus, $settings->leaveTypesToBeConsidered))
            {
                $staffProperty->isleave = true;
                if($appliedLeave->dayType->numberOfLeaves < .5)
                {
                    $haveLeave = false;
                    if($settings->considerLeaveApplyDuration)
                    {
                        if($appliedLeave->dayType->dayspan == 1)
                        {
                            if($attendance->inTime != "00:00:00")
                                $haveLeave = $this->validateLeave ($attendance->actualPunchIn,$attendance->inTime,$settings,1,0);
                        }
                        else
                        {
                            if($attendance->outTime != "00:00:00")
                                $haveLeave = $this->validateLeave ($attendance->actualPunchOut,$attendance->outTime,$settings,0,1);
                        }
                    }
                    else
                    {
                        $haveLeave = true;
                    }
                    if($haveLeave)
                    {
                        $haveLeave = false;
                        $staffProperty->LeaveArray[]=$appliedLeave->dayType->name;
                        $staffProperty->singleDayLeaveAndLeaveTypes[$appliedLeave->leaveType->name] = $appliedLeave->dayType->numberOfLeaves;
                        if($appliedLeave->dayType->dayspan == 1)
                        {
                            $staffProperty->isLatecome = true;
                        }
                        else
                        {
                            $staffProperty->isEarlyGoing = true;
                        }
                        $staffProperty->smallLeaveCount += $appliedLeave->dayType->numberOfLeaves;
                    }
                }
                elseif($appliedLeave->dayType->numberOfLeaves >= .5 && $appliedLeave->dayType->numberOfLeaves < 1)
                {
                    if($appliedLeave->dayType->dayspan == 1)
                    {
                        $staffProperty->fornoonLeave = true;
                    }
                    else
                    {
                        $staffProperty->afternoonLeave = true;
                    }
                    $staffProperty->singleDayLeaveAndLeaveTypes[$appliedLeave->leaveType->name] = $appliedLeave->dayType->numberOfLeaves;
                    $staffProperty->numberOfLeave += $appliedLeave->dayType->numberOfLeaves;
                    $staffProperty->LeaveArray[]=$appliedLeave->leaveType->name . " " . $appliedLeave->dayType->name;
                }
                elseif($appliedLeave->dayType->numberOfLeaves >= 1)
                {
                    $staffProperty->singleDayLeaveAndLeaveTypes[$appliedLeave->leaveType->name] = $appliedLeave->dayType->numberOfLeaves;
                    $staffProperty->isFulldayLeave = true;
                    $staffProperty->LeaveArray[]=$appliedLeave->leaveType->name . " " . $appliedLeave->dayType->name;
                    $staffProperty->isFulldayLeave = true;
                    $staffProperty->numberOfLeave += $appliedLeave->dayType->numberOfLeaves;
                }
            }
        }
        if($staffProperty->numberOfLeave >= 1)
        {
            $staffProperty->isFulldayLeave = true;
        }
        if(!$staffProperty->isleave && !$staffProperty->ispresent)
        {
            $staffProperty->isAbsent = true;
        }
        return $staffProperty;
    }
    public function heOrShePresent($attendance, $settings, $staffProperty, $holiday)
    {
        global $graceTime;
        //$staffId = $attendance->staffId;
        //no punch in & no punch out
        if (trim($attendance->inTime) == "00:00:00" && trim($attendance->outTime) == "00:00:00") 
        {
            if($holiday && $attendance->actualPunchOut == "00:00:00" && $attendance->actualPunchIn == "00:00:00" )
            {
                return $staffProperty;
            }
            $staffProperty->isAbsent = true;
            if($attendance->appliedLeave)
            {
                $staffProperty = $this->returnApproveLeavesTakenByStaff($attendance, $settings, $staffProperty);
                if((float)$staffProperty->numberOfLeave >= .5)
                {
                    if((float)$staffProperty->numberOfLeave >= .50 && (float)$staffProperty->numberOfLeave < 1 )
                    {
                        $staffProperty->isHalfdayAbsent = true;
                        if($staffProperty->fornoonLeave)
                            $staffProperty->isAfternoonAbsent = true;
                        else
                            $staffProperty->isFornoonAbsent = true;
                    }
                    else
                    {
                        $staffProperty->isFulldayLeave = true;
                    }
                }
            }
            return $staffProperty;
        }
        else
        {
            $staffProperty->ispresent = true;
            $punchInTime = date_format(new DateTime($attendance->inTime), 'H:i:s');
            $actualPunchInTime = date_format(new DateTime($attendance->actualPunchIn), 'H:i:s');
            $punchOutTime = date_format(new DateTime($attendance->outTime), 'H:i:s');
            $actualPunchOutTime = date_format(new DateTime($attendance->actualPunchOut), 'H:i:s');
            $staffProperty->punchOutDone = trim($attendance->outTime) == "00:00:00" || $attendance->outTime == null ? false : true ;
            $staffProperty->punchInDone = trim($attendance->inTime) == "00:00:00" || $attendance->inTime == null ? false : true ;
            
            //$ActualHalfTime = date_format(new DateTime($settings->ActualHalfTime), 'H:i:s');
            $grace = 0;
            // $userGraceTime = $graceTime ? $graceTime [$attendance->staffId]:"";
            // $lateCome = strtotime($attendance->inTime) - strtotime($attendance->actualPunchIn) > 0 ? strtotime($attendance->inTime) - strtotime($attendance->actualPunchIn) : 0;
            // $earlyGoing = strtotime($attendance->actualPunchOut) - strtotime($attendance->outTime) > 0 ? strtotime($attendance->actualPunchOut) - strtotime($attendance->outTime) : 0;
            
            // //to_minutes
            // $lateCome = $lateCome ? $lateCome/60 : 0;
            // $earlyGoing =$earlyGoing ? $earlyGoing/60 : 0;
            // $lateMinutes = $lateCome + $earlyGoing;
            if ( !$staffProperty->punchOutDone || !$staffProperty->punchInDone )
            {
                // case punchouttime or punchintime
                $staffProperty->missPunch = true;
                $staffProperty->isHalfdayAbsent = true;
                $staffProperty->punchOut = $punchOutTime;
                $staffProperty->punchIn = $punchInTime;
                $staffProperty = $this->returnApproveLeavesTakenByStaff($attendance, $settings, $staffProperty);
                $numberOfLeaves = (float)$staffProperty->numberOfLeave;
                if($numberOfLeaves >= .5)
                {
                    if($numberOfLeaves >= .5 && $numberOfLeaves < 1 )
                    {
                        $staffProperty->isHalfdayLeave = true;
                    }
                    else
                    {
                        $staffProperty->isFulldayLeave = true;
                    }
                }
                if ($staffProperty->punchOutDone)
                {
                    $staffProperty->graceNow += 0;
                }
                elseif($staffProperty->punchInDone)
                {
                    $staffProperty->graceNow += 0;
                }
                $totalGraceTime = empty($graceTime[$attendance->staffId]) ? $staffProperty->graceNow : ($graceTime[$attendance->staffId] + $staffProperty->graceNow);
                $graceTime[$attendance->staffId] = $totalGraceTime;
                $staffProperty->totalGrace = $graceTime[$attendance->staffId];
                if($staffProperty->graceNow && $graceTime[$attendance->staffId] > $settings->graceTimePerMonthInMin)
                {
                    $staffProperty->graceTimeExeeded = true;
                }
                return $staffProperty;
            }
            // have punchin and punchout
            // Checking garce time
            $staffProperty->punchOutDone = true;
            $staffProperty->punchInDone = true;
            $staffProperty->punchOut = $punchOutTime;
            $staffProperty->punchIn = $punchInTime;
            if($staffProperty->holiday && !$settings->considerHolidayAsFirstPriority)
            {
                if($staffProperty->fullDayHoliday)
                {
                    $punchInTime = $actualPunchInTime;
                    $punchOutTime = $actualPunchOutTime;
                }
                else 
                {
                    $actualWorkingHalfTimeInMinutes = ((strtotime($attendance->actualPunchOut) - strtotime($attendance->actualPunchIn))/60)/2;
                    $ActualHalfTime = date('H:i:s',strtotime('+'.$actualWorkingHalfTimeInMinutes.' minutes',strtotime($attendance->actualPunchIn)));
                    if ($staffProperty->fornoonHoliday)
                    {
                        $actualPunchInTime = $ActualHalfTime;
                    }
                    else
                    {
                        $actualPunchOutTime = $ActualHalfTime;
                    }
                }
            }
            $grace += $this->graceCalculator1($punchInTime, $actualPunchInTime);
            $grace += $this->graceCalculator2($punchOutTime, $actualPunchOutTime);
            
            $staffProperty->ispresent = true;
            if($punchInTime <= $actualPunchInTime && $punchOutTime >= $actualPunchOutTime)
            {
                //he is in time
                $staffProperty->inTime = true;
                $staffProperty->totalGrace = $graceTime[$attendance->staffId];
                if(!$attendance->appliedLeave)
                {
                    //did't have any leaves
                    return $staffProperty;
                }
                else
                {
                    $staffProperty = $this->returnApproveLeavesTakenByStaff($attendance, $settings, $staffProperty);
                    if ($staffProperty->isleave)
                    {
                        $numberOfLeaves = (float)$staffProperty->numberOfLeave;
                        if($numberOfLeaves >= .5)
                        {
                            if($numberOfLeaves >= .5 && $numberOfLeaves < 1 )
                            {
                                $staffProperty->isHalfdayLeave = true;
                            }
                            else
                            {
                                $staffProperty->isFulldayLeave = true;
                            }
                        }
                    }
                }
                return $staffProperty;
            }
            else
            {
                //not in time
                $staffProperty->notInTime = true;
                if (!$attendance->appliedLeave)
                {
                    $maxGraceLimit = (int)$settings->graceTimePerMonthInMin;
                    
                    $perdayGrace = $grace;
                    if($perdayGrace < $maxGraceLimit)
                    {
                        $staffProperty->graceNow = $grace;
                        $totalGraceTime = empty($graceTime[$attendance->staffId]) ? $grace : ($graceTime[$attendance->staffId] + $grace);
                        if ($totalGraceTime > $maxGraceLimit)
                            {
                                //grace time exeeded
                                $staffProperty->graceTimeExeeded = true;
                                
                                //custom rule while grace time exceeding case is written here
                                $customRule = json_decode(CommonService::getInstance()->getSettings(SettingsConstants::GRACE_TIME_EXCEEDING_MANAGEMENT, SettingsConstants::GRACE_TIME_EXCEEDING_MANAGEMENT));
                                if($customRule->customLOP)
                                {
                                    if($customRule->lopType == "FULLDAY")
                                    {
                                        $staffProperty->isFulldayLeave = true;
                                    }
                                    else if($customRule->lopType == "HALFDAY"){
                                        $staffProperty->isHalfDayPresent = true;
                                        $staffProperty->isHalfdayAbsent = true;   
                                    }
                                }
                                else{
                                    $staffProperty->isHalfDayPresent = true;
                                    $staffProperty->isHalfdayAbsent = true;
                                }
                                if($settings->useLOPThresholdTime)
                                {
                                    $exeedTime = $this->getPunchTimeDifferenceInMinutes($attendance);
                                    if($exeedTime < $settings->LOPThersholdTime)
                                    {
                                        $staffProperty->exceedThersholdTime = true;
                                    }
                                    else
                                    {
                                        $graceTime[$attendance->staffId] = $totalGraceTime;
                                        $staffProperty->totalGrace = $graceTime[$attendance->staffId];
                                    }
                                }
                                else
                                {
                                    //global grace time updated only if its lesser than the threshold 
                                    if($totalGraceTime <= $maxGraceLimit)
                                    {
                                        $graceTime[$attendance->staffId] = $totalGraceTime;
                                    }
                                    $staffProperty->totalGrace = $graceTime[$attendance->staffId];
                                }
                                return $staffProperty;
                            }
                            else
                            {
                                // he is not in time but grace time not exeeded
                                $staffProperty->ispresent = true;
                                $graceTime[$attendance->staffId] += $grace;
                                return $staffProperty;
                            }
                    }else
                    {
                        if($maxGraceLimit > $grace)
                        {
                            $staffProperty->graceNow = $grace;
                        }
                        $totalGraceTime = $grace;
                        if ($totalGraceTime > $maxGraceLimit)
                        {
                            //grace time exeeded
                            $staffProperty->graceTimeExeeded = true;
                            //custom rule while grace time exceeding case is written here
                            $customRule = json_decode(CommonService::getInstance()->getSettings(SettingsConstants::GRACE_TIME_EXCEEDING_MANAGEMENT, SettingsConstants::GRACE_TIME_EXCEEDING_MANAGEMENT));
                            if($customRule->customLOP)
                            {
                                if($customRule->lopType == "FULLDAY")
                                {
                                    $staffProperty->isFulldayLeave = true;
                                }
                                else if($customRule->lopType == "HALFDAY"){
                                    $staffProperty->isHalfDayPresent = true;
                                    $staffProperty->isHalfdayAbsent = true;   
                                }
                            }
                            else{
                                $staffProperty->isHalfDayPresent = true;
                                $staffProperty->isHalfdayAbsent = true;
                            }
                            if($settings->useLOPThresholdTime)
                            {
                                $exeedTime = $this->getPunchTimeDifferenceInMinutes($attendance);
                                if($exeedTime < $settings->LOPThersholdTime)
                                {
                                    $staffProperty->exceedThersholdTime = true;
                                }
                                else
                                {
                                    $graceTime[$attendance->staffId] += 0;
                                    $staffProperty->totalGrace = $graceTime[$attendance->staffId];
                                }
                            }
                            else
                            {
                                $graceTime[$attendance->staffId] += 0;
                                $staffProperty->totalGrace = $graceTime[$attendance->staffId];
                            }
                            return $staffProperty;
                        }
                        else
                        {
                            // he is not in time but grace time not exeeded
                            $staffProperty->ispresent = true;
                            $graceTime[$attendance->staffId] += $grace;
                            return $staffProperty;
                        }
                    }
                   
                    
                }
                elseif($attendance->appliedLeave[0]->leaveStatus != "APPROVED") 
                {
                    $maxGraceLimit = (int)$settings->graceTimePerMonthInMin;
                    
                    $perdayGrace = $grace;
                    if($perdayGrace < $maxGraceLimit)
                    {
                        $staffProperty->graceNow = $grace;
                        $totalGraceTime = empty($graceTime[$attendance->staffId]) ? $grace : ($graceTime[$attendance->staffId] + $grace);
                        if ($totalGraceTime > $maxGraceLimit)
                            {
                                //grace time exeeded
                                $staffProperty->graceTimeExeeded = true;
                                
                                //custom rule while grace time exceeding case is written here
                                $customRule = json_decode(CommonService::getInstance()->getSettings(SettingsConstants::GRACE_TIME_EXCEEDING_MANAGEMENT, SettingsConstants::GRACE_TIME_EXCEEDING_MANAGEMENT));
                                if($customRule->customLOP)
                                {
                                    if($customRule->lopType == "FULLDAY")
                                    {
                                        $staffProperty->isFulldayLeave = true;
                                    }
                                    else if($customRule->lopType == "HALFDAY"){
                                        $staffProperty->isHalfDayPresent = true;
                                        $staffProperty->isHalfdayAbsent = true;   
                                    }
                                }
                                else{
                                    $staffProperty->isHalfDayPresent = true;
                                    $staffProperty->isHalfdayAbsent = true;
                                }
                                if($settings->useLOPThresholdTime)
                                {
                                    $exeedTime = $this->getPunchTimeDifferenceInMinutes($attendance);
                                    if($exeedTime < $settings->LOPThersholdTime)
                                    {
                                        $staffProperty->exceedThersholdTime = true;
                                    }
                                    else
                                    {
                                        $graceTime[$attendance->staffId] = $totalGraceTime;
                                        $staffProperty->totalGrace = $graceTime[$attendance->staffId];
                                    }
                                }
                                else
                                {
                                    $graceTime[$attendance->staffId] = $totalGraceTime;
                                    $staffProperty->totalGrace = $graceTime[$attendance->staffId];
                                }
                                return $staffProperty;
                            }
                            else
                            {
                                // he is not in time but grace time not exeeded
                                $staffProperty->ispresent = true;
                                $graceTime[$attendance->staffId] += $grace;
                                return $staffProperty;
                            }
                    }else
                    {
                        
                        $staffProperty->graceNow = $grace > $maxGraceLimit ? 0 : $grace;
                        $totalGraceTime = $grace;
                        if ($totalGraceTime > $maxGraceLimit)
                        {
                            //grace time exeeded
                            $staffProperty->graceTimeExeeded = true;
                            //custom rule while grace time exceeding case is written here
                            $customRule = json_decode(CommonService::getInstance()->getSettings(SettingsConstants::GRACE_TIME_EXCEEDING_MANAGEMENT, SettingsConstants::GRACE_TIME_EXCEEDING_MANAGEMENT));
                            if($customRule->customLOP)
                            {
                                if($customRule->lopType == "FULLDAY")
                                {
                                    $staffProperty->isFulldayLeave = true;
                                }
                                else if($customRule->lopType == "HALFDAY"){
                                    $staffProperty->isHalfDayPresent = true;
                                    $staffProperty->isHalfdayAbsent = true;   
                                }
                            }
                            else{
                                $staffProperty->isHalfDayPresent = true;
                                $staffProperty->isHalfdayAbsent = true;
                            }
                            if($settings->useLOPThresholdTime)
                            {
                                $exeedTime = $this->getPunchTimeDifferenceInMinutes($attendance);
                                if($exeedTime < $settings->LOPThersholdTime)
                                {
                                    $staffProperty->exceedThersholdTime = true;
                                }
                                else
                                {
                                    $graceTime[$attendance->staffId] += 0;
                                    $staffProperty->totalGrace = $graceTime[$attendance->staffId];
                                }
                            }
                            else
                            {
                                $graceTime[$attendance->staffId] += 0;
                                $staffProperty->totalGrace = $graceTime[$attendance->staffId];
                            }
                            return $staffProperty;
                        }
                        else
                        {
                            // he is not in time but grace time not exeeded
                            $staffProperty->ispresent = true;
                            $graceTime[$attendance->staffId] += $grace;
                            return $staffProperty;
                        }
                    }
                   
                    
                }
                else
                {
                    $staffProperty = StaffLeaveService::getInstance()->checkGrace($attendance, $settings, $staffProperty);
                    return $staffProperty;
                }
            }
        }
    }
    public function getStaffDayDetails($attendance,$settings,$staffProperty, $holiday = false)
    {
        global $graceTime;
        $staffProperty = $this->heOrShePresent($attendance, $settings, $staffProperty, $holiday);
        $checkHoliday = implode(" + ",$staffProperty->LeaveArray);
        //if($holiday && $checkHoliday == SettingsConstents::HOLIDAY && $attendance->actualPunchIn == '00:00:00' && $attendance->actualPunchOut == '00:00:00')
        
        if($holiday && $checkHoliday == SettingsConstents::HOLIDAY && !$staffProperty->ispresent)
        {
            return $staffProperty;
        }
        elseif ($staffProperty->isAbsent && !$staffProperty->ispresent)
        {
            $isAbsent = false;
            if($staffProperty->isHalfdayAbsent)
            {
                if($staffProperty->holiday && !$settings->considerHolidayAsFirstPriority)
                {
                    if(!$staffProperty->fullDayHoliday)
                    {
                        if($staffProperty->fornoonHoliday && $staffProperty->isAfternoonAbsent)
                        {
                            $isAbsent = true;
                        }
                        elseif($staffProperty->afternoonHoliday && $staffProperty->isFornoonAbsent)
                        {
                            $isAbsent = true;
                        }
                    }
                }
                else
                {
                    $isAbsent = true;
                }
                if($isAbsent)
                {
                    //is absent but he have half day leave
                    if($staffProperty->isAfternoonAbsent)
                    {
                        $staffProperty->LeaveArray[]="1/2".SettingsConstents::ABSENT.SettingsConstents::AN;
                    }
                    else{
                        $staffProperty->LeaveArray[]="1/2".SettingsConstents::ABSENT.SettingsConstents::FN;
                    }
                    //if he have approved late come or early going leaves then we add it to leaveCount
                    $staffProperty->leaveCount = (float)$staffProperty->numberOfLeave + (float)$staffProperty->smallLeaveCount;
                    $staffProperty->absentCount = .5;
                }
            }
            elseif($staffProperty->isFulldayLeave)
            {
                //is absent, and he have approved full day leave
                $staffProperty->leaveCount = 1 + (float)$staffProperty->smallLeaveCount;
            }
            else
            {
                
                //is absent, and he also did't have any approved leave or may be he have approved late come or early going leaves
                $staffProperty->LeaveArray[]=SettingsConstents::ABSENT;
                //if he have approved late come or early going leaves then we add it to leaveCount
                $staffProperty->leaveCount = (float)$staffProperty->smallLeaveCount;
                $staffProperty->absentCount = 1 - $staffProperty->leaveCount;
            }
            return $staffProperty;
        }
        elseif ($staffProperty->missPunch && $staffProperty->ispresent)
        {
            //miss punching
            if($staffProperty->isleave && $staffProperty->isHalfdayLeave)
            {
                //and he have leave
                $staffProperty->leaveCount = (float)$staffProperty->numberOfLeave;
                $staffProperty->absentCount = .5;
                if($staffProperty->punchOutDone && !$staffProperty->punchInDone)
                {
                    $staffProperty->LeaveArray[] = "1/2".SettingsConstents::CUTTING."(".SettingsConstents::PUNCH_IN_MISS.")";
                }
                elseif(!$staffProperty->punchOutDone && $staffProperty->punchInDone)
                {
                    $staffProperty->LeaveArray[] = "1/2".SettingsConstents::CUTTING."(".SettingsConstents::PUNCH_OUT_MISS.")";
                }
                //if he have approved late come or early going leaves then we add it to leaveCount
                $staffProperty->leaveCount = (float)$staffProperty->numberOfLeave + (float)$staffProperty->smallLeaveCount;
                $staffProperty->presentCount = .5 - (float)$staffProperty->leaveCount;
            }
            elseif($staffProperty->isleave && $staffProperty->isFulldayLeave)
            {
                $staffProperty->leaveCount = 1 + (float)$staffProperty->smallLeaveCount;
            }
            else 
            {
                if($staffProperty->punchOutDone && !$staffProperty->punchInDone)
                {
                    $staffProperty->LeaveArray[] = "1/2".SettingsConstents::CUTTING."(".SettingsConstents::PUNCH_IN_MISS.")";
                }
                elseif(!$staffProperty->punchOutDone && $staffProperty->punchInDone)
                {
                    $staffProperty->LeaveArray[] = "1/2".SettingsConstents::CUTTING."(".SettingsConstents::PUNCH_OUT_MISS.")";
                }
                //Grace time exeeded
                if($staffProperty->graceTimeExeeded)
                {
                    $staffProperty->LeaveArray[]="1/2".SettingsConstents::ABSENT;
                    $staffProperty->absentCount += .5;
                }
                else
                {
                    $staffProperty->LeaveArray[] = "1/2".SettingsConstents::PRESENT;
                    $staffProperty->presentCount = .5 - (float)$staffProperty->leaveCount;
                }
                $staffProperty->absentCount += .5;
                //if he have approved late come or early going leaves then we add it to leaveCount
                $staffProperty->leaveCount = (float)$staffProperty->smallLeaveCount;
            }
            return $staffProperty;
        }
        elseif(!$staffProperty->missPunch && !$staffProperty->isAbsent && $staffProperty->ispresent)
        {
            if($staffProperty->inTime)
            {
                //he is in time
                if($staffProperty->isleave && $staffProperty->isHalfdayLeave)
                {
                    if($staffProperty->exceedDailyGraceTime)
                    {
                        $staffProperty->LeaveArray[] = "1/2".SettingsConstents::PRESENT;
                        $staffProperty->absentCount = 1-(float)$staffProperty->leaveCount;
                    }
                    else
                    {
                        $staffProperty->LeaveArray[] = "1/2".SettingsConstents::PRESENT;
                        $staffProperty->presentCount = 1-(float)$staffProperty->leaveCount;
                    }   
                    //if he have approved late come or early going leaves then we add it to leaveCount
                    $staffProperty->leaveCount = (float)$staffProperty->numberOfLeave + (float)$staffProperty->smallLeaveCount;
                }
                elseif($staffProperty->isleave && $staffProperty->isFulldayLeave)
                {
                    //if he have approved late come or early going leaves then we add it to leaveCount
                    $staffProperty->leaveCount = 1 + (float)$staffProperty->smallLeaveCount;
                }
                else
                {
                    $staffProperty->LeaveArray[] = SettingsConstents::PRESENT;
                    //if he have approved late come or early going leaves then we add it to leaveCount
                    $staffProperty->leaveCount = (float)$staffProperty->smallLeaveCount;
                    $staffProperty->presentCount = 1 - (float)$staffProperty->leaveCount;
                }
            }
            elseif($staffProperty->notInTime)
            {
                //he is not in time 
                //if threshold time is enabled and staff absent time exeed threshold time then he will be absent 
                if($settings->useLOPThresholdTime && $staffProperty->exceedThersholdTime)
                {
                    $staffProperty->LeaveArray[]=SettingsConstents::THRESHOLD_TIME_EXEED."(".SettingsConstents::ABSENT.")";
                    $staffProperty->absentCount = 1;
                }
                elseif($staffProperty->graceTimeExeeded)
                {
                    //his late time exeeded
                    if($staffProperty->isleave && $staffProperty->isHalfdayLeave)
                    {
                        $staffProperty->absentCount = .5;
                        $staffProperty->LeaveArray[] = "1/2".SettingsConstents::CUTTING."(".SettingsConstents::TIME_EXEEDED.")";
                        $staffProperty->leaveCount = (float)$staffProperty->numberOfLeave + (float)$staffProperty->smallLeaveCount;
                        $staffProperty->presentCount = .5 - (float)$staffProperty->leaveCount;
                    }
                    elseif($staffProperty->isleave && $staffProperty->isFulldayLeave)
                    {
                        $staffProperty->leaveCount   = 1 + (float)$staffProperty->smallLeaveCount;
                    }
                    else
                    {
                        if( strtotime($attendance->inTime) <= strtotime($attendance->actualPunchIn))
                        {
                            $perfectInPunch = true;
                        }
                        else{
                            $perfectInPunch = false;
                        }
                        if( strtotime($attendance->outTime) >= strtotime($attendance->actualPunchOut))
                        {
                            $perfectOutPunch = true;
                        }
                        else{
                            $perfectOutPunch = false;
                        }
                        if(!$perfectInPunch)
                        {
                            $cuttingConstant = SettingsConstents::LATE_COMING;
                        }
                        
                        if(!$perfectOutPunch)
                        {
                            if(!$perfectInPunch)
                            {
                                $cuttingConstant = SettingsConstents::FD;
                            }
                            else{
                                $cuttingConstant = SettingsConstents::EARLY_GOING;
                            }
                        }
                        $staffProperty->absentCount = .5;
                        $staffProperty->LeaveArray[] = "1/2".SettingsConstents::PRESENT;
                        $staffProperty->LeaveArray[] = "1/2".SettingsConstents::CUTTING."(".$cuttingConstant.")";
                        $staffProperty->leaveCount = (float)$staffProperty->smallLeaveCount;
                        $staffProperty->presentCount = .5 - $staffProperty->leaveCount;
                    }
                }
                else
                {
                    //late time not exeeded
                    if($staffProperty->isleave && $staffProperty->isHalfdayLeave)
                    {
                        if($staffProperty->exceedDailyGraceTime)
                        {
                            $staffProperty->LeaveArray[]="1/2".SettingsConstents::ABSENT;
                            $staffProperty->absentCount += .5;
                        }
                        else
                        {
                            $staffProperty->LeaveArray[] = "1/2".SettingsConstents::PRESENT;
                            $staffProperty->presentCount = 1 - (float)$staffProperty->leaveCount;
                        }
                        
                        $staffProperty->leaveCount   = (float)$staffProperty->numberOfLeave + (float)$staffProperty->smallLeaveCount;
                        
                    }
                    elseif($staffProperty->isleave && $staffProperty->isFulldayLeave)
                    {
                        $staffProperty->leaveCount   = 1 + (float)$staffProperty->smallLeaveCount;
                    }
                    else
                    {
                        $staffProperty->LeaveArray[] = SettingsConstents::PRESENT;
                        $staffProperty->leaveCount = (float)$staffProperty->smallLeaveCount;
                        $staffProperty->presentCount = 1 - $staffProperty->leaveCount;
                    }
                }
            }
            return $staffProperty;
        }
    }
    public function graceCalculator1($time1,$time2)
    {
        $grace = 0;
        if($time1 >= $time2)
            $grace = ((strtotime($time1) - strtotime($time2)) / 60) + $grace;
            return $grace;
    }
    public function graceCalculator2($time1,$time2)
    {
        $grace = 0;
        if($time1 <= $time2)
            $grace = ((strtotime($time2) - strtotime($time1)) / 60) + $grace;
            return $grace;
    }
    public function getPunchTimeDifferenceInMinutes($attendance)
    {
        if(trim($attendance->inTime) == "00:00:00" || trim($attendance->outTime) == "00:00:00"){
            return 0;
        }
        $punchInTime = $attendance->punchDate." ".$attendance->inTime;
        $punchInTime = new DateTime($punchInTime);
        $punchOutTime = $attendance->punchDate." ".$attendance->outTime;
        $punchTimeDifference = $punchInTime->diff(new DateTime($punchOutTime));
        $punchTimeDifferenceInMinutes   = $punchTimeDifference->format('%h')*60 + $punchTimeDifference->format('%i');
        return $punchTimeDifferenceInMinutes;
    }
    public function getActualPunchTimeDifferenceInMinutes($attendance)
    {
        if(trim($attendance->actualPunchIn) == "00:00:00" || trim($attendance->actualPunchOut) == "00:00:00"){
            return 0;
        }
        $actualPunchInTime = $attendance->punchDate." ".$attendance->actualPunchIn;
        $actualPunchInTime = new DateTime($actualPunchInTime);
        $actualPunchOutTime = $attendance->punchDate." ".$attendance->actualPunchOut;
        $actualPunchTimeDifference = $actualPunchInTime->diff(new DateTime($actualPunchOutTime));
        $actualPunchTimeDifferenceInMinutes = $actualPunchTimeDifference->format('%h')*60 + $actualPunchTimeDifference->format('%i');
        return $actualPunchTimeDifferenceInMinutes;
    }
    public function validateLeaveRespectingLeaveDuration($appliedLeave,$settings,$attendance)
    {
        $currentDate = date_format(new DateTime($attendance->date), 'Y-m-d');
        $leaveDate = date_format(new DateTime($appliedLeave->appliedDate), 'Y-m-d' );
        if(strtotime($currentDate) == strtotime($leaveDate))
        {
            $leaveTime = date_format(new DateTime($appliedLeave->appliedDate), 'H:i:s' );
            $staffMustApplyBefor =  strtotime('-'.$settings->leaveApplyDuration.' minutes',strtotime(date_format(new DateTime($attendance->actualPunchOut), 'H:i:s')));
            //apply within an hour and before that may not be reflected in consolidated Leave report 
            if($staffMustApplyBefor > strtotime($leaveTime))
            {
                $haveLeave = true;
            }
        }
        elseif(strtotime($currentDate) > strtotime($leaveDate))
        {
            $haveLeave = true;
        }
        return $haveLeave;
    }
    public function validateLeave ($time1,$time2,$settings,$dayStart,$dayEnd)
    {
        if($settings->considerLeaveApplyDuration)
        {
            $time1 = date_format(new DateTime($time1), 'H:i:s');
            $time2 = date_format(new DateTime($time2), 'H:i:s');
            // if($dayStart)
            // {
            //     $anstime = $time1 > $time2 ? 0 : (strtotime($time2) - strtotime($time1))/60;
            // }
            // else if($dayEnd)
            // {
            //     $anstime = $time1 > $time2 ? (strtotime($time1) - strtotime($time2))/60 : 0 ;
            // }
            $anstime = $time1 > $time2 ? (strtotime($time1) - strtotime($time2))/60 : (strtotime($time2) - strtotime($time1))/60 ;
            
            if($settings->leaveApplyDuration >= $anstime)
            {
                return true;
            }
            else
            {
                 return false;
            }
        }
        else
        {
            return true;
        }
    }
    public function payRollCalculation($request)
    {
        $period = CommonUtil::getDatePeriodIterator($request->startDate, CommonUtil::addOneDay($request->endDate));
        $hrHolidayList =  CalendarService::getInstance()->getAllHolidaysWithGivenDateRange($request->startDate, $request->endDate);
        //$hrHolidays =  CalendarService::getInstance()->getAllHolidaysWithGivenDateRange($request->startDate, $request->endDate);
        //$deptHolidays = CalendarService::getInstance()->getAllDepartmentHolidayBetweenDateRange ( $request->startDate, $request->endDate, 1 );
        $staffList = $this::getInstance()->getStaffLeaveReportForAGivenDateRange($request);
        
        $settings = CommonService::getInstance()->getSettings(SettingsConstents::STAFF_ATTENDANCE, SettingsConstents::CONSOLIDATED_LEAVE_REPORT_SETTINGS);
        $settings = json_decode($settings);
        
        if (empty($staffList)) 
        {
            $returnObject = new stdClass;
            $returnObject->success = false;
            $returnObject->errorMessage[] = "No staffs Found";
            //$returnObject->partialSuccess = false;
        }
        else
        {
            $staffPayroll = new stdClass;
            $staffPayRollList = $this::getInstance()->getStaffPayrollDetailsWithPayrollId($request);
            $slNo = 0;
            foreach ($staffList as $staff)
            {
                //helping hand for debugging
                // if($staff->staffId == "202")
                // {
                //     $test = "hi";
                // }
                $slNo++;
                $staffPayroll->presentDays = 0;
                $staffPayroll->absentDays = 0;
                $staffPayroll->leaveDays = 0;
                $staffPayroll->holidays =0;
                $staffPayroll->undefinedDays = 0;
                $staffDayLeave = new stdClass();
                foreach ($period as $dt)
                {
                    if($settings->graceTimePerMonthInMin)
                    {
                        $staffProperty = new ConsolidatedStaffLeaveReport();
                        //grace time calculations are done here
                        $returnValue = $this::getInstance()->showStaffAttendanceDetails($staff, $dt, $hrHolidayList, $settings, $staffProperty);
                        $staffPayroll->presentDays += $staffProperty->presentCount;
                        $staffPayroll->absentDays += $staffProperty->absentCount;
                        $staffPayroll->leaveDays += $staffProperty->leaveCount;
                        $staffPayroll->holidays += $staffProperty->holidayCounter;
                        if($staffProperty->absentCount)
                        {
                            $staffDayAbsentCount = new stdClass();
                            $staffDayAbsentCount->absentCount = $staffProperty->absentCount;
                            $staffDayAbsentCount->date = $dt->format('Y-m-d');
                            if($staffProperty->isFornoonAbsent)
                            {
                                $staffDayAbsentCount->session = "FN";
                            }
                            else if($staffProperty->isAfternoonAbsent)
                            {
                                $staffDayAbsentCount->session = "AN";
                            }
                            else
                            {
                                $staffDayAbsentCount->session = "FD";
                            }
                            $staffDayAbsentCount->whyabsent = $this::getInstance()->whyAbsent($staffProperty);
                            $staffDayLeave->staffDayAbsentCount[] = $staffDayAbsentCount;
                        }
                        if($staffProperty->undefinedDays)
                        {
                            $staffPayroll->undefinedDays ++;
                        }
                        
                        foreach ($staffProperty->singleDayLeaveAndLeaveTypes as $dayLeaveTypes=>$inDayLeaves)
                        {
                            //leaves taken by staff 
                            $staffDayLeave->totalMonthlyLeaves[$dayLeaveTypes]+=$inDayLeaves;
                            if($staffProperty->isleave)
                            {
                                $staffDayLeaveCount = new stdClass();
                                $staffDayLeaveCount->leaveCount = $staffProperty->leaveCount;
                                $staffDayLeaveCount->leaveType = $dayLeaveTypes;
                                $staffDayLeaveCount->date = $dt->format('Y-m-d');
                                $staffDayLeave->staffDayLeaveCount[]=$staffDayLeaveCount;
                            }
                        }
                    }
                }
                $staffPayroll->staffDayLeave = $staffDayLeave;
                $recordExist = false;
                foreach($staffPayRollList as $staffDetails)
                {
                    if($staffDetails->staff_id == $staff->staffId)
                    {
                        $recordExist = true;
                        break;
                    }
                }
                if($recordExist)
                {
                    $returnObject = $this::getInstance()->updatePayrollDetails($staffPayroll,$request,$staffDetails,$returnObject);
                }
                else
                {
                    $returnObject = $this::getInstance()->insertPayrollDetails($staffPayroll,$request,$returnObject,$staff);
                }
            }  
        }
        $this::getInstance()->updatePayrollPeriod($request);
        return $returnObject;
    }
    
    public function showStaffAttendanceDetails($staff, $date, $hrHolidayList, $settings, $staffProperty)
    {
        $dateMatched = false;
        foreach ($staff->attendance as $attendance) 
        {
            if ($date->format('Y-m-d') == $attendance->date) 
            {
                $dateMatched = true;
                if ($hrHolidayList[$date->format('Y-m-d')] && (in_array($staff->deptId,$hrHolidayList[$date->format('Y-m-d')]->dept) || in_array("0",$hrHolidayList[$date->format('Y-m-d')]->dept))) 
                {
                    if($hrHolidayList[$date->format('Y-m-d')]->session == 'FD' || empty( $hrHolidayList[$date->format('Y-m-d')]->session ) )
                    {
                        $staffProperty->holidayCounter = 1;
                        $staffProperty->fullDayHoliday = true;
                    }
                    else 
                    {
                        $staffProperty->holidayCounter = .5;
                        if($hrHolidayList[$date->format('Y-m-d')]->session == 'FN')
                        {
                            $staffProperty->fornoonHoliday = true;
                        }
                        else
                        {
                            $staffProperty->afternoonHoliday = true;
                        }
                    }
                    $staffProperty->LeaveArray[] =SettingsConstents::HOLIDAY;
                    $staffProperty->holiday = true;
                    if(!$settings->considerHolidayAsFirstPriority)
                    {
                        $holiday = true;
                    }
                    return $staffProperty;
                }
                $staffProperty->holiday = false;
                return $this::getInstance()->getLeaveDetails($attendance, $settings, $staffProperty);
            }
        }
        if (! $dateMatched)
        {
            if ($hrHolidayList[$date->format('Y-m-d')] && (in_array($staff->deptId,$hrHolidayList[$date->format('Y-m-d')]->dept) || in_array("0",$hrHolidayList[$date->format('Y-m-d')]->dept)))
            {
                $staffProperty->LeaveArray[] =SettingsConstents::HOLIDAY;
                $staffProperty->holiday = true;
                if($hrHolidayList[$date->format('Y-m-d')]->session == 'FD' || empty( $hrHolidayList[$date->format('Y-m-d')]->session ) )
                {
                    $staffProperty->holidayCounter = 1;
                    $staffProperty->fullDayHoliday = true;
                }
                else 
                {
                    $staffProperty->holidayCounter = .5;
                    if($hrHolidayList[$date->format('Y-m-d')]->session == 'FN')
                    {
                        $staffProperty->fornoonHoliday = true;
                    }
                    else
                    {
                        $staffProperty->afternoonHoliday = true;
                    }
                }
                if(!$settings->considerHolidayAsFirstPriority)
                {
                    $holiday = true;
                    $this::getInstance()->getLeaveDetails($attendance, $settings, $staffProperty,$holiday);
                }
                return $staffProperty;
            }
        }
        $staffProperty->undefinedDays=true;
        return $staffProperty;
    }
    public function getLeaveDetails($attendance, $settings, $staffProperty,$holiday = false)
    {
        if ($settings->graceTimePerMonthInMin)
        {
            if($attendance->actualPunchIn == "00:00:00" || empty($attendance->actualPunchIn) || $attendance->actualPunchOut == "00:00:00" || empty($attendance->actualPunchOut) )
            {
                $staffProperty->noActualPunch = true;
                $staffProperty->undefinedDays=true;
                return $staffProperty;
            }
            $staffProperty = StaffLeaveService::getInstance()->getStaffDayDetails($attendance,$settings,$staffProperty,$holiday);
        }
    }
    public function getStaffPayrollDetailsWithPayrollId($request)
    {
        $request = $this->realEscapeObject($request);
        if($request && $request->payrollPeriodId)
        {
            //get pay roll with date and id in the request  
            $sql = "SELECT pay.id,pay.form_date,pay.to_date,pay.name,pay.description,pay.type,payl.staff_id,payl.absent_count,payl.leave_count,payl.present_count,payl.leave_details
            FROM hr_pay_roll_period pay 
            INNER JOIN hr_staff_payroll_leave_details payl ON payl.pay_roll_id = pay.id
            WHERE pay.id=$request->payrollPeriodId;";
            try {
                $staffList = $this->executeQueryForList($sql);
            } catch (\Exception $e) {
                throw new ProfessionalException($e->getCode(), $e->getMessage());
            }
            return $staffList;
        }
    }
    public function updatePayrollDetails($staffPayroll,$request,$staffDetails,$returnObject)
    {
        $request = $this->realEscapeObject($request);
        $leaves = json_encode($staffPayroll->staffDayLeave);
        $sql = "UPDATE hr_staff_payroll_leave_details SET absent_count=$staffPayroll->absentDays, leave_count=$staffPayroll->leaveDays, present_count=$staffPayroll->presentDays, leave_details='$leaves',updated_by='$request->currentStaff', updated_date=utc_timestamp() WHERE pay_roll_id='$request->payrollPeriodId' and staff_id = $staffDetails->staff_id;";
        try {
            $this->executeQuery($sql);
            $returnObject->success = true;
        } 
        catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
            $returnObject->success = false;
            $returnObject->errorMessage[] = "Couldn't update $staffDetails->staffName details";
        }
        return $returnObject; 
    }
    public function insertPayrollDetails($staffPayroll,$request,$returnObject,$staff)
    {
        $request = $this->realEscapeObject($request);
        $leaves = json_encode($staffPayroll->staffDayLeave);
        $sql = "INSERT INTO hr_staff_payroll_leave_details (staff_id, pay_roll_id, absent_count, leave_count, present_count, leave_details, created_by, created_date, updated_by, updated_date) VALUES ('$staff->staffId', '$request->payrollPeriodId', '$staffPayroll->absentDays', '$staffPayroll->leaveDays', '$staffPayroll->presentDays', '$leaves', $request->currentStaff, utc_timestamp(), $request->currentStaff, utc_timestamp());";
        try {
         $this->executeQuery($sql);
         $returnObject->success = true;
        } 
        catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
            $returnObject->success = false;
            $returnObject->errorMessage[] = "Couldn't create $staff->staffName details";
        }
        return $returnObject; 
    }
    public function getStaffPayrollPeriods($id = null)
    {
        $id = $this->realEscapeString($id);
        $condition .= $id?" and id = $id ":"";  
        $sql = "SELECT 
        hrpay.id, hrpay.form_date, hrpay.to_date, hrpay.name, hrpay.description, hrpay.type, istaff.staffName AS createdStaff ,DATE_FORMAT(CONVERT_TZ(hrpay.created_date , '+00:00', @@global .time_zone), '%Y-%m-%d %H:%i:%s') as created_date, ustaff.staffName AS updatedStaff, DATE_FORMAT(CONVERT_TZ(hrpay.updated_date , '+00:00', @@global .time_zone), '%Y-%m-%d %H:%i:%s') as updated_date
        FROM hr_pay_roll_period hrpay
        LEFT JOIN staffaccounts istaff ON istaff.staffID = hrpay.created_by
        LEFT JOIN staffaccounts ustaff ON ustaff.staffID = hrpay.updated_by
        WHERE 1=1 $condition;";
        try 
        {
            $staffList = $this->executeQueryForList($sql);
        } 
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffList;
    }
    public function updatePayrollPeriod($request)
    {
        $request = $this->realEscapeObject($request);
        $sql = "UPDATE hr_pay_roll_period SET updated_by='$request->currentStaff', updated_date= utc_timestamp() WHERE id='$request->payrollPeriodId';";
        try 
        {
            $this->executeQuery($sql);
        } 
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function getStaffLeaveDetails($request)
    {
        $request = $this->realEscapeObject($request);
        $sectionID = $request->sectionID;
        if($request->endDate != $request->startDate)
        {
            if (!empty($request->startDate)) {
                $criteria .= "  AND (la.startDate >= '$request->startDate' OR
                                  ('$request->startDate' BETWEEN la.startDate and la.endDate) ) ";
            }
            //endDate
            if (!empty($request->endDate)) {
                $criteria .= "  AND (la.endDate <= '$request->endDate' OR
                    ('$request->endDate' BETWEEN la.startDate and la.endDate) ) ";
            }
        }
        else
        {
            if (!empty($request->startDate)) {
                $criteria .= "  AND (la.startDate = '$request->startDate' OR
                                  ('$request->startDate' BETWEEN la.startDate and la.endDate) ) ";
            }
        }
        $criteria .= $request->staffID?" and st.staffID = '$request->staffID'":"";
        $criteria .= $request->leaveID?" and la.leaveID = '$request->leaveID'":"";
        if(in_array("",$sectionID))
        {
            $criteria .= "";
        }
        else{
                $criteria .= " and la.sectionID in (".implode(",",$sectionID).")";
        }
        $sql = "SELECT 
        la.applicationID, la.startDate, la.endDate, st.staffName, lt.leaveName, ld.daytypeName, sec.sectionName, la.noofDays, la.noofleaves, la.sectionID, la.designationID, la.leaveDesc, st.staffAccount, la.leaveSub, lt.leaveDesc as leaveTypeDesc, la.leaveID, st.staffID ,pay.id,pay.present_count,pay.absent_count,pay.leave_details,pay.leave_count,
        lt.required_leavecrtfct, lt.leaveperiod_start, lt.leaveperiod_end,
        la.hr_group_lvapplnids_id,
        hrc.filepath, hrc.filename,
        lt.leaveperiod_end,lt.leaveperiod_start,st.staffID,la.leaveID,la.hr_group_lvapplnids_id,
        st.deptID
        FROM staffaccounts st
        LEFT JOIN hr_staff_payroll_leave_details pay on pay.staff_id = st.staffID and pay.pay_roll_id = $request->payrollPeriodId
        LEFT JOIN hr_leave_applications la ON st.staffID = la.staffID  AND la.approved = 1 $criteria
        LEFT JOIN hr_leavetypes lt ON lt.leaveID = la.leaveID
        LEFT JOIN hr_leave_daytype ld ON ld.daytypeID = la.daytypeID
        LEFT JOIN hr_sections sec ON sec.sectionID = la.sectionID
        LEFT JOIN hr_leaveapplication_certificates hrc on hrc.hr_group_lvapplnids_id = la.hr_group_lvapplnids_id
        WHERE st.isResigned = 0 ORDER BY la.startDate,st.staffAccount DESC";
        try 
        {
            $leaveDetails = $this->executeQueryForList($sql);
        } 
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $leaveDetails;
    }
    public function staffLeaveCertificationCount($staffLeaveDetail)
    {
        $sql = "select count(hr_group_lvapplnids_id) as count from hr_leave_applications where startDate >= '$staffLeaveDetail->leaveperiod_start' and endDate <='$staffLeaveDetail->leaveperiod_end' and staffID='$staffLeaveDetail->staffID' and leaveID='$staffLeaveDetail->leaveID' and hr_group_lvapplnids_id < '$staffLeaveDetail->hr_group_lvapplnids_id' and hr_group_lvapplnids_id not in(select hr_group_lvapplnids_id from hr_leaveapplication_certificates)";
        try 
        {
            $leaveDetails = $this->executeQueryForList($sql);
        } 
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $leaveDetails->count ;
    }
    public function getHrSectionDetailBySectionID($sectionID = false)
    {
        $sectionID = $this->realEscapeArray($sectionID);
        $sectionIds = $sectionID?implode(",",$sectionID):"";
        $condition = $sectionIds?" WHERE sectionID IN (".$sectionIds .")":"";
        $sql = "SELECT sectionID, sectionName, sectionDesc from hr_sections $condition order by sectionName asc";
        try 
        {
            $hrSections= $this->executeQueryForList($sql);
            $sectionsArray=[];
            foreach($hrSections as $hr)
            {
                $sectionsArray[]= $hr->sectionName;
            }
        } 
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return implode(",",$sectionsArray);
    }
    public function getStaffNumberOfLeaveApplicationLimit($leaveID,$staffID)
    {
        $sql = "SELECT IF(hrlt.noofleaveappliaction < COUNT(hrl.applicationID) + 1,'false','true') as confirm FROM  hr_leavetypes hrlt 
        INNER JOIN hr_leave_applications hrl ON hrlt.leaveperiod_start < hrl.startDate AND hrlt.leaveperiod_end > hrl.endDate AND hrlt.leaveID = hrl.leaveID
        WHERE hrl.staffID = $staffID AND hrlt.leaveID = $leaveID;";
        try 
        {
            return CommonUtil::stringToBoolean($this->executeQueryForObject($sql)->confirm);
        } 
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function getReportRulesOfLeaveTypes($id = null)
    {
        $condition = $id?"WHERE leaveID = ".$id:"";
        $sql = "SELECT leaveID,leaveName,report_rules FROM hr_leavetypes $condition;";
        try 
        {
            return $this->executeQueryForList($sql);
        } 
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function getStaffLeaveApplicationByGroupID($grpID)
    {
        $sql = "select applicationID,staffID, designationID, sectionID, leaveID, leaveSub, leaveDesc, startDate, endDate, daytypeID, noofDays, noofleaves, fromgained, compensation_leaveID, compensation_startdate, compensation_enddate, timeStart, timeEnd from hr_leave_applications where hr_group_lvapplnids_id=$grpID";
        try {
            $applications = $this->executeQueryForList($sql);
            return $applications;
        } catch (\Exception $e) {
            return false;
        }
    }
    
    public function getApplicationSanctionDetailsByApplicationID($id)
    {
        $sql = "select applicationID, staffID, confirmed, approved, rejected, confapprvDate, conf_rejected from hr_leave_sanctioned_person where applicationID=".$id;
        try {
            $sanctionDetails = $this->executeQueryForObject($sql);
            return $sanctionDetails;
        } catch (\Exception $e) {
            return false;
        }
    }
    public function getHrApplicationSanctionCertificatesByGroupID($id)
    {
        $sql = "select applicationID, staffID, confirmed, approved, rejected, confapprvDate, conf_rejected from hr_leave_sanctioned_person where applicationID=".$id;
        try {
            $sanctionDetails = $this->executeQueryForObject($sql);
            return $sanctionDetails;
        } catch (\Exception $e) {
            return false;
        }
    }
    /**
     * While editting a leave application we have to delete old leave 
     * This function is used while there is an error in newly created leaves then we delete new application and insert old leave; 
     */
    public function deleteNewLeaveApplicationAndInsertOld($array_applnID,$oldLeaveApplications)
    {
        if(!empty($array_applnID))
        {
            $sql = "delete from hr_leave_applications where applicationID in (".implode(',',$array_applnID).")";
            $this->executeQuery($sql);
        }
        try{
            foreach($oldLeaveApplications->applications as $application)
            {
                if($application->leavecount_leaveID)
                {
                    $sql = "INSERT INTO hr_leave_applications (staffID, designationID, sectionID, leaveID, leaveSub, leaveDesc, startDate, endDate, daytypeID, noofDays, noofleaves, fromgained, compensation_leaveID, compensation_startdate, compensation_enddate, timeStart, timeEnd) VALUES ('$application->staffID', '$application->designationID', '$application->sectionID', '$application->leaveID', '$application->leaveSub', '$application->leaveDesc', '$application->startDate', '$application->endDate', '$application->daytypeID', '$application->noofDays', '$application->noofleaves', '$application->fromgained', '$application->leavecount_leaveID', '$application->compnstfromday', '$application->compnsttoday', '$application->startTime', '$application->endTime')";
                }
                else
                {
                    $sql = "INSERT INTO hr_leave_applications (staffID, designationID, sectionID, leaveID, leaveSub, leaveDesc, startDate, endDate, daytypeID, noofDays, noofleaves, fromgained, timeStart, timeEnd) VALUES ('$application->staffID', '$application->designationID', '$application->sectionID', '$application->leaveID', '$application->leaveSub', '$application->leaveDesc', '$application->startDate', '$application->endDate', '$application->daytypeID', '$application->noofDays', '$application->noofleaves', '$application->fromgained', '$application->startTime', '$application->endTime')";
                    
                }
                $applicationIDs[] = $this->executeQueryForObject($sql.$values, true);
            }
            return $applicationIDs;
        }catch (\Exception $e) {
            return false;
        }
    }
    function whyAbsent($staffProperty)
    {
        $responseHTML ="";
        foreach($staffProperty->LeaveArray as $data)
        {
            switch ($data)
            {
                case "1/2".SettingsConstents::ABSENT:
                    $responseHTML .="1/2".SettingsConstents::ABSENT;
                    break;
                case "1/2".SettingsConstents::ABSENT.SettingsConstents::FN:
                    $responseHTML .="1/2".SettingsConstents::ABSENT.SettingsConstents::FN;
                    break;
                case "1/2".SettingsConstents::ABSENT.SettingsConstents::AN:
                    $responseHTML .="1/2".SettingsConstents::ABSENT.SettingsConstents::AN;
                    break;
                case "1/2".SettingsConstents::CUTTING."(".SettingsConstents::PUNCH_IN_MISS.")":
                    $responseHTML .="1/2".SettingsConstents::CUTTING."(".SettingsConstents::PUNCH_IN_MISS.")";
                    break;
                case "1/2".SettingsConstents::CUTTING."(".SettingsConstents::PUNCH_OUT_MISS.")":
                    $responseHTML .="1/2".SettingsConstents::CUTTING."(".SettingsConstents::PUNCH_OUT_MISS.")";
                    break;
                case SettingsConstents::THRESHOLD_TIME_EXEED."(".SettingsConstents::ABSENT.")":
                    $responseHTML .=SettingsConstents::THRESHOLD_TIME_EXEED."(".SettingsConstents::ABSENT.")";
                    break;
                case "1/2".SettingsConstents::CUTTING."(".SettingsConstents::TIME_EXEEDED.")":
                    $responseHTML .= "1/2".SettingsConstents::CUTTING."(".SettingsConstents::TIME_EXEEDED.")";
                    break;
                case SettingsConstents::ABSENT:
                    $responseHTML .=SettingsConstents::ABSENT;
                    break;
                case "1/2".SettingsConstents::CUTTING."(".SettingsConstents::LATE_COMING.")";
                    $responseHTML .= "1/2".SettingsConstents::CUTTING."(".SettingsConstents::LATE_COMING.")";
                    break;
                case "1/2".SettingsConstents::CUTTING."(".SettingsConstents::EARLY_GOING.")";
                    $responseHTML .= "1/2".SettingsConstents::EARLY_GOING."(".SettingsConstents::EARLY_GOING.")";
                    break;
                case "1/2".SettingsConstents::CUTTING."(".SettingsConstents::EARLY_GOING.")";
                    $responseHTML .= "1/2".SettingsConstents::EARLY_GOING."(".SettingsConstents::FD.")";
                    break;
            }
            $responseHTML = $responseHTML?$responseHTML." + ":"";
        }
        $responseHTML = rtrim($responseHTML,' + ');
        return $responseHTML;
    }
    public function getAllStaffWithInaSection($sectionID)
    {
        if(in_array("",$sectionID))
        {
            $sectionID = $this->realEscapeArray($sectionID);
            $sql = "select staffID,staffName,sectionID from staffaccounts";
        }
        else{
            $sectionID = $this->realEscapeArray($sectionID);
            $condString = implode(",",$sectionID);
            $condition = "WHERE sectionID in (".$condString.")";
            $sql = "select staffID,staffName,sectionID from staffaccounts $condition";
        }
        try {
            $staffDetails = $this->executeQueryForList($sql);
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    public function getPayRollPeriodByStartDateAndEndDate($startDate = null,$endDate = null)
    {
        if($startDate)
            $sql = "select * from hr_pay_roll_period where '".$startDate."' between form_date and to_date;";
        try {
            $payrollPeriod = $this->executeQueryForList($sql);
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $payrollPeriod;
    }
    public function getStaffUpdatePunchTimeRequestByPayRollPeriodID($payRollId,$staffId)
    {
        $sql = "select su.id, su.punchDate, su.punchIn, su.punchOut, su.actualpunchIn, su.actualpunchOut, su.punchtime_shiftchange, su.appliedDate, su.confirmed, su.conf_rejected, su.approved, su.rejected from staffpunchtime_shiftchange_updaterequest su 
        inner join hr_pay_roll_period pp on su.punchDate between pp.form_date and pp.to_date
        where punchtime_shiftchange = 0 and staffID = $staffId and pp.id = $payRollId and su.rejected <> 1;";
        try {
            $punchTimeRequest = $this->executeQueryForList($sql);
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $punchTimeRequest;
    }
    public function getLeaveDetailsByLeaveCode($code)
    {
        try {
            $code = $this->realEscapeString($code);
            $sql = "SELECT leaveID,leaveName,leaveDesc  FROM hr_leavetypes hl WHERE leaveName = '$code";
            return $this->executeQueryForObject($sql);
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function getDayDetailsByDayCode($code)
    {
        try {
            $code = $this->realEscapeString($code);
            $sql = "SELECT daytypeID ,daytypeName ,daytypeDesc,noofleaves  from hr_leave_daytype hld WHERE daytypeName = '$code";
            return $this->executeQueryForObject($sql);
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function updateleaveViaScript($request)
    {
        $request = $this->realEscapeObject($request);
        try{
            $sql = "INSERT
                        IGNORE
                        INTO
                        hr_leave_applications (staffID,
                        designationID,
                        sectionID,
                        leaveID,
                        leaveSub,
                        leaveDesc,
                        startDate,
                        endDate,
                        appliedDate,
                        confirmed,
                        approved,
                        rejected,
                        daytypeID,
                        noofDays,
                        noofleaves,
                        previous_leave,
                        conf_rejected,
                        fromgained,
                        compensation_leaveID,
                        compensation_startdate,
                        compensation_enddate,
                        timeStart,
                        timeEnd,
                        hr_group_lvapplnids_id)
                    VALUES($request->staffID,
                    $request->designationID,
                    $request->sectionID,
                    $request->leaveID,
                    '$request->leaveSubject',
                    '$request->leaveDesc',
                    '$request->startDate',
                    '$request->endDate',
                    NOW(),
                    0,
                    1,
                    0,
                    $request->daytypeID,
                    $request->noofDays,
                    $request->noofleaves,
                    0,
                    0,
                    $request->fromgained,
                    NULL,
                    NULL,
                    NULL,
                    NULL,
                    NULL,
                    NULL);
        ";
        $applicationID = $this->executeQueryForObject($sql, true);
        if(!$applicationID)
        {
            $updateSelect = "SELECT applicationID 
                                    from hr_leave_applications 
                                    WHERE 
                                        staffID ='$request->staffID
                                        and  designationID = '$request->designationID'
                                        and sectionID = '$request->sectionID'
                                        and startDate = '$request->startDate'
                                        and endDate = '$request->endDate' and approved = 0 ";
            $exists = $this->executeQueryForObject($updateSelect);
            if($exists)
            {
                $sqlUpdateQuery = "UPDATE hr_leave_applications SET approved = 1 where applicationID = '$exists->applicationID'";
                $applicationID = $exists->applicationID;
                $this->executeQuery($sqlUpdateQuery);
            }
            else{
                return false;
            }
        }
        $sql2 = "INSERT INTO hr_leave_sanctioned_person (applicationID,
                                                             staffID,
                                                             confirmed,
                                                             approved,
                                                             rejected,
                                                             confapprvDate,
                                                             conf_rejected) 
                                                             VALUES($applicationID,
                                                              $request->sanctioningPerson,
                                                              0,
                                                              1,
                                                              0,
                                                              NOW(),
                                                              0);
        ";
        $this->executeQuery($sql2);
        return true;
        }catch (\Exception $e) {
            return false;
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function getEscalationDetailsOfStaff($staffID)
    {
        try{
            $staffID = $this->realEscapeString($staffID);
            $sql = "SELECT
                            id,
                            time_of_escalation_in_minutes as escalationTime,
                            updated_date
                        from
                            leaveEscalation
                        WHERE
                            staffID = '$staffID'";
            return $this->executeQueryForObject($sql);
        }catch (\Exception $e) {
            return false;
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function getCurrentDateLeaves()
    {
        try{
            $result = [];
            $dateFrom = date('Y-m-d')." 00:00:00";
            $dateTo = date('Y-m-d')." 11:59:59";
            $sql = "SELECT
                            hla.applicationID ,
                            hla.staffID ,
                            s.staffName,
                            hla.leaveID ,
                            hl.leaveName ,
                            hla.designationID ,
                            hla.sectionID ,
                            hla.leaveSub ,
                            hla.leaveDesc ,
                            hla.appliedDate ,
                            hla.confirmed ,
                            hla.approved ,
                            hla.rejected ,
                            hlca.sectionID ,
                            hlca.designationID ,
                            hlca.approvalTime ,
                            hla.startDate,
                            hla.endDate,
                            hlca.approvalTimeAfternoon,
                            hld.fromTime,
                            hld.toTime
                        from
                            hr_leave_applications hla
                            inner join hr_leave_confirm_approve hlca on hlca.designationID = hla.designationID and hlca.sectionID = hla.sectionID 
                            inner join staffaccounts s on s.staffID = hla.staffID
                            inner join hr_leavetypes hl ON hl.leaveID = hla.leaveID 
                            inner join hr_leave_daytype hld ON hld.daytypeID = hla.daytypeID
                        WHERE
                            startDate BETWEEN '$dateFrom' and '$dateTo
                            GROUP BY hla.applicationID
                            ORDER BY hla.applicationID";
            $leaves = $this->executeQueryForList($sql);
            foreach ($leaves as $leave) {
                    if($leave->fromTime)
                    {
                        $dateTime = new DateTime($leave->fromTime);
                        $amOrpm = $dateTime->format('A');
                        if($amOrpm == "AM")
                        {
                            if(strtotime($leave->approvalTime) < time())
                            {
                                $result[] = $leave;
                            }
                        }
                        elseif ($amOrpm == "PM") {
                            if(strtotime($leave->approvalTimeAfternoon) < time())
                            {
                                $result[] = $leave;
                            }                        
                        }
                    }
                    else{
                        $result[] = $leave;
                    }
                    $sqlLeavePolicy = "";
            }
            return $result;
        }catch (\Exception $e) {
            return false;
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function updateLeaveEscalation($applicationID,$approve,$reject)
    {
        try{
            $applicationID = $this->realEscapeString($applicationID);
            $confirm = $this->realEscapeString($confirm);
            $approve = $this->realEscapeString($approve);
            $sql = "SELECT applicationID  from hr_leave_applications hla WHERE applicationID = '$applicationID";
            $exists = $this->executeQueryForObject($sql);
            $reponse = new stdClass();
            $reponse->msg = "";
            $reponse->data = "";
            if($exists->applicationID)
            {
                $sqlUpdate = "UPDATE hr_leave_applications SET approved = '$approve',rejected = '$reject' WHERE applicationID = '$applicationID";
                $this->executeQuery($sqlUpdate);
                $sanctionCheck = "SELECT applicationID from hr_leave_sanctioned_person WHERE applicationID = '$exists->applicationID";
                $sanctioned = $this->executeQueryForObject($sanctionCheck);
                if($sanctioned->applicationID)
                {
                    $sql = "UPDATE hr_leave_sanctioned_person SET approved = '$approve',rejected = '$reject' WHERE applicationID = '$sanctioned->applicationID";
                }
                else{
                    
                    $staffID = $_SESSION['staffID'];
                     $sql="INSERT INTO hr_leave_sanctioned_person (applicationID,
                                                                     staffID,
                                                                     confirmed,
                                                                     approved,
                                                                     rejected,
                                                                    confapprvDate,
                                                                    conf_rejected) 
                                                                    VALUES('$applicationID', $staffID, 0, $approve$reject, NOW(), 0);
                     ";
                }
                $this->executeQuery($sql);
                $reponse->data = true;
            }
            else{
                $reponse->msg = "Application ID Not Found ";
            }
        }catch (\Exception $e) {
            $reponse->data = false;
            $reponse->msg = $e->getMessage();
            return $reponse;
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $reponse;
    }
    public function checkForEscalationStatus($designationID,$sectionID, $time, $applicationID)
    {
        try {
            $response = new stdClass();
            $response->msg = "";
            $response->data = "";
            $designationID = $this->realEscapeString($designationID);
            $sectionID = $this->realEscapeString($sectionID);
            $applicationID = $this->realEscapeString($applicationID);
            $time = $this->realEscapeString($time);
            $sessionTime = $this->getSessionTimeFromLeaveApplicationID($applicationID)->fromTime;
            $dateTime = new DateTime($sessionTime);
            $amOrpm =  $dateTime->format('A'); // 'A' ret
            $sql = "SELECT hlca.approvalTime,hlca.approvalTimeAfternoon from hr_leave_confirm_approve hlca WHERE sectionID = '$sectionID' AND designationID= '$designationID' and approve =1 order by approvalTime DESC";
            $result = $this->executeQueryForObject($sql);
            if($result->approvalTime)
            {
                
                if($amOrpm == "AM")
                {
                    $approvalTime = $result->approvalTime;
                }
                else{
                    $approvalTime = $result->approvalTimeAfternoon;
                }
                $dateTime = new DateTime($approvalTime);
                $dateTime->modify("+$time minutes");
                $newTime = $dateTime->format('H:i:s');
                $currentDateTime = new DateTime();
                if ($dateTime < $currentDateTime) {
                    $response->data = false;
                    $response->msg = "Time Exceeded For Approval";
                } else {
                    $response->data = true;
                }
            }
            else{
                $response->data = true;
                $response->msg = "Some data like Designation/Section/Approval time not set";
                
            }
            
        }catch (\Exception $e) {
            $response->data =  false;
            $response->msg =  $e->getMessage();
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $response;
    }
    public function getstaffLeaveDetailsByApplicationID($applicationID)
    {
        try{
            $applicationID = $this->realEscapeString($applicationID);
            $sql = "SELECT applicationID ,
                           staffID ,
                           designationID ,
                           sectionID ,
                           leaveID ,
                           leaveSub ,
                           leaveDesc ,
                           startDate ,
                           endDate ,
                           noofleaves,
                           noofDays * noofleaves as totalLeave ,
                           noofDays
                           from hr_leave_applications 
                           WHERE applicationID = $applicationID";
            return $this->executeQueryForObject($sql);
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function getPayrollPeriodByDate($date)
    {
        try{
            $date = $this->realEscapeString($date);
            $sql = "SELECT id,name,form_date,to_date from hr_pay_roll_period WHERE '$date' >= form_date and '$date' <= to_date ";
            return $this->executeQueryForObject($sql);
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function getPayrollProcessedStatus($staffID, $payRollId)
    {
        try{
            $staffID = $this->realEscapeString($staffID);
            $payRollId = $this->realEscapeString($payRollId);
            $sql = "SELECT id FROM hr_staff_payroll_leave_details WHERE staff_id = $staffID and pay_roll_id = $payRollId";
            $status = $this->executeQueryForObject($sql);
            if($status)
            {
                //payroll already processed
                return true;
            }
            else{
                  //payroll not processed
                  return false;
            }
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function updateLeaveByApplicationID($appID, $fromDate, $toDate)
    {
        try{
            $appID = $this->realEscapeString($appID);
            $fromDate = $this->realEscapeString($fromDate);
            $toDate = $this->realEscapeString($toDate);
            $staffID = $_SESSION['staffID'];
            // $diff = abs(strtotime($fromDate) - strtotime($toDate));
            // $days = floor($diff / (60 * 60 * 24));
            $date1 = new DateTime($fromDate);
            $date2 = new DateTime($toDate);
            $diff = $date1->diff($date2);
            $days = $diff->days + 1;
            $sqlUpdate = "UPDATE hr_leave_applications SET startDate = '$fromDate', endDate='$toDate', noofDays=$days WHERE applicationID = $appID";
            $this->executeQuery($sqlUpdate);
            $sqlgetLog = "SELECT log from hr_leave_sanctioned_person WHERE applicationID = $appID";
            $log = $this->executeQueryForObject($sqlgetLog);
            if(!$log)
            {
                $log = [];
            }
            else{
                $log = json_decode($log);
            }
            $logEntry = new \stdClass();
            $logEntry->staffID = $staffID;
            $logEntry->time = date('Y-m-d H:i:s');
            $logEntry->from = $fromDate;
            $logEntry->to = $toDate;
            $log [] = $logEntry;
            $jsonLog = json_encode($log);
            $sqlSanctionUpdate = "UPDATE hr_leave_sanctioned_person SET isEdited = 1, log = '$jsonLog' WHERE applicationID = $appID";
            $this->executeQuery($sqlSanctionUpdate);
            return true;
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function getSessionTimeFromLeaveApplicationID($appID)
    {
        try{
            $appID = $this->realEscapeString($appID);
            $sql = "SELECT  hld.fromTime,hld.toTime from hr_leave_applications hla inner join hr_leave_daytype hld  on hla.daytypeID = hld.daytypeID  WHERE applicationID = $appID";
            return $this->executeQueryForObject($sql);
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function checkForExistingLeave($date, $appID)
    {
        try{
            $date = $this->realEscapeString($date);
            $appID = $this->realEscapeString($appID);
            $staffSql = "SELECT staffID from hr_leave_applications WHERE applicationID = $appID";
            $staffID = $this->executeQueryForObject($staffSql)->staffID;
            if($staffID)
            {
                $sql = "SELECT applicationID  from hr_leave_applications hla WHERE '$date' BETWEEN startDate and endDate and applicationID != '$appID' and staffID = '$staffID";
                $exists = $this->executeQueryForObject($sql) ? true : false;
            }
            return $exists;
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
   
}