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 / 274
CRAP
0.00% covered (danger)
0.00%
0 / 6854
StaffService
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 274
1794260.00
0.00% covered (danger)
0.00%
0 / 6854
 __construct
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 4
 __clone
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 2
 getInstance
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 7
 getAllFaculties
0.00% covered (danger)
0.00%
0 / 1
240.00
0.00% covered (danger)
0.00%
0 / 23
 getAllFacultiesForApi
0.00% covered (danger)
0.00%
0 / 1
90.00
0.00% covered (danger)
0.00%
0 / 38
 getStaffByDepartment
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 24
 getStaffByIds
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 getStaffNameById
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 getStaffBySubject
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 17
 getBatchAssignedStaffs
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 15
 getBatchAssignedStaffExcludeTutors
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 getBatchTutors
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 17
 createTutors
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 18
 deleteTutors
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 13
 getStaffDetailsById
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 17
 getStaffDetailsByIdForApi
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 54
 getAllBasicDetailsOfStaffsByStatus
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 27
 isBatchMentor
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 19
 createNormalisePrivilegeForTutor
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 deleteNormalisePrivilegeForTutor
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 getNormalisePrivilegeTutor
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 14
 getFacultyList
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 24
 isStaffAssignedBatch
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 19
 assignFacultyForSubject
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 33
 unassignFacultyFromSubject
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 getEvaluationStudentSuggestion
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 14
 getStaffDetailsBySbsID
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 getsbsIDsBystaffID
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 getSubjectHandlingStaffs
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 19
 getEvaluationTypeBySbsId
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 16
 getEvaluationQuestions
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 getEvaluationFaculties
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 26
 getEvaluationQuestionAnswers
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 getEvalStudentAnswer
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 13
 getEvalStudentAnswerCount
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 27
 getStaffLoginDetails
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 18
 isGroupTutor
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 15
 createStaffEvalGrade
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 14
 updateStaffEvalGrade
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 15
 getStaffEvalGrade
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 getNumberOfLeavesTakenByStaffsBetweenTwoDate
0.00% covered (danger)
0.00%
0 / 1
110.00
0.00% covered (danger)
0.00%
0 / 32
 createStaffDelAttendancePreference
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 deleteStaffDelAttendancePreference
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 isStaffDelAttandanceBatch
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 13
 getEvaluationType
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 28
 getEvaluationFacultiesByDept
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 26
 addSubjectCountAndStudentCountToEvaluationFacultiesByDeptResponse
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 15
 getEvaluationTypeById
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 createAddMarksPrivilege
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 14
 deleteAddMarksPrivilege
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 getGrievances
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 27
 getGrievaneAssignedIdToStaff
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 isActionTakenForGrievance
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 12
 getStaffSbsIdBySubject
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 getStaffSubjectAllocation
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 13
 updateAddMarksPrivilege
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 26
 getStaffHourDetails
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 14
 getStaffAttendanceMarkedDetails
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 14
 addStaffWorkLog
0.00% covered (danger)
0.00%
0 / 1
90.00
0.00% covered (danger)
0.00%
0 / 29
 updateStaffWorkLog
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 17
 updateStaffWorkLogByDay
0.00% covered (danger)
0.00%
0 / 1
210.00
0.00% covered (danger)
0.00%
0 / 54
 removeStaffWorkLog
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 getStaffWorkLogByDate
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 13
 rejectStaffWorkLogByDate
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 getRejectedStaffWorkLogByDate
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 deleteStaffWorkLogByDate
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 13
 getStaffWorkLogByStaff
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 15
 isStaffWorkLogDateValid
0.00% covered (danger)
0.00%
0 / 1
182.00
0.00% covered (danger)
0.00%
0 / 61
 getDailyWorkLogApprovalListByDate
0.00% covered (danger)
0.00%
0 / 1
90.00
0.00% covered (danger)
0.00%
0 / 44
 getDailyWorkLogApprovalListByDept
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 24
 verifyWorkLogByStaff
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 20
 verifyWorkLogByDate
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 17
 getWorkLogNotSubmittedStaffs
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 16
 getWorkLogNotSubmittedStaffsByDate
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 239
 getWorkLogSubmittedStaffsByDate
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 66
 getWorkLogSubmittedByStaffAndByDate
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 15
 getWorkLogNotSubmittedByStaffAndByDate
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 15
 isTutor
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 15
 getStaffAssignedPreviousBatches
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 getStaffAssignedPreviousSemByBatchId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 getStaffAssignedPreviousSubjects
0.00% covered (danger)
0.00%
0 / 1
90.00
0.00% covered (danger)
0.00%
0 / 63
 getStaffAssignedPreviousDepartments
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 getStaffDetailsBySubjectId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 getWorkLogEditPreference
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 27
 addWorkLogEditPreference
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 deleteWorkLogEditPreference
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 canStaffEditWorkLogPreference
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 14
 searchUnMarkedFaculties
0.00% covered (danger)
0.00%
0 / 1
380.00
0.00% covered (danger)
0.00%
0 / 135
 isFacultyEvalStudentSuggestionMandatory
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 13
 upsertStaffProfileInfo
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 19
 deleteStaffProfileInfo
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 getStaffProfileSectionInfoByStaffId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 getStaffProfileInfoBySectionId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 getStaffPublicProfileDetails
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 getStaffPublicProfileViewDetails
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 30
 searchStaffByStaffName
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 getStaffIdByMailId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 updateStaffPassword
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 getStaffDetailsByDeptId
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 17
 getTutorDetailsByStaffId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 getStaffsDetailsForHourSwap
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 23
 createStaffMonthlyReport
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 createStaffMonthlyRepParticulars
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 13
 updateStaffMonthlyReport
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 deleteStaffMonthlyRepParticularsByRepId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 createStaffMonthlyReportDetails
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 getStaffMonReportsBySbsId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 getStaffMonthlyReportDetailsByRepId
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 13
 getStaffMonthlyReportByReportId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 deleteStaffMonthlyReportDetails
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 deleteStaffMonthlyReport
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 getAllMonthlyRepOfAStaff
0.00% covered (danger)
0.00%
0 / 1
110.00
0.00% covered (danger)
0.00%
0 / 45
 getStaffMonthlyReportByReportIds
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 getStaffDetailsAssignedToPseudoSub
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 createQuickReportPrivilegeToStaff
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 14
 deleteQuickReportPrivilegeToStaff
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 getQuickReportAuthorisationByStaffId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 getStaffDetailsFromSbsRelation
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 57
 getStaffDetailsByDeptIdAndName
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 getPrincipalDetails
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 getErpAdminDetails
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 getHodDetailsByDeptID
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 searchStaffDetails
0.00% covered (danger)
0.00%
0 / 1
240.00
0.00% covered (danger)
0.00%
0 / 69
 deleteStaffAchievementDocs
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 getStaffDetailsByAccount
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 15
 ValidateDutyLeavePrivilegesObject
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 15
 getAllDutyLeavePrivilegeOfStaff
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 13
 grantDutyLeavePrivileges
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 13
 getDutyLeavePrivileges
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 20
 removeDutyLeavePrivileges
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 12
 getStaffDetailsWithPhDGuideShip
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 getStaffDesignationByStaffId
0.00% covered (danger)
0.00%
0 / 1
342.00
0.00% covered (danger)
0.00%
0 / 61
 isStaffAssignedToPseudoSub
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 13
 isStaffAssignedToPseudoSubBySBS
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 15
 getAssignedStaffByDepartment
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 18
 insertStaffQualificationDetails
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 15
 getStaffQualificationDetailsByStaffId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 deleteStaffQualification
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 getLectureTypes
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 checkStaffHasNaacReportEntryPermission
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 checkStaffHasExatAccessPermission
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 hasCentrAttendPrivilege
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 12
 getFacultyAttendanceShiftDetails
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 28
 saveFacultyAttendance
0.00% covered (danger)
0.00%
0 / 1
650.00
0.00% covered (danger)
0.00%
0 / 90
 pushSaveBulkFacultyAttendanceToTaskQueue
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 24
 saveBulkFacultyAttendance
0.00% covered (danger)
0.00%
0 / 1
90.00
0.00% covered (danger)
0.00%
0 / 57
 getStaffByDepartments
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 18
 getStaffDetailsByDepartments
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 20
 getStaffDetailsByDepartment
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 20
 createUpdateHodNotesCheck
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 21
 getAllStaffWithAuthPermissionId
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 14
 verifyStaffAccountAndFetchDetails
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 22
 getStaffDetailsByBatchID
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 23
 getQuickReportAuthorisationByStaffIdAndReportName
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 16
 getStaffPhoneById
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 15
 getStaffDetailsByIdForFormways
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 16
 getAllFacultiesForFormways
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 28
 getFacultiesForAttendanceExchange
0.00% covered (danger)
0.00%
0 / 1
90.00
0.00% covered (danger)
0.00%
0 / 29
 getStaffListBySubjectID
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 18
 getMonthlyReportSubmittedStaffsByBatchID
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 27
 getNotConformedStaffList
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 63
 getNotConformedStaffListOfSubBatches
0.00% covered (danger)
0.00%
0 / 1
72.00
0.00% covered (danger)
0.00%
0 / 68
 getNotConformedSubBatchList
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 35
 getCountOfWorkLogType
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 getTotalWorkLengthOfWorkLogType
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 14
 getAllStaffQualification
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 8
 updateStaffProfile
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 17
 getExamControllerDetails
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 isHOD
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 13
 isFacultyIsERPAdmin
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 13
 isFacultyIsPrincipal
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 13
 isFacultyIsPrincipalOrERPAdmin
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 13
 isFacultyIsHODOrPrincipalOrERPAdmin
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 23
 getStaffHodPrivelegesByBatch
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 21
 getAllStaffMailIdByRequest
0.00% covered (danger)
0.00%
0 / 1
462.00
0.00% covered (danger)
0.00%
0 / 37
 createEmailLog
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 14
 getEmailLogsByRequest
0.00% covered (danger)
0.00%
0 / 1
110.00
0.00% covered (danger)
0.00%
0 / 20
 approveSubjectProposedPlan
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 19
 approveAllSubjectProposedPlan
0.00% covered (danger)
0.00%
0 / 1
182.00
0.00% covered (danger)
0.00%
0 / 38
 getAllFacultiesAndDetails
0.00% covered (danger)
0.00%
0 / 1
462.00
0.00% covered (danger)
0.00%
0 / 57
 getStaffRole
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 4
 getAllSubjectsAndStaffDetails
0.00% covered (danger)
0.00%
0 / 1
1056.00
0.00% covered (danger)
0.00%
0 / 85
 getSubjectPlanDetails
0.00% covered (danger)
0.00%
0 / 1
702.00
0.00% covered (danger)
0.00%
0 / 111
 getSubjectCoursePlanDetails
0.00% covered (danger)
0.00%
0 / 1
600.00
0.00% covered (danger)
0.00%
0 / 107
 getStaffWorkingBatches
0.00% covered (danger)
0.00%
0 / 1
272.00
0.00% covered (danger)
0.00%
0 / 62
 approveSubjectProposedPlanByPrinciple
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 11
 approveAllSubjectProposedPlanByPrinciple
0.00% covered (danger)
0.00%
0 / 1
182.00
0.00% covered (danger)
0.00%
0 / 36
 getStaffDepartmentDetails
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 15
 getConsolidateStaffWorkingHours
0.00% covered (danger)
0.00%
0 / 1
72.00
0.00% covered (danger)
0.00%
0 / 20
 getStaffAchievementsByStaffId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 8
 checkInstanceIsCorrect
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 23
 staffIsOrWasTutor
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 14
 getStaffSbsBySubject
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 17
 getAllStaffsWithPreviousHistoryOfaSubject
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 60
 examMarkExternalStaffByExam
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 16
 assignExamValuationFaculty
0.00% covered (danger)
0.00%
0 / 1
182.00
0.00% covered (danger)
0.00%
0 / 51
 getStaffByStaffIds
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 14
 assignStudentsToExamValuationStaffs
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 29
 getExamsAssignedForValuationByStaff
0.00% covered (danger)
0.00%
0 / 1
210.00
0.00% covered (danger)
0.00%
0 / 67
 getStudentsForExamValuationByStaff
0.00% covered (danger)
0.00%
0 / 1
132.00
0.00% covered (danger)
0.00%
0 / 61
 getBatchExamValuationDates
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 19
 getHodDetailsByBatchId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 23
 getHodListByBatchId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 24
 getAttendanceMarkedStaffDetails
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 20
 getCourseFileStaffDetails
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 30
 getStaffListBySubject
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 14
 getCourseFileObjectives
0.00% covered (danger)
0.00%
0 / 1
182.00
0.00% covered (danger)
0.00%
0 / 46
 createOrUpdateCourseFileObjectives
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 16
 updateCourseFileObjectives
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 11
 createCourseFileObjectives
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 8
 deleteCourseFileObjectives
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 12
 createCourseObjectiveResourses
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 7
 deleteCourseFileObjectivesResourses
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 16
 getStaffListBySubjectRequest
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 21
 getSubjectExamValuationDates
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 22
 getStaffDetailsByBatchDept
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 37
 getExamRegAssignedForValuationByStaff
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 29
 getAllBatchTutor
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 27
 getAllExamControllerDetails
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 getExamValuationStudentMarkEntryStatus
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 25
 getStudentAssignedStaffByExam
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 19
 getExamRegistrationsByValuationDate
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 22
 checkExamControllerTechnicalSupportStaff
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 getQuestionPaperBankStaffByBatchSem
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 26
 getActualSubjectPlanDetails
0.00% covered (danger)
0.00%
0 / 1
552.00
0.00% covered (danger)
0.00%
0 / 93
 getActualSubjectCoverageDetails
0.00% covered (danger)
0.00%
0 / 1
462.00
0.00% covered (danger)
0.00%
0 / 89
 getQuestionBankPoolStaffByBatchSem
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 25
 copyQuestionsFromStaff
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 25
 unassignFacultyFromSbs
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 17
 getSbsId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 14
 getStaffDetailsWithPhDGuideShipForDataImport
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 isStaffGroupTutor
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 23
 checkIfStaffAccountExist
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 25
 getQuestionPaperModulesByRequest
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 36
 getQuestionPaperBankByBatchSem
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 22
 getStaffListByRequest
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 17
 isExternalExaminer
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 19
 getHodListBasedOnRequest
0.00% covered (danger)
0.00%
0 / 1
90.00
0.00% covered (danger)
0.00%
0 / 29
 getPrincipalListBasedOnRequest
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 19
 getSbsStaffDetails
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 34
 getAllStaffs
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 14
 isStaffAssignedToValuation
0.00% covered (danger)
0.00%
0 / 1
272.00
0.00% covered (danger)
0.00%
0 / 48
 autoAssignStudentsToExamValuationStaffs
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 28
 getAssignStudentsToExamValuationStaffDates
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 27
 getDigitalValuationAssignedStaffs
0.00% covered (danger)
0.00%
0 / 1
110.00
0.00% covered (danger)
0.00%
0 / 37
 getStaffListBySubjectDepartment
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 16
 getStaffAssignedForExamsValuation
0.00% covered (danger)
0.00%
0 / 1
90.00
0.00% covered (danger)
0.00%
0 / 51
 getValuatedStaffDetailsByExamRegRequest
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 25
 getStaffDetailsByUniqueCode
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 13
 getConsolidateStaffWorkingHoursForStaffWorkingHourReport
0.00% covered (danger)
0.00%
0 / 1
110.00
0.00% covered (danger)
0.00%
0 / 39
 getStaffDetailsForApi
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 getClassTutorDetails
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 18
 teachingPlanUploadStatusReport
0.00% covered (danger)
0.00%
0 / 1
420.00
0.00% covered (danger)
0.00%
0 / 119
 syallabusCoverageReport
0.00% covered (danger)
0.00%
0 / 1
650.00
0.00% covered (danger)
0.00%
0 / 183
 unmarkedAttendanceDetails
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 78
 clusterWiseStudentAttendance
0.00% covered (danger)
0.00%
0 / 1
72.00
0.00% covered (danger)
0.00%
0 / 158
 getBackgroundImage
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 21
 getStaffStudentsForDigitalValuation
0.00% covered (danger)
0.00%
0 / 1
72.00
0.00% covered (danger)
0.00%
0 / 31
 getStaffDetailsByStaffCode
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 getAllNonResignedStaff
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 8
 getAllEscalationLeaveStaffs
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 17
 addEscalationLeaveStaffs
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 49
 uniassignFacultyFromEscalation
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 updateTimeOfLeaveEscalation
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 35
 getStaffDetailsByStaffAccount
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 CheckForEscalationMenu
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 10
 getHodPrivilegesDepartmentsByStaff
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 21
 getBatchesByStaffId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 16
 getStaffProfilePic
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 16
 removeStaffProfilePic
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 11
 getstaffAttendance
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 30
 updatestaffAttendanceByAdmin
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 21
 getAllDesignations
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 8
 getDesignationByDesignationID
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 33
<?php
namespace com\linways\core\ams\professional\service;
use stdClass;
use com\linways\base\dto\MySqlResult;
use Respect\Validation\Validator as v;
use com\linways\core\ams\professional\dto\Staff;
use Respect\Validation\Exceptions\DateException;
use com\linways\core\ams\professional\dto\Subject;
use com\linways\core\ams\professional\logging\Events;
use com\linways\core\ams\professional\util\CommonUtil;
use com\linways\core\ams\professional\dto\AMSConstants;
use com\linways\core\ams\professional\constant\ExamType;
use com\linways\core\ams\professional\constant\UserType;
use com\linways\core\ams\professional\logging\AMSLogger;
use com\linways\core\ams\professional\queue\AMSTaskQueue;
use com\linways\core\ams\professional\dto\StaffAttendance;
use com\linways\core\ams\professional\dto\StaffEvaluation;
use com\linways\core\ams\professional\dto\StaffProfileInfo;
use com\linways\core\ams\professional\constant\HRLeaveTypes;
use com\linways\core\ams\professional\dto\SettingsConstents;
use com\linways\core\ams\professional\dto\StaffDailyWorkLog;
use com\linways\core\ams\professional\dto\StaffEvalSettings;
use com\linways\core\ams\professional\service\CommonService;
use com\linways\core\ams\professional\dto\StaffMonthlyReport;
use com\linways\core\ams\professional\request\GetStaffRequest;
use com\linways\core\ams\professional\service\ResourceService;
use com\linways\core\ams\professional\service\SubBatchService;
use com\linways\core\ams\professional\service\BioMetricService;
use com\linways\core\ams\professional\dto\StaffDeleteAttendance;
use com\linways\core\ams\professional\dto\WorkLogEditPreference;
use com\linways\core\ams\professional\mapper\StaffServiceMapper;
use com\linways\core\ams\professional\request\StaffLoginRequest;
use com\linways\core\ams\professional\response\GetStaffResponse;
use com\linways\core\ams\professional\service\PermissionService;
use com\linways\core\ams\professional\constant\SettingsConstants;
use com\linways\core\ams\professional\service\SubjectPlanService;
use com\linways\core\ams\professional\response\SearchStaffResponse;
use com\linways\core\ams\professional\dto\StaffMonthlyReportDetails;
use com\linways\core\ams\professional\request\RemoveResourceRequest;
use com\linways\core\ams\professional\request\GetPreSignedUrlRequest;
use com\linways\core\ams\professional\exception\ProfessionalException;
use com\linways\core\ams\professional\request\WorkLogPreferenceRequest;
use com\linways\core\ams\professional\request\api\GetAllFacultiesRequest;
use com\linways\core\ams\professional\request\WorkLogApprovalListRequest;
use com\linways\core\ams\professional\request\WorkLogStaffDetailsRequest;
use com\linways\core\ams\professional\response\WorkLogPreferenceResponse;
use com\linways\core\ams\professional\request\WorkLogStaffDetailsResponse;
use com\linways\core\ams\professional\response\SearchUnMarkedStaffResponse;
use com\linways\core\ams\professional\response\WorkLogApprovalListResponse;
use com\linways\core\ams\professional\dto\biometric\BiometricAttendanceUploadRequest;
use com\linways\core\ams\professional\constant\biometric\BiometricAttendanceUploadRequestType;
use com\linways\core\ams\professional\constant\biometric\BiometricAttendanceUploadRequestStatus;
use com\linways\core\ams\professional\service\DepartmentService;
use com\linways\core\ams\professional\util\S3Utils;
class StaffService extends BaseService
{
    // /Condition 1 - Presence of a static member variable
    private static $_instance = null;
    private $mapper = [];
    private $logger;
    // /Condition 2 - Locked down the constructor
    private function __construct()
    {
        $this->mapper = StaffServiceMapper::getInstance()->getMapper();
        $this->logger = AMSLogger::getLogger();
    }
    // 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;
    }
    /**
     * get staff details
     *
     * @param Object $staffRequest
     * @return $staffDetails
     * @throws ProfessionalException
     */
    public function getAllFaculties($staffRequest)
    {
        $staffDetails = [];
        $staffRequest->deptId = $this->realEscapeString($staffRequest->deptId);
        $staffRequest->batchId = $this->realEscapeString($staffRequest->batchId);
        $staffRequest->subbatchId = $this->realEscapeString($staffRequest->subbatchId);
        if ($staffRequest) {
            if (!$staffRequest->deptId && !$staffRequest->batchId && !$staffRequest->subbatchId) {
                $sqlStaff = "SELECT distinct staffID AS id, staffName AS name,deptID as deptId FROM staffaccounts WHERE isResigned=0";
            } else if ($staffRequest->deptId && !$staffRequest->batchId && !$staffRequest->subbatchId) {
                $sqlStaff = "SELECT distinct staffID as id, staffName as name FROM staffaccounts WHERE isResigned=0 AND deptID IN ($staffRequest->deptId)";
                // "IN" is used when multiple deptId is given as $staffRequest->deptId
            } else if ($staffRequest->deptId && $staffRequest->batchId && !$staffRequest->subbatchId) {
                $sqlStaff = "SELECT distinct st.staffID as id, st.staffName as name FROM staffaccounts st INNER JOIN sbs_relation sr ON st.staffID = sr.staffID INNER JOIN batches b ON b.batchID = sr.batchID AND b.semID = sr.semID  WHERE st.isResigned=0 AND st.deptID=$staffRequest->deptId AND sr.batchID = $staffRequest->batchId";
            } else if ($staffRequest->deptId && $staffRequest->batchId && $staffRequest->subbatchId) {
                $sqlStaff = "SELECT distinct st.staffID as id, st.staffName as name FROM staffaccounts st INNER JOIN sbs_relation sr ON st.staffID = sr.staffID INNER JOIN subbatch_sbs ss ON ss.sbsID=sr.sbsID WHERE st.isResigned=0 AND st.deptID=$staffRequest->deptId AND ss.subbatchID=$staffRequest->subbatchId";
            }
            try {
                $staffDetails = $this->executeQueryForList($sqlStaff);
            } catch (\Exception $e) {
                throw new ProfessionalException ($e->getCode(), $e->getMessage());
            }
        }
        return $staffDetails;
    }
    /**
     *
     * @param GetAllFacultiesRequest $request
     * @return array|object|$objectList[]
     * @throws ProfessionalException
     * @author gadheyan
     */
    public function getAllFacultiesForApi(GetAllFacultiesRequest $request)
    {
        $staffs = [];
        $request = $this->realEscapeObject($request);
        $sql = "SELECT 
                s.staffID AS id, s.staffName AS name,  s.staffAccount as loginId, s.staffCode as code, s.isResigned AS staffResigned,    lt.typeName as lectureTypeName, d.deptName AS departmentName, vs.name AS schoolName,s.salutation
                FROM
                staffaccounts s 
                INNER JOIN department d ON
                d.deptID = s.deptID
                LEFT JOIN lectureTypes lt 
                on s.lectureType = lt.id 
                LEFT JOIN v4_school vs ON
                vs.id = d.school_id
                WHERE 1=1 ";
        if ($request) {
            if ($request->id) {
                $sql .= " AND s.staffID = $request->id";
            } else if (!empty($request->ids)) {
                $sql .= " AND s.staffID IN ('" . implode("','", $request->ids) . "')";
            }
            if ($request->deptId) {
                $sql .= " AND s.deptID = $request->deptId";
            }
            if ($request->staffLock) {
                $sql .= " AND s.staffLock = $request->staffLock";
            }
            if($request->isResigned === "1" || $request->isResigned === "0") {
                $sql .= " AND s.isResigned = '$request->isResigned'";
            }
        }
        $sql .= " ORDER BY s.isResigned ASC, -s.list_order DESC,s.staffID ASC";
        try {
            $staffs = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffs;
    }
    /**
     * @param $deptID
     * @param string $staffName
     * @param string $sortBy
     * @param string $sortOrder
     * @return Object|null
     * @throws ProfessionalException
     * @author jithinvijayan
     */
    function getStaffByDepartment($deptID, $staffName = "", $sortBy = 'staffName', $sortOrder = 'ASC')
    {
        $stafflist = null;
        $criteria = null;
        $criteria1 = "";
        $deptID = $this->realEscapeString($deptID);
        $staffName = $this->realEscapeString($staffName);
        $sql = "select staffID,staffName,staffPhone from staffaccounts where deptID = '$deptID' and isResigned = 0";
        if ($deptID == null) {
            throw new ProfessionalException(ProfessionalException::DEPARTMENT_ID_NOT_DEFINED, "DEPARTMENT_ID_NOT_DEFINED");
        }
        if ($staffName) {
            $criteria1 .= " AND sa.staffName like '%$staffName%'";
            $criteria .= " AND sat.staffName like '%$staffName%'";
            $sql = "SELECT DISTINCT sa.staffID ,sa.staffName FROM sbs_relation sr INNER JOIN staffaccounts sa ON sr.staffID = sa.staffID WHERE sr.batchID IN (SELECT batchID FROM batches WHERE deptID = '$deptID') $criteria1  UNION select sat.staffID ,sat.staffName FROM staffaccounts sat WHERE sat.deptID='$deptID$criteria ";
        }
        $criteria = " ORDER BY $sortBy $sortOrder";
        $sql .= $criteria;
        try {
            $stafflist = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $stafflist;
    }
    /**
     *
     * @param array $staffIdList
     * @return $staffDetails
     * @throws ProfessionalException
     */
    public function getStaffByIds($staffIdList)
    {
        $staffDetails = NULL;
        $staffIds = implode(',', $staffIdList);
        $staffIds = $this->realEscapeString($staffIds);
        $sql = "SELECT staffID AS id, staffName AS name, deptID  FROM staffaccounts  WHERE staffID IN ($staffIds)";
        try {
            $staffDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /**
     * Get staff name by staffId
     *
     * @param int $staffId
     * @return $staffName
     * @throws ProfessionalException
     */
    public function getStaffNameById($staffId)
    {
        $staffName = NULL;
        $staffId = $this->realEscapeString($staffId);
        $sql = "SELECT staffName AS name  FROM staffaccounts  WHERE staffID = $staffId";
        try {
            $staffName = $this->executeQueryForObject($sql)->name;
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffName;
    }
    /**
     * get staff details by subject
     *
     * @param int $subjectId
     * @param int $batchId
     * @param int $semId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffBySubject($subjectId, $batchId, $semId, $subbatchID)
    {
        $batchId = $this->realEscapeString($batchId);
        $semId = $this->realEscapeString($semId);
        $subjectId = $this->realEscapeString($subjectId);
        $subbatchID = $this->realEscapeString($subbatchID);
        $subbatchCond = "";
        if ($subbatchID) {
            $subbatchCond = " and subbatchID = $subbatchID";
        }
        $sql = "SELECT distinct sa.staffID, sa.staffCode, sa.staffName, sr.sbsID from staffaccounts sa inner join sbs_relation sr on sa.staffID = sr.staffID left join subbatch_sbs ss on sr.sbsID = ss.sbsID where sr.subjectID=$subjectId AND sr.batchID=$batchId AND sr.semID=$semId  $subbatchCond ";
        try {
            $staffDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /**
     * get batch assigned staffs using batchid and semid
     *
     * @param int $batchId
     * @param int $semId
     * @return $staffDetails
     * @throws ProfessionalException
     */
    public function getBatchAssignedStaffs($batchId, $semId)
    {
        $staffDetails = NULL;
        $batchId = $this->realEscapeString($batchId);
        $semId = $this->realEscapeString($semId);
        $sql = "SELECT  DISTINCT t1.staffID, t2.staffName FROM sbs_relation t1, staffaccounts t2  WHERE t2.staffID=t1.staffID AND t1.batchID=$batchId";
        if (!empty($semId)) {
            $sql .= " AND t1.semID=$semId ";
        }
        try {
            $staffDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /**
     * get batch assigned staffs using batchid and semid
     *
     * @param int $batchId
     * @param int $semId
     * @return $staffDetails
     * @throws ProfessionalException
     */
    public function getBatchAssignedStaffExcludeTutors($batchId, $semId)
    {
        $staffDetails = NULL;
        $batchId = $this->realEscapeString($batchId);
        $semId = $this->realEscapeString($semId);
        $sql = "SELECT  DISTINCT t1.staffID, t2.staffName FROM sbs_relation t1, staffaccounts t2  WHERE t2.staffID=t1.staffID AND t1.batchID=$batchId AND t1.semID=$semId AND t1.staffID NOT IN(select t2.staffID from batch_tutor t1, staffaccounts t2, department t3 where t1.batchID=$batchId and t1.semID=$semId and t1.staffID=t2.staffID and t2.deptID=t3.deptID)";
        try {
            $staffDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /**
     * get batch tutor details by batchId and semId
     *
     * @param int $batchId
     * @param int $semId
     * @return object|array|$objectList[]
     * @throws ProfessionalException
     */
    public function getBatchTutors($batchId, $semId,$studentId = null)
    {
        $staffDetails = NULL;
        $batchId = $this->realEscapeString($batchId);
        $semId = $this->realEscapeString($semId);
        if(!empty($studentId)){
            $sql = "select sta.staffID, sta.staffName, dept.deptName, sta.staffPhone,bt.tutorID from studentaccount stu INNER JOIN batches b on b.batchID = stu.batchID INNER JOIN batch_tutor bt ON bt.batchID = b.batchID AND bt.semID = b.semID INNER JOIN staffaccounts sta ON sta.staffID = bt.staffID INNER JOIN department dept on dept.deptID = sta.deptID where stu.studentID = $studentId";
        }
        else{
            $sql = "select t2.staffID, t2.staffName, t3.deptName, t2.staffPhone,t1.tutorID  from batch_tutor t1, staffaccounts t2, department t3 where t1.batchID=$batchId and t1.semID=$semId and t1.staffID=t2.staffID and t2.deptID=t3.deptID";
        }
        try {
            $staffDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /**
     * insert into batch_tutor
     *
     * @param int $batchId
     * @param int $semId
     * @param $staffIds
     * @return MySqlResult|null
     * @throws ProfessionalException
     */
    public function createTutors($batchId, $semId, $staffIds)
    {
        $batchId = $this->realEscapeString($batchId);
        $semId = $this->realEscapeString($semId);
        $staffIds = $this->realEscapeArray($staffIds);
        $sql = "INSERT IGNORE INTO batch_tutor(staffID,semID,batchID) VALUES ";
        $values = [];
        if ($staffIds) {
            foreach ($staffIds as $staffID) {
                $values [] = "($staffID,$semId,$batchId)";
            }
        }
        $sql .= implode(',', $values);
        try {
            return $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * un assign tutor from batch
     *
     * @param int $batchId
     * @param int $semId
     * @param
     *            integer array $staffIds
     * @return MySqlResult
     * @throws ProfessionalException
     */
    public function deleteTutors($batchId, $semId, $staffIds)
    {
        $batchId = $this->realEscapeString($batchId);
        $semId = $this->realEscapeString($semId);
        $staffIds = $this->realEscapeArray($staffIds);
        if ($staffIds) {
            $sql = "DELETE FROM batch_tutor WHERE batchID=$batchId AND semID=$semId AND staffID IN(" . implode(',', $staffIds) . ")";
        }
        try {
            return $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Returns staff details by id
     *
     * @param integer $staffId
     * @return object|array|$objectList[]
     * @throws ProfessionalException
     * @author Jithin
     */
    public function getStaffDetailsById($staffId)
    {
        $staffDetails = NULL;
        $staffId = $this->realEscapeString($staffId);
        $sql = "SELECT sa.*,d.deptID as deptId ,d.deptName,d.departmentDesc,hd.designationID as hrDesigId,
                hd.designationName as hrDesigName, hd.designationDesc as hrDesigDesc ,sd.id as staffDesigId,
                sd.name as staffDesigName, sd.description as staffDesigDesc, hs.sectionId, hs.sectionName,
                hs.sectionDesc FROM staffaccounts sa LEFT JOIN department d ON d.deptID = sa.deptID
                LEFT JOIN hr_designations hd ON hd.designationID = sa.designationID LEFT JOIN staff_designation sd
                ON sd.id = sa.academicDesignationID LEFT JOIN hr_sections hs ON hs.sectionID=sa.sectionID
                WHERE sa.staffID='$staffId'";
        try {
            $staffDetails = $this->executeQueryForList($sql, $this->mapper [StaffServiceMapper::GET_STAFF_DETAILS_BY_ID]);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /**
     *
     * @param unknown $id
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     * @author gadheyan
     */
    public function getStaffDetailsByIdForApi($id)
    {
        $staffDetails = NULL;
        $id = $this->realEscapeString($id);
        $sql = "SELECT 
    sta.staffID AS id,
    sta.staffName AS name,
    staffAccount AS loginId,
    sta.staffEmail AS email,
    sta.staffGender AS gender,
    sta.staffBirthday AS dob,
    sta.staffAddress AS address,
    sta.staffPhone AS phone,
    sta.staffCreateDate AS creationDate,
    sta.deptID AS departmentId,
    dpt.deptName AS departmentName,
    dpt.departmentDesc AS departmentDescription,
    sta.isHOD AS isHOD,
    sta.isPrincipal,
    sta.qualificationID AS qualificationId,
    sta.specializationID AS specializationId,
    sta.yearOfPassing,
    sta.instituteName,
    sta.staffCode,
    sta.isFaculty,
    isResigned,
    sta.other_designation AS otherDesignation,
    sta.dateOfJoining,
    sta.designationID AS designationId,
    sta.sectionID AS sectionId,
    sta.academicDesignationID AS academicDesignationId,
    GROUP_CONCAT(sde.name) as academicDesignationName,
    GROUP_CONCAT(sde.description) as academicDesignationDescription,
    sta.bloodGroup,
    sta.aictCode,
    sta.panNumber,
    sta.rejoiningDate,
    sta.staffPassword,
    sta.fieldOfSpecialization ,
    lt.typeName as lectureTypeName,
    sta.salutation
FROM
    staffaccounts sta
        INNER JOIN
    department dpt ON dpt.deptID = sta.deptID AND sta.staffID = $id
    LEFT JOIN staff_designation sde ON FIND_IN_SET(sde.id,sta.academicDesignationID)
    left join lectureTypes lt on sta.lectureType = lt.id 
    GROUP BY sta.staffID;";
        try {
            $staffDetails = $this->executeQueryForObject($sql, FALSE, $this->mapper [StaffServiceMapper::GET_STAFF_DETAILS_BY_ID_FOR_API]);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /**
     * returns basic details like staff id,name, staff code from staff account based of staff status
     *
     * @param boolean $isResigned
     * @return [object]
     * @throws ProfessionalException
     * @author Jithin
     */
    public function getAllBasicDetailsOfStaffsByStatus($isResigned = NULL)
    {
        $staffDetails = [];
        $isResigned = $this->realEscapeString($isResigned);
        $sql = "SELECT sa.staffID AS staffId,
                       sa.staffName AS name,
                       sa.staffCode AS code,
                       sa.myImage,
                       sa.staffGender,
                       dp.deptName 
                       FROM staffaccounts sa 
                       INNER JOIN department dp ON dp.deptID=sa.deptID  
                       WHERE sa.staffID>0 ";
        if (!is_null($isResigned)) {
            $sql = $sql . "AND isResigned='$isResigned'";
        }
        try {
            $staffDetails = $this->executeQueryForList($sql);
            foreach ($staffDetails as  $staffDetail) {
                $profilePicture = $this->getStaffProfilePic($staffDetail->staffId);
                $imagePath = $profilePicture->docpath;
                $staffDetail->myImage = $imagePath;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /**
     *
     * Check for logged in user is a mentor
     *
     * @param $bid
     * @param $staffId
     * @param $semId not mandatory
     * @return true if mentor else false
     * @throws ProfessionalException
     */
    public function isBatchMentor($bid, $staffId, $semId = null)
    {
        $bid = $this->realEscapeString($bid);
        $staffId = $this->realEscapeString($staffId);
        $semId = $this->realEscapeString($semId);
        $semConditionSql = "";
        if ($semId) {
            $semConditionSql = "AND semID = $semId";
        }
        $sql = "SELECT count(tutorId) as count FROM batch_tutor WHERE batchID =$bid AND staffID= $staffId $semConditionSql";
        try {
            $count = $this->executeQueryForObject($sql)->count;
            if ($count) {
                return true;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return false;
    }
    /**
     * Set privilege for the tutor to define normalize rule for the batch
     *
     * @param int $batchId
     * @param int $deptId
     * @return MySqlResult
     * @throws ProfessionalException
     */
    public function createNormalisePrivilegeForTutor($batchId, $deptId)
    {
        $batchId = $this->realEscapeString($batchId);
        $deptId = $this->realEscapeString($deptId);
        $sql = "insert into normalize_tutor_privilege (batchId,deptId) values ($batchId,$deptId)";
        try {
            return $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Delete tutor privilege to define normalize rule for the batch
     *
     * @param int $batchId
     * @param int $deptId
     * @return MySqlResult
     * @throws ProfessionalException
     */
    public function deleteNormalisePrivilegeForTutor($batchId, $deptId)
    {
        $batchId = $this->realEscapeString($batchId);
        $deptId = $this->realEscapeString($deptId);
        $sql = "delete from normalize_tutor_privilege where batchId= $batchId and deptId=$deptId";
        try {
            return $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Checks if the tutor has the privilege
     * to define normalize rule for the batch
     *
     * @param int $batchId
     * @param int $deptId
     * @return boolean
     * @throws ProfessionalException
     */
    public function getNormalisePrivilegeTutor($batchId, $deptId)
    {
        $batchId = $this->realEscapeString($batchId);
        $deptId = $this->realEscapeString($deptId);
        $sql = "select batchId from normalize_tutor_privilege where batchId= $batchId and deptId=$deptId";
        try {
            $batch = $this->executeQueryForObject($sql);
            if ($batch != null) {
                return true;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return false;
    }
    /**
     * Get faculties assigned for a batch
     *
     * @param GetStaffRequest $staffRequest
     * @param int $allFaculty
     *            :
     *            set value to get details of all faculties
     *
     * @return \com\linways\core\ams\professional\response\GetStaffResponse
     * @throws ProfessionalException
     */
    public function getFacultyList($staffRequest, $allFaculty = 0)
    {
        $staffList = new GetStaffResponse ();
        $batchId = $this->realEscapeString($staffRequest->batchId);
        $deptId = $this->realEscapeString($staffRequest->deptId);
        $semId = $this->realEscapeString($staffRequest->semId);
        $startIndex = $this->realEscapeString($staffRequest->startIndex);
        $endIndex = $this->realEscapeString($staffRequest->endIndex);
        $staffName = $this->realEscapeString($staffRequest->staffName);
        if (!$allFaculty) {
            $sql = "select distinct  sa.staffID as id, sa.staffName as name from sbs_relation sr inner join staffaccounts sa on sa.staffID = sr.staffID where sr.batchID='$batchId' and sr.semID='$semId' and sa.staffName like '%$staffName%'";
        } else {
            $sql = "SELECT staffID as id, staffName as name FROM staffaccounts WHERE isResigned=0 and staffName like '%$staffName%' limit $startIndex,$endIndex ";
            $sql_count = "SELECT count(staffID) AS count FROM staffaccounts WHERE isResigned=0";
        }
        try {
            $staffList->staffs = $this->executeQueryForList($sql);
            if ($allFaculty) {
                $staffList->totalRecords = $this->executeQueryForObject($sql_count)->count;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffList;
    }
    /**
     * Returns true if a staff is assigned for the batch
     *
     * @param int $staffId
     * @param int $batchId
     * @param int $semId
     * @param int $subjetcId
     * @return boolean
     * @throws ProfessionalException
     */
    public function isStaffAssignedBatch($staffId, $batchId, $semId, $subjectId = null)
    {
        $batchId = $this->realEscapeString($batchId);
        $semId = $this->realEscapeString($semId);
        $staffId = $this->realEscapeString($staffId);
        $subjectId = $this->realEscapeString($subjectId);
        $sql = " select sr.staffID from  sbs_relation sr  where sr.staffID = $staffId and sr.batchID = $batchId and sr.semID = $semId and isPseudosubject=0";
        if ($subjectId) {
            $sql .= " and sr.subjectID = $subjectId";
        }
        try {
            $staffId = $this->executeQueryForObject($sql);
            if ($staffId) {
                return true;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return false;
    }
    /**
     * Assigns facullty to a subject
     *
     * @param int $batchId
     * @param int $semId
     * @param int $subjectId
     * @param int $staffId
     * @param $createdBy
     * @return array
     * @throws ProfessionalException
     */
    public function assignFacultyForSubject($batchId, $semId, $subjectId, $staffId, $createdBy)
    {
        $batchId = $this->realEscapeString($batchId);
        $semId = $this->realEscapeString($semId);
        $subjectId = $this->realEscapeString($subjectId);
        $createdBy = $this->realEscapeString($createdBy);
        if (is_array($staffId)) {
            $staffId = $this->realEscapeArray($staffId);
            foreach ($staffId as $staff) {
                $isAssigned = $this->isStaffAssignedBatch($staff, $batchId, $semId, $subjectId);
                if (!$isAssigned) {
                    $values[] = "(" . $staff . "," . $batchId . "," . $subjectId . "," . $semId . "," . $createdBy . ",UTC_TIMESTAMP()," . $createdBy . ",UTC_TIMESTAMP())";
                } else {
                    $alreadyAssignedStaffs[] = $staff;
                }
            }
            $value = implode(",", $values);
        } else {
            $staffId = $this->realEscapeString($staffId);
            $value = "(" . $staffId . "," . $batchId . "," . $subjectId . "," . $semId . "," . $createdBy . ",UTC_TIMESTAMP()," . $createdBy . ",UTC_TIMESTAMP())";
        }
        $sql = "INSERT INTO sbs_relation (staffID, batchID, subjectID, semID,createdBy,createdDate, updatedBy,updatedDate) 
                VALUES " . $value;
        try {
            if ($value) {
                $this->executeQuery($sql);
            }
            if (!empty($alreadyAssignedStaffs)) {
                return $alreadyAssignedStaffs;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Unassign faculty from the subject
     *
     * @param int $batchId
     * @param int $semId
     * @param int $staffId
     * @param int $subjectId
     * @return MySqlResult
     * @throws ProfessionalException
     */
    public function unassignFacultyFromSubject($batchId, $semId, $staffId, $subjectId)
    {
        $batchId = $this->realEscapeString($batchId);
        $semId = $this->realEscapeString($semId);
        $staffId = $this->realEscapeString($staffId);
        $subjectId = $this->realEscapeString($subjectId);
        $sql = "delete from sbs_relation where batchID = $batchId and semID = $semId and subjectID = $subjectId  and staffID = $staffId";
        try {
            return $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    public function getEvaluationStudentSuggestion($sbsId, $staffId, $batchId, $semId, $eval_typeId)
    {
        $batchId = $this->realEscapeString($batchId);
        $semId = $this->realEscapeString($semId);
        $eval_typeId = $this->realEscapeString($eval_typeId);
        $sbsId = $this->realEscapeString($sbsId);
        $staffId = $this->realEscapeString($staffId);
        $sql = "select commentID,comments,extra_sugg_question_no from staffeval_student_suggestions where sbsID=$sbsId and staffID=$staffId and batchID=$batchId and semID=$semId and eval_typeID=$eval_typeId";
        try {
            $comments = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $comments;
    }
    /**
     *
     * @param int $sbsID
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffDetailsBySbsID($sbsID)
    {
        $sbsID = $this->realEscapeString($sbsID);
        $sql = "SELECT staff.staffID AS id, staff.staffPhone AS phone, staff.staffName AS name, semID, subjectID,sbs.batchID FROM sbs_relation sbs, staffaccounts staff WHERE sbs.staffID = staff.staffID AND sbs.sbsID = \"" . $sbsID . "\"";
        try {
            $staffDetails = $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    public function getsbsIDsBystaffID($staffID)
    {
        $sql = "";
        $staffID = $this->realEscapeString($staffID);
        $sbsIds = [];
        $sql = "SELECT DISTINCT sr.sbsID FROM sbs_relation sr WHERE staffID=$staffID";
        try {
            $sbsIds = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $sbsIds;
    }
    /**
     * get subject handling staff details
     *
     * @param integer $subjectID
     * @param integer $batchID
     * @param integer $semID
     * @return $staffs
     * @throws ProfessionalException
     */
    public function getSubjectHandlingStaffs($subjectID, $batchID, $semID, $staffId = null)
    {
        $staffs = [];
        $batchID = $this->realEscapeString($batchID);
        $semID = $this->realEscapeString($semID);
        $subjectID = $this->realEscapeString($subjectID);
        $staffId = $this->realEscapeString($staffId);
        $condition = "";
        if($staffId){
            $condition = " AND sr.staffID = $staffId ";
        }
        $sql = "SELECT sr.sbsID, sa.staffID, sa.staffName FROM sbs_relation sr
        INNER JOIN staffaccounts sa ON sa.staffID=sr.staffID WHERE sr.subjectID=$subjectID AND sr.batchID=$batchID AND sr.semID=$semID $condition";
        try {
            $staffs = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffs;
    }
    public function getEvaluationTypeBySbsId($sbsID, $subjectCategories)
    {
        $evaluationType = [];
        $sbsID = $this->realEscapeString($sbsID);
        if ($subjectCategories) {
            $categories = implode("\", \"", $subjectCategories);
            $categories = "\"" . $categories . "\"";
            $subjectCondition = " AND subc.subjectCategory IN ($categories)";
        }
        $sql = "select ss.eval_typeID as id, st.eval_name as name from staffeval_stafflist ss INNER JOIN staffeval_type st ON st.eval_typeID= ss.eval_typeID INNER JOIN sbs_relation sbs ON sbs.sbsID = ss.sbsID INNER JOIN subjects sub ON sub.subjectID = sbs.subjectID LEFT JOIN subject_category subc ON subc.subjectcatID = sub.subjectcatID where ss.sbsID=$sbsID $subjectCondition";
        try {
            $evaluationType = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $evaluationType;
    }
    /**
     * get questions related to evaluation type
     *
     * @param integer $evalTypeID
     * @return $objectList $questions
     * @throws ProfessionalException
     */
    public function getEvaluationQuestions($evalTypeID)
    {
        $questions = [];
        $evalTypeID = $this->realEscapeString($evalTypeID);
        $sql = "SELECT t1.questionID, t2.question from staffeval_type_questions t1, staffeval_questions t2 where t1.questionID=t2.questionID and t1.eval_typeID=\"$evalTypeID\"  ORDER BY t1.question_order ASC";
        try {
            $questions = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $questions;
    }
    /**
     * get faculties that added to evaluation type
     *
     * @param integer $batchID
     * @param integer $semID
     * @param integer $evalTypeID
     * @return $objectList $evaluationFaculties
     */
    public function getEvaluationFaculties($batchID, $semID, $evalTypeID, $subjectCategories = null)
    {
        $batchID = $this->realEscapeString($batchID);
        $semID = $this->realEscapeString($semID);
        $evalTypeID = $this->realEscapeString($evalTypeID);
        // $subjectCategories = $this->realEscapeArray($subjectCategories);
        $evaluationFaculties = [];
        $cond = "";
        if ($sbsID) {
            $cond = "AND t1.sbsID=$sbsID";
        }
        if ($subjectCategories) {
            $categories = implode("\", \"", $subjectCategories);
            $categories = "\"" . $categories . "\"";
            $subjectCondition = " AND subc.subjectcatName IN ($categories)";
        }
        $sql = "SELECT t2.sbsID, t3.staffID, t3.staffName, t4.subjectName, t3.myImage, t4.subjectDesc, t3.staffCode, t5.evalStartDate,t5.evalEndDate from staffeval_stafflist t1, sbs_relation t2, staffaccounts t3, subjects t4 , subject_category subc,staffeval_type t5  WHERE t1.eval_typeID = \"$evalTypeID\" AND t1.batchID=\"$batchID\" AND t1.semID=\"$semID\" AND t1.sbsID = t2.sbsID AND t2.staffID = t3.staffID AND t4.subjectID = t2.subjectID AND subc.subjectcatID = t4.subjectcatID AND t1.eval_typeID = t5.eval_typeID $cond $subjectCondition";
        try {
            $evaluationFaculties = $this->executeQueryForList($sql);
            foreach ($evaluationFaculties as $faculty) {
                $studentCount = $this->getEvalStudentAnswerCount($batchID, $semID, $evalTypeID, $faculty->sbsID);
                $faculty->studentCount = $studentCount;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $evaluationFaculties;
    }
    /**
     * get answers related to evaluation questions
     *
     * @param integer $questID
     * @return $objectList $answers
     * @throws ProfessionalException
     */
    public function getEvaluationQuestionAnswers($questID)
    {
        $answers = [];
        $questID = $this->realEscapeString($questID);
        $sql = "select answerID, answer, point from staffeval_answers where questionID=\"$questID\"";
        try {
            $answers = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $answers;
    }
    /**
     * get students feedback answers related to evaluation type
     *
     * @param integer $sbsID
     * @param integer $evalTypeID
     * @param integer $ansID
     * @return $objectList $studentAnswers
     * @throws ProfessionalException
     */
    public function getEvalStudentAnswer($sbsID, $evalTypeID, $ansID)
    {
        $sbsID = $this->realEscapeString($sbsID);
        $evalTypeID = $this->realEscapeString($evalTypeID);
        $ansID = $this->realEscapeString($ansID);
        $studentAnswers = NULL;
        $sql = "select answer_count from staffeval_studentanswers where eval_typeID=\"$evalTypeID\" and sbsID=\"$sbsID\" and answerID=\"$ansID\"";
        try {
            $studentAnswers = $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $studentAnswers;
    }
    /**
     * get total students feedback answers related to evaluation type
     *
     * @param integer $sbsID
     * @param integer $evalTypeID
     * @param integer $ansID
     * @return $objectList $studentAnswers
     * @throws ProfessionalException
     */
    public function getEvalStudentAnswerCount($batchID, $semID, $evalTypeID, $sbsID)
    {
        $batchID = $this->realEscapeString($batchID);
        $semID = $this->realEscapeString($semID);
        $sbsID = $this->realEscapeString($sbsID);
        $evalTypeID = $this->realEscapeString($evalTypeID);
        $studentAnswersCount = NULL;
        $questionSql = "SELECT count(t1.questionID) as count from staffeval_type_questions t1, staffeval_questions t2 where t1.questionID=t2.questionID and t1.eval_typeID=\"$evalTypeID\"  ORDER BY t1.question_order asc";
        //$sql = "SELECT max(answer_count) as count from staffeval_studentanswers where batchID=\"$batchID\" and semID=\"$semID\" and eval_typeID=\"$evalTypeID\" and sbsID=\"$sbsID\"";
        $sql = "SELECT sum(answer_count) as answer_count from staffeval_studentanswers where batchID='$batchID' and semID='$semID' and eval_typeID='$evalTypeID' and sbsID='$sbsID' group by questionID;";
        try {
            $questioncount = $this->executeQueryForObject($questionSql)->count;
            //$anscount_persbsid = $this->executeQueryForObject($sql)->count;
            $anscount_persbsid = $this->executeQueryForList($sql);
            $ansCount = 0;
            foreach ($anscount_persbsid as $count) {
                if ($ansCount < $count) {
                    $ansCount = (int)$count->answer_count;
                }
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        if ($questioncount != 0) {
            //$studentAnswersCount = $anscount_persbsid / $questioncount;
            $studentAnswersCount = $ansCount;
        } else {
            $studentAnswersCount = 0;
        }
        return $studentAnswersCount;
    }
    /*
     * @param array $staffId
     * @throws ProfessionalException
     * @return $staffDetails
     */
    public function getStaffLoginDetails($staffId)
    {
        $staffDetails = NULL;
        $staffId = $this->realEscapeString($staffId);
        $sql = "SELECT sa.staffID as staffId,
        sa.staffName as staffName,
        sa.staffAccount,
        sa.staffPassword,
        sa.deptId,isHOD,sa.isPrincipal,isResigned,d.deptName,sa.staffLock
        FROM staffaccounts sa
        INNER JOIN department d on d.deptID = sa.deptID
        WHERE sa.staffID=$staffId";
        try {
            $staffDetails = $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /**
     * Check if the staff is group tutor
     *
     * @param int $batchId
     * @param int $semId
     * @param int $staffId
     * @return boolean
     * @throws ProfessionalException
     */
    public function isGroupTutor($batchId, $semId, $staffId)
    {
        $batchId = $this->realEscapeString($batchId);
        $semId = $this->realEscapeString($semId);
        $staffId = $this->realEscapeString($staffId);
        $sql = "SELECT count(staffID) as count FROM batch_tutor WHERE batchID = $batchId  AND staffID= $staffId and semID = $semId";
        try {
            $count = $this->executeQueryForObject($sql)->count;
            if ($count) {
                return true;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return false;
    }
    /**
     * To create settings for staff evaluation grade
     *
     * @param StaffEvalSettings $staffEval
     * @return MySqlResult
     * @throws ProfessionalException
     */
    public function createStaffEvalGrade($staffEval)
    {
        $staffEval = null;
        $name = $this->realEscapeString($staffEval->name);
        $startPercent = $this->realEscapeString($staffEval->startPercent);
        $endPercent = $this->realEscapeString($staffEval->endPercent);
        $grade = $this->realEscapeString($staffEval->grade);
        $createdBy = $this->realEscapeString($staffEval->createdBy);
        $sql = "insert into staff_evaluation_grade_config (name, startPercent, endPercent, grade, createdBy, createdDate) value (\"$name\",$startPercent$endPercent, \"$grade\", $createdBy, UTC_TIMESTAMP())";
        try {
            return $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * To update settings for staff evaluation grade
     *
     * @param StaffEvalSettings $staffEval
     * @return MySqlResult
     * @throws ProfessionalException
     */
    public function updateStaffEvalGrade($staffEval)
    {
        $staffEval = null;
        $id = $this->realEscapeString($staffEval->id);
        $name = $this->realEscapeString($staffEval->name);
        $startPercent = $this->realEscapeString($staffEval->startPercent);
        $endPercent = $this->realEscapeString($staffEval->endPercent);
        $grade = $this->realEscapeString($staffEval->grade);
        $updatedBy = $this->realEscapeString($staffEval->updatedBy);
        $sql = "update staff_evaluation_grade_config set name = \"$name\", startPercent = $startPercent, endPercent = $endPercent, grade = \"$grade\" , updatedBy = $updatedBy, updatedDate = UTC_TIMESTAMP() where id = $id";
        try {
            return $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Get staff evaluation grade settings
     *
     * @return object|array|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffEvalGrade()
    {
        $sql = "SELECT * FROM staff_evaluation_grade_config";
        try {
            $staffEvalGradeDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffEvalGradeDetails;
    }
    /**
     *
     * @param string $fromDate
     *            'from date' must be in the format of (YYYY-MM-DD)
     * @param string $toDate
     *            'to date' must be in the format of (YYYY-MM-DD)
     * @param string $leaveType
     * @param bool $isApproved
     *            default TRUE
     * @param integer $staffId
     * @return [Staff]
     * @throws ProfessionalException
     * @author Jithin
     *         returns number of leaves taken by each staff or a particular staff.
     */
    public function getNumberOfLeavesTakenByStaffsBetweenTwoDate($fromDate, $toDate, $leaveType, $isApproved = true, $staffId = NULL)
    {
        $result = [];
        $fromDate = $this->realEscapeString($fromDate);
        $toDate = $this->realEscapeString($toDate);
        $leaveType = $this->realEscapeString($leaveType);
        $isApproved = $this->realEscapeString($isApproved);
        $staffId = $this->realEscapeString($staffId);
        if (empty ($fromDate)) {
            throw new ProfessionalException (ProfessionalException::INVALID_FROM_DATE, "Invalid from date");
        }
        if (empty ($toDate)) {
            throw new ProfessionalException (ProfessionalException::INVALID_TO_DATE, "Invalid to date");
        }
        if (empty ($leaveType) || $leaveType != (HRLeaveTypes::LOP || HRLeaveTypes::CASUAL_LEAVE || HRLeaveTypes::DUTY_LEAVE || HRLeaveTypes::ML)) {
            throw new ProfessionalException (ProfessionalException::INVALID_LEAVE_TYPE, "Invalid leave type");
        }
        $query = "SELECT SUM((DATEDIFF(LEAST(hla.endDate, '$toDate'),GREATEST(hla.startDate, '$fromDate'))+1)*hla.noofleaves)
                  AS numberOfLOP, sa.staffID, sa.staffName, sa.staffCode FROM hr_leave_applications hla
                  INNER JOIN hr_leavetypes hlt ON hla.leaveID = hlt.leaveID INNER JOIN staffaccounts sa
                  ON hla.staffID=sa.staffID WHERE '$fromDate' <= hla.endDate AND '$toDate' >= hla.startDate
                  AND hla.approved= '$isApproved' AND hlt.leaveName='$leaveType'";
        if (!empty ($staffId)) {
            $query .= " AND sa.staffID = '$staffId'";
        }
        $query .= " GROUP BY hla.staffID ORDER BY hla.staffID ASC";
        try {
            $result = $this->executeQueryForList($query, $this->mapper [StaffServiceMapper::GET_NUMBER_OF_LOP_TAKEN_BY_STAFFS]);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $result;
    }
    /**
     * Add preference to delete attendance by faculty
     *
     * @param StaffDeleteAttendance $staffPreference
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function createStaffDelAttendancePreference($staffPreference)
    {
        $deptId = $this->realEscapeString($staffPreference->deptId);
        $batchId = $this->realEscapeString($staffPreference->batchId);
        $createdBy = $this->realEscapeString($staffPreference->createdBy);
        $sql = "insert into staff_delete_attendance_config (deptId, batchId, createdBy, createdDate) values ($deptId$batchId$createdBy, utc_timestamp())";
        try {
            return $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Add preference to delete attendance by faculty
     *
     * @param int $batchId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function deleteStaffDelAttendancePreference($batchId)
    {
        $batchId = $this->realEscapeString($batchId);
        $sql = "delete from staff_delete_attendance_config where batchId = $batchId";
        try {
            return $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Check whether staffs can delete attendance of the batch
     *
     * @param int $batchId
     * @return boolean
     * @throws ProfessionalException
     */
    public function isStaffDelAttandanceBatch($batchId)
    {
        $batchId = $this->realEscapeString($batchId);
        $sql = "select batchId from staff_delete_attendance_config where batchID = $batchId";
        try {
            $batchId = $this->executeQueryForObject($sql)->batchId;
            if ($batchId) {
                return true;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return false;
    }
    /**
     * Get evaluation types by department
     *
     * @param int $deptId
     * @param int $batchId
     * @param int $semId
     * @param bool $includeStaffWiseEval
     * @return object|array|$objectList[]
     * @throws ProfessionalException
     */
    public function getEvaluationType($deptId, $batchId = 0, $semId = 0, $includeStaffWiseEval = false)
    {
        $deptId = $this->realEscapeString($deptId);
        $batchId = $this->realEscapeString($batchId);
        $semId = $this->realEscapeString($semId);
        $deptString = "";
        $batchSting = "";
        $semString = "";
        if ($deptId) {
            $deptString = " deptID = $deptId";
        }
        if ($batchId) {
            $batchSting = " ss.batchID = $batchId";
        }
        if ($semId) {
            $semString = " and ss.semID =  $semId";
        }
        if ($includeStaffWiseEval) {
            $sql = "select distinct(st.eval_typeID) as id,eval_name as name from department dep left join staffaccounts sa on dep.deptID = sa.deptID inner join sbs_relation sr on sr.staffID = sa.staffID inner join batches ba on ba.batchID = sr.batchID inner join staffeval_studentanswers ss on ss.batchID = ba.batchID  inner join staffeval_type st on ss.eval_typeID = st.eval_typeID  where dep.deptID = $deptId ORDER BY st.eval_typeID DESC";
        } else {
            $sql = "select distinct(st.eval_typeID) as id,eval_name as name from staffeval_studentanswers ss left join staffeval_type st on ss.eval_typeID = st.eval_typeID left join  batches bat on ss.batchID = bat.batchID where $deptString $batchSting $semString ORDER BY st.eval_typeID DESC";
        }
        try {
            $evaluationDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $evaluationDetails;
    }
    /**
     * Get Faculty evaluation details by department
     *
     * @param int $deptId
     * @param int $evalTypeID
     * @param null $subjectCategories
     * @return void
     * @throws ProfessionalException
     */
    public function getEvaluationFacultiesByDept($deptId, $evalTypeID, $subjectCategories = null)
    {
        $deptId = $this->realEscapeString($deptId);
        $evalTypeID = $this->realEscapeString($evalTypeID);
        $subjectCondition = "";
        if ($subjectCategories) {
            $categories = implode("\", \"", $subjectCategories);
            $categories = "\"" . $categories . "\"";
            $subjectCondition = " AND subc.subjectcatName IN ($categories)";
        }
        $sql = "SELECT sa.staffID,sa.staffName,sr.subjectID,sub.subjectName,sr.sbsID,ss.batchID,ss.semID,b.batchName
                FROM staffeval_stafflist ss 
                INNER JOIN sbs_relation sr ON ss.sbsID = sr.sbsID
                INNER JOIN batches b ON b.batchID = ss.batchID
                INNER JOIN staffaccounts sa ON sa.staffID = sr.staffID 
                INNER JOIN subjects sub ON sub.subjectID = sr.subjectID 
                LEFT JOIN subject_category subc ON  subc.subjectcatID = sub.subjectcatID 
                WHERE ss.eval_typeID = $evalTypeID AND b.deptID = $deptId $subjectCondition";
        try {
            $evalFaculties = new \stdClass();
            $evalFaculties->staffs = $this->executeQueryForList($sql, $this->mapper [StaffServiceMapper::GET_STAFF_EVALUATION]);
            $evalFaculties = $this->addSubjectCountAndStudentCountToEvaluationFacultiesByDeptResponse($evalFaculties, $evalTypeID);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $evalFaculties;
    }
    /**
     * Undocumented function
     *
     * @param $evalFaculties
     * @param $evalTypeID
     * @return void
     * @throws ProfessionalException
     */
    public function addSubjectCountAndStudentCountToEvaluationFacultiesByDeptResponse($evalFaculties, $evalTypeID)
    {
        $subjectCount = 0;
        $studentCount = 0;
        foreach ($evalFaculties->staffs as $faculty) {
            if ($subjectCount < count($faculty->subjects)) {
                $subjectCount = count($faculty->subjects);
            }
            foreach ($faculty->subjects as $facultySubject) {
                $studentCount = $this->getEvalStudentAnswerCount($facultySubject->batchId, $facultySubject->semId, $evalTypeID, $facultySubject->sbsId);
                $facultySubject->studentCount = $studentCount;
            }
        }
        $evalFaculties->subjectCount = $subjectCount;
        return $evalFaculties;
    }
    /**
     * get evaluation type details
     *
     * @param integer $evalID
     * @return Object|null
     * @throws ProfessionalException
     */
    public function getEvaluationTypeById($evalID)
    {
        $evalID = $this->realEscapeString($evalID);
        $evaluationType = NULL;
        $sql = "select distinct eval_typeID as id, eval_name as name from staffeval_type WHERE eval_typeID=$evalID";
        try {
            $evaluationType = $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $evaluationType;
    }
    /**
     * Create staff privilege to add marks on autonormalize
     *
     * @param int $batchId
     * @param int $deptId
     * @param int $addmarks
     * @param int $round
     * @param int $staffId
     * @param int $rule
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function createAddMarksPrivilege($batchId, $deptId, $addmarks, $round, $staffId, $rule)
    {
        $deptId = $this->realEscapeString($deptId);
        $batchId = $this->realEscapeString($batchId);
        $staffId = $this->realEscapeString($staffId);
        $addmarks = $this->realEscapeString($addmarks);
        $round = $this->realEscapeString($round);
        $rule = $this->realEscapeString($rule);
        $sql = "insert into normalize_add_marks_privilege (deptId, batchId,addMarksHide, roundOffHide ,facultyNormalizeHide, createdBy, createdDate, updatedBy, updatedDate) value ($deptId$batchId$addmarks$round$rule$staffId, UTC_TIMESTAMP(), $staffId, UTC_TIMESTAMP())";
        try {
            return $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Delete staff privilege to add marks on autonormalize
     *
     * @param int $batchId
     * @param int $deptId
     * @return MySqlResult
     * @throws ProfessionalException
     */
    public function deleteAddMarksPrivilege($batchId, $deptId)
    {
        $deptId = $this->realEscapeString($deptId);
        $batchId = $this->realEscapeString($batchId);
        $sql = "delete from normalize_add_marks_privilege where deptId = $deptId and batchId = $batchId";
        try {
            return $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Get Grievances from students
     *
     * @param string $tableName
     * @param string $fromdate
     * @param string $todate
     * @param int $deptId
     * @throws ProfessionalException
     */
    public function getGrievances($tableName, $fromdate, $todate, $deptId = 0, $staffId)
    {
        $fromdate = $this->realEscapeString($fromdate);
        $todate = $this->realEscapeString($todate);
        $tableName = $this->realEscapeString($tableName);
        $deptId = $this->realEscapeString($deptId);
        $staffId = $this->realEscapeString($staffId);
        $strCond = "";
        if ($deptId) {
            $strCond = " and ( sm.deptID = $deptId";
            $batches = BatchService::getInstance()->getHODPrivilegedBatchIdsAndSemIds($staffId);
            if ($batches) {
                $batchIds = $batches['batchIds'];
                $semIds = $batches['semIds'];
                for ($i = 0; $i < count($batchIds); $i++) {
                    $strCond .= " OR (bat.batchID = " . $batchIds[$i] . " and bat.semID = " . $semIds[$i] . ")";
                }
            }
            $strCond .= " )";
        }
        $sql = "select sm.messageID, sm.studentID, sm.createdDate, sm.messageSubject, sa.studentName, bat.batchName, sm.isRead from $tableName sm inner join studentaccount sa on  sm.studentID = sa.studentID inner join batches bat on sm.batchID = bat.batchID where sm.createdDate between '$fromdate' and '$todate$strCond Order by createdDate ASC";
        try {
            $messages = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $messages;
    }
    /**
     * Checks if grievane assigned to staff
     *
     * @param string $msgRecipient
     * @param int $msgId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function getGrievaneAssignedIdToStaff($msgRecipient, $msgId)
    {
        $sql = " select id from grievance_assignstaff where " . $msgRecipient . "_id =  $msgId";
        try {
            $assignedId = $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $assignedId;
    }
    /**
     * Checks if grievane assigned to staff
     *
     * @param int $grievanceId
     * @return boolean
     * @throws ProfessionalException
     */
    public function isActionTakenForGrievance($grievanceId)
    {
        $sql = " select id from grievance_cell_action where grievance_assignstaff_id = $grievanceId";
        try {
            $actionTakenId = $this->executeQueryForObject($sql);
            if ($actionTakenId) {
                return true;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return false;
    }
    /**
     * Get sbsId of a staff by subject
     *
     * @param int $staffId
     * @param int $semId
     * @param int $batchId
     * @param int $subjectId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffSbsIdBySubject($staffId, $semId, $batchId, $subjectId)
    {
        $sql = "select sbsID from sbs_relation where staffID = $staffId and batchID = $batchId and semID = $semId and subjectID = $subjectId";
        try {
            $sbsId = $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $sbsId;
    }
    /**
     * Get all staffs and their handling subjects by dept
     *
     * @param int $deptId
     * @throws ProfessionalException
     */
    public function getStaffSubjectAllocation($deptId)
    {
        $deptId = $this->realEscapeString($deptId);
        $sql = "SELECT sa.staffID, sa.staffName, sdep.deptName as staffDept, bct.id,bct.type_name, bct.is_pg, sub.subjectID, sub.subjectName,sub.subjectDesc, sc.subjectcatName AS subjectCategory from staffaccounts sa inner join sbs_relation sr on sa.staffID = sr.staffID inner join batches ba on ba.batchID = sr.batchID and sr.semID = ba.semID inner join batch_course_type bct on bct.id = ba.patternID inner join subjects sub on sub.subjectID = sr.subjectID 
        LEFT JOIN subject_category sc ON (sub.subjectcatID = sc.subjectcatID)
        LEFT JOIN department sdep ON (sa.deptID = sdep.deptID) 
        WHERE sa.deptID = $deptId and sub.subjectName != '" . Subject::TUTOR_SUBJECT . "' and sa.isResigned = 0 order by sa.staffID, sub.subjectcatID Desc, is_pg";
        try {
            $sujectAllocations = $this->executeQueryForList($sql, $this->mapper [StaffServiceMapper::GET_STAFF_SUBJECT_ALLOCATION]);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $sujectAllocations;
    }
    /**
     * Update staff privilege to add marks on autonormalize
     *
     * @param int $batchId
     * @param int $deptId
     * @param int $addmarks
     * @param int $round
     * @param int $staffId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function updateAddMarksPrivilege($batchId, $deptId, $staffId, $addmarks = null, $round = null, $rule = null)
    {
        $deptId = $this->realEscapeString($deptId);
        $batchId = $this->realEscapeString($batchId);
        $staffId = $this->realEscapeString($staffId);
        $addmarks = $this->realEscapeString($addmarks);
        $round = $this->realEscapeString($round);
        $rule = $this->realEscapeString($rule);
        $sql_rule = "";
        $sql_addMarks = "";
        $sql_round = "";
        if ($addmarks != null) {
            $sql_addMarks = " addMarksHide = $addmarks,";
        }
        if ($round != null) {
            $sql_round = " roundOffHide = $round,";
        }
        if ($rule != null) {
            $sql_rule = " facultyNormalizeHide = $rule,";
        }
        $sql = "update normalize_add_marks_privilege set $sql_addMarks $sql_round $sql_rule updatedBy = $staffId, updatedDate= UTC_TIMESTAMP() where batchId = $batchId and deptId = $deptId";
        try {
            return $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * get staff hour details by date, hour and staffid
     *
     * @param int $staffId
     * @param string $date
     * @param int $hour
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffHourDetails($staffId, $date, $hour)
    {
        $staffId = $this->realEscapeString($staffId);
        $date = $this->realEscapeString($date);
        $hour = $this->realEscapeString($hour);
        $date = date('Y-m-d', strtotime($date));
        $hourDetails = null;
        $sql = "SELECT group_concat(DISTINCT bth.batchName) AS batchName , group_concat(DISTINCT sbj.subjectName) AS subjectName, if(sbth.subbatchName,sbth.subbatchName,'All') as subbatchName, group_concat(distinct sbjp.topicName) as topicName ,bt.stratTime as startTime, bt.endTime  FROM batch_timetable bt INNER JOIN sbs_relation sr ON sr.batchID=bt.batchID INNER JOIN attendance_confirm acm ON acm.batchID=sr.batchID AND bt.timetableDate = acm.attendanceDate AND bt.hourID=acm.hour AND sr.sbsID=acm.sbsID INNER JOIN staffaccounts sa ON sa.staffID=sr.staffID INNER JOIN batches bth ON bth.batchID=bt.batchID INNER JOIN subjects sbj ON sbj.subjectID=sr.subjectID LEFT JOIN subjectplan sbjp ON sbjp.sbsID=sr.sbsID AND FROM_UNIXTIME(sbjp.date) like '$date%' LEFT JOIN subbatch_sbs ss ON ss.sbsID=sr.sbsID LEFT JOIN subbatches sbth ON sbth.subbatchID=ss.subbatchID WHERE bt.timetableDate='$date' AND sa.staffID=$staffId AND bt.hourID=$hour group by bt.hourID";
        try {
            $hourDetails = $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $hourDetails;
    }
    /**
     *  get staff worklog details on time mode
     *
     * @param Int $staffId
     * @param String $date
     * @return void
     */
    public function getStaffAttendanceMarkedDetails($staffId, $date)
    {
        $staffId = $this->realEscapeString($staffId);
        $date = $this->realEscapeString($date);
        $date = date('Y-m-d', strtotime($date));
        $attendanceMarkedDetails = null;
        $sql = "SELECT group_concat(DISTINCT bth.batchName) AS batchName , group_concat(DISTINCT sbj.subjectName) AS subjectName, bt.stratTime as startTime, group_concat(distinct sbjp.topicName) as topicName ,bt.endTime FROM batch_timetable bt INNER JOIN sbs_relation sr ON sr.batchID=bt.batchID INNER JOIN attendance_confirm acm ON acm.batchID=sr.batchID AND bt.timetableDate = acm.attendanceDate AND acm.hour=bt.hourID AND sr.sbsID=acm.sbsID INNER JOIN staffaccounts sa ON sa.staffID=sr.staffID INNER JOIN batches bth ON bth.batchID=bt.batchID INNER JOIN subjects sbj ON sbj.subjectID=sr.subjectID LEFT JOIN subjectplan sbjp ON sbjp.sbsID=sr.sbsID AND FROM_UNIXTIME(sbjp.date) like '$date%' LEFT JOIN subbatch_sbs ss ON ss.sbsID=sr.sbsID 
        LEFT JOIN subbatches sbth ON sbth.subbatchID=ss.subbatchID  WHERE bt.timetableDate= '$date' AND sa.staffID = $staffId group by UNIX_TIMESTAMP(STR_TO_DATE( bt.stratTime, '%h:%i %p')),UNIX_TIMESTAMP(STR_TO_DATE(bt.endTime , '%h:%i %p'))";
        try {
            $attendanceMarkedDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $attendanceMarkedDetails;
    }
    /**
     * add new work log for a staff
     *
     * @param
     *            array of StaffDailyWorkLog $staffWorkLogList
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function addStaffWorkLog($staffWorkLogList)
    {
        $staffWorkLogList = $this->realEscapeArray($staffWorkLogList);
        if (!empty ($staffWorkLogList) && $staffWorkLogList != NULL) {
           
            $sql = "INSERT INTO staffDailyWorkLog (staffId, date, hourName, hourId, startTime, endTime, isExtraHour, workDetails, status,submittedDate, type, createdBy, createdDate, updatedBy, updatedDate) VALUES ";
            $value = [];
            foreach ($staffWorkLogList as $staffWorkLog) {
                if($staffWorkLog->status=='SUBMITTED'){
                    $submittedDate  = 'utc_timestamp()';
                }else{
                    $submittedDate = null;
                }
                $value [] = "($staffWorkLog->staffId, '" . date('Y-m-d', strtotime($staffWorkLog->date)) . "', '$staffWorkLog->hourName', $staffWorkLog->hourId" . ($staffWorkLog->startTime ? "'$staffWorkLog->startTime'" : 'null') . ", " . ($staffWorkLog->endTime ? "'$staffWorkLog->endTime'" : 'null') . ", '$staffWorkLog->isExtraHour', '$staffWorkLog->workDetails', '$staffWorkLog->status', '$submittedDate','$staffWorkLog->type', $staffWorkLog->createdBy, utc_timestamp(), $staffWorkLog->updatedBy, utc_timestamp())";
            }
            $sql .= implode(',', $value);
            try {
                $date = date('Y-m-d', strtotime($staffWorkLog->date));
                // $sqlCheck = "INSERT INTO staffDailyWorkLog (staffId, date, hourName, hourId, startTime, endTime, isExtraHour, workDetails, status,submittedDate, type, createdBy, createdDate, updatedBy, updatedDate) VALUES (6, '2024-05-03', 'Hour-1', 1, '17:15', '17:45', '', 'test test test test test', 'NOT_SUBMITTED', '','Meeting', 6, utc_timestamp(), 6, utc_timestamp())";
                $sqlCheck = "SELECT id from staffDailyWorkLog WHERE staffId = $staffWorkLog->staffId and `date` = '$date'  and status = '$staffWorkLog->status' and workDetails = '$staffWorkLog->workDetails' AND type='$staffWorkLog->type'";
                $hasDuplicate =  $this->executeQueryForObject($sqlCheck);
                if($hasDuplicate)
                {
                    return false;
                }
                $this->executeQueryForObject($sql);
                return true;
            } catch (\Exception $e) {
                throw new ProfessionalException ($e->getCode(), $e->getMessage());
            }
        }
    }
    /**
     * update staff work log by id
     *
     * @param StaffDailyWorkLog $staffWorkLog
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function updateStaffWorkLog($staffWorkLog)
    {
        $condition="";
        if($staffWorkLog->isRejected && $staffWorkLog->status=='SUBMITTED'){
            $condition=",isVerified = 0, submittedDate = utc_timestamp() ";
        } else if($staffWorkLog->status=='SUBMITTED'){
            $condition=", submittedDate = utc_timestamp() ";
        }
        $staffWorkLog = $this->realEscapeObject($staffWorkLog);
        $sql = "UPDATE staffDailyWorkLog SET hourName='$staffWorkLog->hourName', startTime=" . ($staffWorkLog->startTime ? "'$staffWorkLog->startTime'" : 'null') . ", endTime=" . ($staffWorkLog->endTime ? "'$staffWorkLog->endTime'" : 'null') . ", workDetails='$staffWorkLog->workDetails', status='$staffWorkLog->status',
        type='$staffWorkLog->type',
         updatedBy=$staffWorkLog->updatedBy, updatedDate=utc_timestamp() $condition WHERE id=$staffWorkLog->id";
        try {
            return $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * update all hour work log in a day
     *
     * @param
     *            array of StaffDailyWorkLog $staffWorkLogList
     * @throws ProfessionalException
     */
    public function updateStaffWorkLogByDay($staffWorkLogList)
    {
        $staffWorkLogNewList = [];
        $staffWorkLogList = $this->realEscapeArray($staffWorkLogList);
        if (!empty ($staffWorkLogList) && $staffWorkLogList != NULL) {
            $workLogDate = current($staffWorkLogList)->date;
            $staffId = current($staffWorkLogList)->staffId;
            $workLogList = StaffService::getInstance()->getStaffWorkLogByDate($staffId, $workLogDate);
            foreach ($workLogList as $workLog) {
                $existingWorklogIdArray[] = $workLog->id;
                if($workLog->isVerified ==  3){
                    $isRejected = true;
                }
            }
            $staffWorkLogToDelete = [];
            foreach ($staffWorkLogList as $staffWorkLog) {
                try {
                    if ($staffWorkLog->id) {
                        if($isRejected){
                            $staffWorkLog->isRejected= true;
                        }
                        $worklogIdArray[] = $staffWorkLog->id;
                        $this->updateStaffWorkLog($staffWorkLog);
                    } else {
                        $staffWorkLogNewList [] = $staffWorkLog;
                    }
                } catch (\Exception $e) {
                    throw new ProfessionalException ($e->getCode(), $e->getMessage());
                }
            }
            if (count($staffWorkLogNewList)) {
                try {
                    $response = $this->addStaffWorkLog($staffWorkLogNewList);
                    if(!$response)
                    {
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                } catch (\Exception $e) {
                    throw new ProfessionalException ($e->getCode(), $e->getMessage());
                }
            }
            $staffWorkLogToDelete = array_diff($existingWorklogIdArray, $worklogIdArray);
            if (!empty ($staffWorkLogToDelete)) {
                try {
                    $this->removeStaffWorkLog($staffWorkLogToDelete);
                } catch (\Exception $e) {
                    throw new ProfessionalException ($e->getCode(), $e->getMessage());
                }
            }
        }
    }
    /**
     * delete row from staff daily dorkLog
     *
     * @param int $staffId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function removeStaffWorkLog($deleteIdArray)
    {
        $deleteIdArray = $this->realEscapeArray($deleteIdArray);
        $deleteIds = implode(",", $deleteIdArray);
        $sql = "DELETE FROM staffDailyWorkLog WHERE id IN ($deleteIds)";
        try {
            return $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * get staff daily work log by staff id and date
     *
     * @param int $staffId
     * @param string $date
     * @throws ProfessionalException
     */
    public function getStaffWorkLogByDate($staffId, $date)
    {
        $staffId = $this->realEscapeString($staffId);
        $date = $this->realEscapeString($date);
        $date = date('Y-m-d', strtotime($date));
        $workLog = [];
        $sql = "select * from staffDailyWorkLog WHERE date='$date' AND staffId=$staffId ORDER BY hourId";
        try {
            $workLog = $this->executeQueryForList($sql, $this->mapper [StaffServiceMapper::GET_STAFF_WORK_LOG]);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        // print_r($workLog);
        return $workLog;
    }
     /**
     * reject staff worklog details 
     * @param Int $staffId
     * @param String $date
     * @return void
     */
    public function rejectStaffWorkLogByDate($staffId, $date)
    {
        $staffId = $this->realEscapeString($staffId);
        $date = $this->realEscapeString($date);
        $sql = "UPDATE  staffDailyWorkLog SET isVerified = 3 ,verifiedBy = null, verifiedDate=null,approvedBy=null,approvedDate=null,status='NOT_SUBMITTED',submittedDate=null WHERE date='$date' AND staffId=$staffId";
        try {
            return $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        
    }
     /**
     * reject staff worklog details 
     * @param Int $staffId
     * @param String $date
     * @return void
     */
    public function getRejectedStaffWorkLogByDate($staffId, $date)
    {
        $staffId = $this->realEscapeString($staffId);
        $date = $this->realEscapeString($date);
        $date = date('Y-m-d', strtotime($date));
        $sql = "SELECT * FROM  staffDailyWorkLog WHERE isVerified = 3 AND  date='$date' AND staffId=$staffId";
        try {
            return $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        
    }
    /**
     * delete staff daily work log by staff id and date
     *
     * @param int $staffId
     * @param string $date
     * @throws ProfessionalException
     */
    public function deleteStaffWorkLogByDate($staffId, $date)
    {
        $staffId = $this->realEscapeString($staffId);
        $date = $this->realEscapeString($date);
        $date = date('Y-m-d', strtotime($date));
        $workLog = [];
        $sql = "DELETE from staffDailyWorkLog WHERE date='$date' AND staffId=$staffId ORDER BY hourId";
        try {
            $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return true;
    }
    /**
     * get staff daily work log by staff id and date
     *
     * @param int $staffId
     * @param string $date
     * @throws ProfessionalException
     */
    public function getStaffWorkLogByStaff($staffId, $from, $to)
    {
        $staffId = $this->realEscapeString($staffId);
        $from = $this->realEscapeString($from);
        $to = $this->realEscapeString($to);
        $from = date('Y-m-d', strtotime($from));
        $to = date('Y-m-d', strtotime($to));
        $workLog = [];
        $sql = "select * from staffDailyWorkLog WHERE date BETWEEN '$from' AND '$to' AND staffId=$staffId";
        try {
            $workLog = $this->executeQueryForList($sql, $this->mapper [StaffServiceMapper::GET_STAFF_WORK_LOG_REPORT]);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $workLog;
    }
    /**
     * staff selected date is work log markable or not
     *
     * @param string $workLogDate
     * @return boolean
     */
    public function isStaffWorkLogDateValid($workLogDate)
    {
        $flag = true;
        $isEnabled = CommonService::getInstance()->getSettings(SettingsConstents::DAILY_WORK_LOG, SettingsConstents::DAILY_WORK_LOG_LIMIT_INCLUDE);
        if ($isEnabled) {
            $workLogDate = $this->realEscapeString($workLogDate);
            $workLogDate = date('Y-m-d', strtotime($workLogDate));
            $limit = CommonService::getInstance()->getSettings(SettingsConstents::DAILY_WORK_LOG, SettingsConstents::DAILY_WORK_LOG_LIMIT);
            $type = CommonService::getInstance()->getSettings(SettingsConstents::DAILY_WORK_LOG, SettingsConstents::DAILY_WORK_LOG_LIMIT_TYPE);
            $timeForDailyWorkLog = json_decode(CommonService::getInstance()->getSettings(SettingsConstents::DAILY_WORK_LOG, SettingsConstants::DAILY_WORK_LOG_LIMIT_ADD_ON_TIME));
            switch ($type) {
                case "DAY" :
                    if($timeForDailyWorkLog->enableAddOnTime){
                        $date = date("Y-m-d H:i:s");
                        $workLogDate = date("Y-m-d H:i:s", strtotime(date("Y-m-d",strtotime("+" . $limit . " day", strtotime($workLogDate)))." ".$timeForDailyWorkLog->addOnTime));
                    }else{
                        $date = date("Y-m-d");
                        $workLogDate = date("Y-m-d",strtotime("+" . $limit . " day", strtotime($workLogDate)));
                    }
                    if ($date > $workLogDate) {
                        $flag = false;
                    }
                    break;
                case "WEEK":
                    $date = new \DateTime($workLogDate);
                    // Modify the date it contains
                    $weekNoSunday = date('N', strtotime($date->format('Y-m-d')));
                    if ($weekNoSunday != 7) {
                        $date->modify('next sunday');
                    }
                    $sunday = $date->format('Y-m-d');
                    if($timeForDailyWorkLog->enableAddOnTime){
                        $newdate = date("Y-m-d H:i:s", strtotime(date("Y-m-d",strtotime("+" . $limit . " day", strtotime($sunday)))." ".$timeForDailyWorkLog->addOnTime));
                        $dateTime = date("Y-m-d H:i:s");
                    }else{
                        $newdate =  date("Y-m-d",strtotime("+" . $limit . " day", strtotime($sunday)));
                        $dateTime = date("Y-m-d");
                    }
                    if ($newdate < $dateTime) {
                        $flag = false;
                    }
                    break;
                case "MONTH":
                    $date = new \DateTime($workLogDate);
                    $lastDate = $date->format('Y-m-d');
                    if ($date->format('Y-m-t') != $date->format('Y-m-d')) {
                        $lastDate = $date->format('Y-m-t');
                    }
                    if($timeForDailyWorkLog->enableAddOnTime){
                        $newdate = date("Y-m-d H:i:s", strtotime(date("Y-m-d",strtotime("+" . $limit . " day", strtotime($lastDate)))." ".$timeForDailyWorkLog->addOnTime));
                        $dateTime = date("Y-m-d H:i:s");
                    }else{
                        $newdate = date("Y-m-d",strtotime("+" . $limit . " day", strtotime($lastDate)));
                        $dateTime = date("Y-m-d");
                    }
                    if ($newdate < $dateTime) {
                        $flag = false;
                    }
                    break;
            }
        }
        return $flag;
    }
    /**
     * get daily work log approval list
     *
     * @param WorkLogApprovalListRequest $workLogApprovalListRequest
     * @return \com\linways\core\ams\professional\response\WorkLogApprovalListResponse
     * @throws ProfessionalException
     */
    public function getDailyWorkLogApprovalListByDate($workLogApprovalListRequest)
    {
        $workLogApprovalListRequest = $this->realEscapeObject($workLogApprovalListRequest);
        $workLogApprovalListResponse = new WorkLogApprovalListResponse ();
        $date = date('Y-m-d', strtotime($workLogApprovalListRequest->date));
        $isVerified = '';
        $workLog = [];
        $cond = "";
        switch ($workLogApprovalListRequest->position) {
            case AMSConstants::HOD :
                $isVerified = '0,1';
                break;
            case AMSConstants::PRINCIPAL :
                $isVerified = '0,1,2';
                break;
            default :
                $isVerified = '0';
        }
        $sqlCount = "select distinct count(distinct sdwl.staffId) as totalRecords from staffDailyWorkLog sdwl INNER JOIN staffaccounts sa ON sa.staffID=sdwl.staffId WHERE date ='$date' AND status='" . StaffDailyWorkLog::SUBMITTED . "' AND isVerified IN ($isVerified";
        $sql = "select distinct sdwl.date, sa.staffName, sdwl.staffId, sdwl.status,date(sdwl.submittedDate) as submittedDate,sdwl.isVerified,  (select staffName from staffaccounts WHERE staffId=sdwl.verifiedBy) as verifiedStaff,sdwl.verifiedDate, (select staffName from staffaccounts WHERE staffId=sdwl.approvedBy) as approvedStaff,sdwl.approvedDate from staffDailyWorkLog sdwl INNER JOIN staffaccounts sa ON sa.staffID=sdwl.staffId INNER JOIN department dept ON dept.deptID=sa.deptID WHERE date ='$date' AND status='" . StaffDailyWorkLog::SUBMITTED . "' AND isVerified IN ($isVerified";
        if ($workLogApprovalListRequest->deptId) {
            $cond .= "AND sa.deptId=$workLogApprovalListRequest->deptId ";
        }
        if ($workLogApprovalListRequest->staffName) {
            $cond .= "AND sa.staffName like '%$workLogApprovalListRequest->staffName%' ";
        }
        
        $sqlCount .= $cond;
        $sql .= $cond;
        try {
            $workLogApprovalListResponse->totalRecords = $this->executeQueryForObject($sqlCount)->totalRecords;
            if ($workLogApprovalListRequest->isExport) {
                $workLogApprovalListRequest->endIndex = $workLogApprovalListRequest->totalRecords;
            }
            if ($workLogApprovalListRequest->sortBy) {
                $sql .= "ORDER BY $workLogApprovalListRequest->sortBy $workLogApprovalListRequest->sortOrder";
            }
            if($workLogApprovalListRequest->startIndex>=0) {
                $sql .= " LIMIT $workLogApprovalListRequest->startIndex$workLogApprovalListRequest->endIndex";
            }
            $workLogApprovalListResponse->staffList = $this->executeQueryForList($sql, $this->mapper [StaffServiceMapper::GET_STAFF_WORK_LOG_APPROVAL_LIST]);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $workLogApprovalListResponse;
    }
    /**
     * get daily work log approval list
     *
     * @param string $date
     * @param string $position
     * @return object|array|$objectList[]
     * @throws ProfessionalException
     */
    public function getDailyWorkLogApprovalListByDept($date, $deptId, $position)
    {
        $date = $this->realEscapeString($date);
        $position = $this->realEscapeString($position);
        $date = date('Y-m-d', strtotime($date));
        $isVerified = '';
        $workLog = [];
        switch ($position) {
            case AMSConstants::HOD :
                $isVerified = '0,1';
                break;
            case AMSConstants::PRINCIPAL :
                $isVerified = '1,2';
                break;
            default :
                $isVerified = '0';
        }
        $sql = "select distinct sdwl.date, sa.staffName, sdwl.staffId, sdwl.status,sdwl.isVerified, (select staffName from staffaccounts WHERE staffId=sdwl.verifiedBy) as verifiedStaff,sdwl.verifiedDate, (select staffName from staffaccounts WHERE staffId=sdwl.approvedBy) as approvedStaff,sdwl.approvedDate  from staffDailyWorkLog sdwl INNER JOIN staffaccounts sa ON sa.staffID=sdwl.staffId WHERE date ='$date' AND status='" . StaffDailyWorkLog::SUBMITTED . "' AND isVerified IN ($isVerified) AND sa.deptID=$deptId";
        try {
            $workLog = $this->executeQueryForList($sql, $this->mapper [StaffServiceMapper::GET_STAFF_WORK_LOG_APPROVAL_LIST]);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $workLog;
    }
    /**
     * verifiy staff work log
     *
     * @param string $date
     * @param int $staffId
     * @param int $flag
     * @param int $updatedBy
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function verifyWorkLogByStaff($date, $staffId, $flag, $crntStatus, $updatedBy)
    {
        $date = $this->realEscapeString($date);
        $staffId = $this->realEscapeString($staffId);
        $flag = $this->realEscapeString($flag);
        $date = date('Y-m-d', strtotime($date));
        if ($flag == 1) {
            $sql = "UPDATE staffDailyWorkLog SET isVerified=$flag, verifiedBy=$updatedBy, verifiedDate=utc_timestamp(),  updatedBy=$updatedBy, updatedDate=utc_timestamp() WHERE staffId=$staffId AND date='$date'";
        } else {
            $upStr = "";
            if ($crntStatus == 0) {
                $upStr = " verifiedBy=$updatedBy, verifiedDate=utc_timestamp(),";
            }
            $sql = "UPDATE staffDailyWorkLog SET isVerified=$flag$upStr approvedBy=$updatedBy, approvedDate=utc_timestamp(),  updatedBy=$updatedBy, updatedDate=utc_timestamp() WHERE staffId=$staffId AND date='$date'";
        }
        try {
            return $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * verifiy staff work log
     *
     * @param string $date
     * @param int $flag
     * @param array $staffList
     * @param int $updatedBy
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function verifyWorkLogByDate($date, $flag, $staffList, $updatedBy)
    {
        $date = $this->realEscapeString($date);
        $flag = $this->realEscapeString($flag);
        $updatedBy = $this->realEscapeString($updatedBy);
        $staffList = $this->realEscapeArray($staffList);
        $date = date('Y-m-d', strtotime($date));
        if ($flag == 1) {
            $sql = "UPDATE staffDailyWorkLog SET isVerified=$flag, verifiedBy=$updatedBy, verifiedDate=utc_timestamp(),  updatedBy=$updatedBy, updatedDate=utc_timestamp() WHERE date='$date' AND staffId IN (" . implode(',', $staffList) . ")";
        } else {
            $sql = "UPDATE staffDailyWorkLog SET isVerified=$flag, verifiedBy=if(verifiedBy,verifiedBy,$updatedBy), verifiedDate=if(verifiedDate,verifiedDate,utc_timestamp()), approvedBy=$updatedBy, approvedDate=utc_timestamp(),  updatedBy=$updatedBy, updatedDate=utc_timestamp() WHERE date='$date' AND staffId IN (" . implode(',', $staffList) . ")";
        }
        try {
            return $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * get details of daily log not submited staffs
     *
     * @param string $date
     * @param int $deptId
     * @return object|array|$objectList[]
     * @throws ProfessionalException
     */
    public function getWorkLogNotSubmittedStaffs($date, $deptId = 0)
    {
        $date = $this->realEscapeString($date);
        $deptId = $this->realEscapeString($deptId);
        $date = date('Y-m-d', strtotime($date));
        $staffDetails = [];
        $sql = "select distinct sa.staffName, sa.deptID, swl.staffId from staffaccounts sa LEFT JOIN staffDailyWorkLog swl ON swl.staffId=sa.staffID AND swl.date='$date' AND swl.status='" . StaffDailyWorkLog::SUBMITTED . "' WHERE swl.staffId is null AND sa.isResigned=0 AND sa.isPrincipal=0 ";
        if ($deptId) {
            $sql .= "AND sa.deptID=$deptId";
        }
        try {
            $staffDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /**
     * get worklog not submitted staff details
     *
     * @param WorkLogStaffDetailsRequest $workLogStaffDetailsRequest
     * @return object|array|$objectList[]
     * @throws ProfessionalException
     */
    public function getWorkLogNotSubmittedStaffsByDate($workLogStaffDetailsRequest,$includeGuestLecture)
    {
        global $COLLEGE_CODE;
        $workLogStaffDetailsRequest = $this->realEscapeObject($workLogStaffDetailsRequest);
    
        $deptId = $this->realEscapeString($workLogStaffDetailsRequest->deptId);
        $fromDate = date('Y-m-d', strtotime($workLogStaffDetailsRequest->fromDate));
        $toDate = date('Y-m-d', strtotime($workLogStaffDetailsRequest->toDate));
        $staffNameSearchTxt = $this->realEscapeString($workLogStaffDetailsRequest->staffNameSearchTxt);
        $sortBy = $this->realEscapeString($workLogStaffDetailsRequest->sortBy);
        $sortOrder = $this->realEscapeString($workLogStaffDetailsRequest->sortOrder);
        $startIdx = (int)$workLogStaffDetailsRequest->startIndex;
        $endIdx = (int)$workLogStaffDetailsRequest->endIndex;
        $isExport = $workLogStaffDetailsRequest->isExport ? (int)$workLogStaffDetailsRequest->isExport : 0;
        $includeGuestLecture = (int)$includeGuestLecture;
    
        $workLogStaffDetails = new WorkLogStaffDetailsResponse();
    
        try {
            $createTempTableSql = "
            CREATE TEMPORARY TABLE DatesTable AS
            SELECT ADDDATE('1970-01-01', t4.i * 10000 + t3.i * 1000 + t2.i * 100 + t1.i * 10 + t0.i) AS timetableDate
            FROM
                (SELECT 0 i UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t0,
                (SELECT 0 i UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t1,
                (SELECT 0 i UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t2,
                (SELECT 0 i UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t3,
                (SELECT 0 i UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t4
            WHERE ADDDATE('1970-01-01', t4.i * 10000 + t3.i * 1000 + t2.i * 100 + t1.i * 10 + t0.i) BETWEEN '$fromDate' AND '$toDate';
            ";
    
            $this->executeQuery($createTempTableSql);
    
            if ($includeGuestLecture && $COLLEGE_CODE == "IIIC") {
                $sql = "
        SELECT 
            staffID,
            staffName,
            deptName,
            deptID,
            totalWorkingDay,
            totalSubmitted,
            totalNotSubmitted,
            notMarkedDates
        FROM (
            SELECT 
                sa.staffID,
                sa.staffName,
                dept.deptName,
                sa.deptID,
                COUNT(DISTINCT dt.timetableDate) AS totalWorkingDay,
                COUNT(DISTINCT CASE WHEN sdwl.status = 'SUBMITTED' THEN sdwl.date END) AS totalSubmitted,
                COUNT(DISTINCT CASE WHEN sdwl.status IS NULL THEN dt.timetableDate END) AS totalNotSubmitted,
                GROUP_CONCAT(DISTINCT CASE WHEN sdwl.status IS NULL THEN dt.timetableDate END) AS notMarkedDates
            FROM staffaccounts sa
            INNER JOIN department dept ON dept.deptID = sa.deptID
            INNER JOIN DatesTable dt ON dt.timetableDate BETWEEN '$fromDate' AND '$toDate'
            LEFT JOIN staffDailyWorkLog sdwl ON sdwl.staffId = sa.staffID AND sdwl.date = dt.timetableDate
            WHERE sa.isPrincipal = 0
              AND sa.isResigned = 0
              AND sa.staffLock = 0
              AND ('$staffNameSearchTxt' = '' OR sa.staffName LIKE CONCAT('%', '$staffNameSearchTxt', '%'))
              AND ($deptId = 0 OR sa.deptID = $deptId)
            GROUP BY sa.staffID, sa.staffName, dept.deptName, sa.deptID
        ) AS subquery
        WHERE totalNotSubmitted > 0
        ORDER BY 
            CASE '$sortBy'
                WHEN 'deptName' THEN deptName
                WHEN 'staffName' THEN staffName
                WHEN 'totalSubmitted' THEN totalSubmitted
                ELSE staffName
            END $sortOrder
        LIMIT $startIdx$endIdx;
        ";
            } elseif( $COLLEGE_CODE == "IIIC") {
                $sql = "
                 SELECT 
                staffID,
                staffName,
                deptName,
                deptID,
                totalWorkingDay,
                totalSubmitted,
                totalNotSubmitted,
                notMarkedDates
            FROM (
                SELECT 
                    sa.staffID,
                    sa.staffName,
                    dept.deptName,
                    sa.deptID,
                    COUNT(DISTINCT dt.timetableDate) AS totalWorkingDay,
                    COUNT(DISTINCT CASE WHEN sdwl.status = 'SUBMITTED' THEN sdwl.date END) AS totalSubmitted,
                    COUNT(DISTINCT CASE 
                        WHEN sdwl.status IS NULL 
                            AND (sa.lectureType != 2 OR EXISTS (
                                SELECT 1
                                FROM batch_timetable bt
                                INNER JOIN sbs_relation sr ON sr.sbsID = bt.sbsID
                                WHERE sr.staffID = sa.staffID
                                AND bt.timetableDate = dt.timetableDate
                            )) 
                        THEN dt.timetableDate 
                    END) AS totalNotSubmitted,
                    GROUP_CONCAT(DISTINCT CASE 
                        WHEN sdwl.status IS NULL 
                            AND (sa.lectureType != 2 OR EXISTS (
                                SELECT 1
                                FROM batch_timetable bt
                                INNER JOIN sbs_relation sr ON sr.sbsID = bt.sbsID
                                WHERE sr.staffID = sa.staffID
                                AND bt.timetableDate = dt.timetableDate
                            )) 
                        THEN dt.timetableDate 
                    END) AS notMarkedDates
                FROM staffaccounts sa
                INNER JOIN department dept ON dept.deptID = sa.deptID
                INNER JOIN DatesTable dt ON dt.timetableDate BETWEEN '$fromDate' AND '$toDate'
                LEFT JOIN staffDailyWorkLog sdwl ON sdwl.staffId = sa.staffID AND sdwl.date = dt.timetableDate
                WHERE sa.isPrincipal = 0
                AND sa.isResigned = 0
                AND sa.staffLock = 0
                AND ('$staffNameSearchTxt' = '' OR sa.staffName LIKE CONCAT('%', '$staffNameSearchTxt', '%'))
                AND ($deptId = 0 OR sa.deptID = $deptId)
                AND EXISTS (
                    SELECT 1
                    FROM batch_timetable bt
                    INNER JOIN sbs_relation sr ON sr.sbsID = bt.sbsID
                    WHERE sr.staffID = sa.staffID
                        AND bt.timetableDate BETWEEN '$fromDate' AND '$toDate'
                        AND sa.lectureType != 2
                )
                GROUP BY sa.staffID, sa.staffName, dept.deptName, sa.deptID
            ) AS subquery
            WHERE totalNotSubmitted > 0
            ORDER BY 
                CASE '$sortBy'
                    WHEN 'deptName' THEN deptName
                    WHEN 'staffName' THEN staffName
                    WHEN 'totalSubmitted' THEN totalSubmitted
                    ELSE staffName
                END $sortOrder
            LIMIT $startIdx$endIdx;
            ";
            }
            else{
            $sql="
                SELECT 
                staffID,
                staffName,
                deptName,
                deptID,
                totalWorkingDay,
                totalSubmitted,
                totalNotSubmitted,
                notMarkedDates
            FROM (
                SELECT 
                    sa.staffID,
                    sa.staffName,
                    dept.deptName,
                    sa.deptID,
                    COUNT(DISTINCT dt.timetableDate) AS totalWorkingDay,
                    COUNT(DISTINCT CASE WHEN sdwl.status = 'SUBMITTED' THEN sdwl.date END) AS totalSubmitted,
                    COUNT(DISTINCT CASE WHEN sdwl.status IS NULL THEN dt.timetableDate END) AS totalNotSubmitted,
                    GROUP_CONCAT(DISTINCT CASE WHEN sdwl.status IS NULL THEN dt.timetableDate END) AS notMarkedDates
                FROM staffaccounts sa
                INNER JOIN department dept ON dept.deptID = sa.deptID
                INNER JOIN DatesTable dt ON dt.timetableDate BETWEEN '$fromDate' AND '$toDate'
                LEFT JOIN staffDailyWorkLog sdwl ON sdwl.staffId = sa.staffID AND sdwl.date = dt.timetableDate
                WHERE sa.isPrincipal = 0
                  AND sa.isResigned = 0
                  AND sa.staffLock = 0
                  AND ('$staffNameSearchTxt' = '' OR sa.staffName LIKE CONCAT('%', '$staffNameSearchTxt', '%'))
                  AND ($deptId = 0 OR sa.deptID = $deptId)
                GROUP BY sa.staffID, sa.staffName, dept.deptName, sa.deptID
            ) AS subquery
            WHERE totalNotSubmitted > 0
            ORDER BY 
                CASE '$sortBy'
                    WHEN 'deptName' THEN deptName
                    WHEN 'staffName' THEN staffName
                    WHEN 'totalSubmitted' THEN totalSubmitted
                    ELSE staffName
                END $sortOrder
            LIMIT $startIdx$endIdx;
            ";
            $sqlCount = "
            SELECT COUNT(*) AS totalRecord
            FROM (
                SELECT 
                    sa.staffID,
                    sa.staffName,
                    dept.deptName,
                    sa.deptID,
                    COUNT(DISTINCT dt.timetableDate) AS totalWorkingDay,
                    COUNT(DISTINCT CASE WHEN sdwl.status = 'SUBMITTED' THEN sdwl.date END) AS totalSubmitted,
                    COUNT(DISTINCT CASE WHEN sdwl.status IS NULL THEN dt.timetableDate END) AS totalNotSubmitted
                FROM staffaccounts sa
                INNER JOIN department dept ON dept.deptID = sa.deptID
                INNER JOIN DatesTable dt ON dt.timetableDate BETWEEN '$fromDate' AND '$toDate'
                LEFT JOIN staffDailyWorkLog sdwl ON sdwl.staffId = sa.staffID AND sdwl.date = dt.timetableDate
                WHERE sa.isPrincipal = 0
                AND sa.isResigned = 0
                AND sa.staffLock = 0
                AND ('$staffNameSearchTxt' = '' OR sa.staffName LIKE CONCAT('%', '$staffNameSearchTxt', '%'))
                AND ($deptId = 0 OR sa.deptID = $deptId)
                GROUP BY sa.staffID, sa.staffName, dept.deptName, sa.deptID
            ) AS subquery
            WHERE totalNotSubmitted > 0;";
            
                
            }
    
            $sqlCount = "
            SELECT COUNT(*) AS totalRecord
            FROM (
                SELECT 
                    sa.staffID,
                    sa.staffName,
                    dept.deptName,
                    sa.deptID,
                    COUNT(DISTINCT dt.timetableDate) AS totalWorkingDay,
                    COUNT(DISTINCT CASE WHEN sdwl.status = 'SUBMITTED' THEN sdwl.date END) AS totalSubmitted,
                    COUNT(DISTINCT CASE WHEN sdwl.status IS NULL THEN dt.timetableDate END) AS totalNotSubmitted
                FROM staffaccounts sa
                INNER JOIN department dept ON dept.deptID = sa.deptID
                INNER JOIN DatesTable dt ON dt.timetableDate BETWEEN '$fromDate' AND '$toDate'
                LEFT JOIN staffDailyWorkLog sdwl ON sdwl.staffId = sa.staffID AND sdwl.date = dt.timetableDate
                WHERE sa.isPrincipal = 0
                  AND sa.isResigned = 0
                  AND sa.staffLock = 0
                  AND ('$staffNameSearchTxt' = '' OR sa.staffName LIKE CONCAT('%', '$staffNameSearchTxt', '%'))
                  AND ($deptId = 0 OR sa.deptID = $deptId)
                GROUP BY sa.staffID, sa.staffName, dept.deptName, sa.deptID
            ) AS subquery
            WHERE totalNotSubmitted > 0;
            ";
    
            $staffDetails = $this->executeQueryForList($sql);
            $totalRecords = $this->executeQuery($sqlCount);
    
            $workLogStaffDetails->totalRecords = $totalRecords;
            $workLogStaffDetails->staffs = $staffDetails;
    
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    
        return $workLogStaffDetails;
    }
    
    
    
    /**
     * get worklog submitted staff details by date
     *
     * @param WorkLogStaffDetailsRequest $workLogStaffDetailsRequest
     * @param string $toDate
     * @param int $deptId
     * @return object|array|$objectList[]
     * @throws ProfessionalException
     */
    public function getWorkLogSubmittedStaffsByDate($workLogStaffDetailsRequest)
    {
        $workLogStaffDetailsRequest = $this->realEscapeObject($workLogStaffDetailsRequest);
        $deptId = $workLogStaffDetailsRequest->deptId;
        $fromDate = date('Y-m-d', strtotime($workLogStaffDetailsRequest->fromDate));
        $toDate = date('Y-m-d', strtotime($workLogStaffDetailsRequest->toDate));
        $staffDetails = [];
        $totalWorkingDays = TimetableService::getInstance()->getTotalWorkingDays($fromDate, $toDate);
        $workLogStaffDetails = new WorkLogStaffDetailsResponse ();
//         $sql = "SELECT date, staffName, staffId, deptName, deptID, totalSubmitted, totalWorkingDay FROM ( select distinct group_concat( distinct sdwl.date) as date, sa.deptID,sa.staffName, sdwl.staffId, sdwl.status, dept.deptName, (SELECT count(distinct date) FROM staffDailyWorkLog WHERE staffId=sdwl.staffId AND status='SUBMITTED' and date  between  '$fromDate' AND '$toDate') as totalSubmitted, (select count(distinct bt.timetableDate) FROM batch_timetable bt LEFT JOIN lms_calender lc ON bt.timetableDate BETWEEN FROM_UNIXTIME(lc.timeStart) AND FROM_UNIXTIME(lc.timeEnd) AND lc.deptID=0 and lc.batchID=0 AND lc.flag in (1,3) WHERE bt.timetableDate BETWEEN '$fromDate' AND '$toDate' AND eventID is null) AS totalWorkingDay from staffDailyWorkLog sdwl INNER JOIN staffaccounts sa ON sa.staffID=sdwl.staffId  INNER JOIN department dept ON dept.deptID = sa.deptID WHERE date BETWEEN '$fromDate' AND '$toDate' AND status='SUBMITTED' ";
//         $sqlCount = "SELECT count(staffId) as totalRecord FROM ( select distinct group_concat( distinct sdwl.date) as date, sa.deptID,sa.staffName, sdwl.staffId, sdwl.status, dept.deptName, (SELECT count(distinct date) FROM staffDailyWorkLog WHERE staffId=sdwl.staffId AND status='SUBMITTED' and date  between  '$fromDate' AND '$toDate') as totalSubmitted, (select count(distinct bt.timetableDate) FROM batch_timetable bt LEFT JOIN lms_calender lc ON bt.timetableDate BETWEEN FROM_UNIXTIME(lc.timeStart) AND FROM_UNIXTIME(lc.timeEnd) AND lc.deptID=0 and lc.batchID=0 AND lc.flag in (1,3) WHERE bt.timetableDate BETWEEN '$fromDate' AND '$toDate' AND eventID is null) AS totalWorkingDay from staffDailyWorkLog sdwl INNER JOIN staffaccounts sa ON sa.staffID=sdwl.staffId  INNER JOIN department dept ON dept.deptID = sa.deptID WHERE date BETWEEN '$fromDate' AND '$toDate' AND status='SUBMITTED' ";
        $sql = "select date,
                staffName,
                staffId,
                deptName,
                deptID,
                " . $totalWorkingDays . " as totalWorkingDay,
                totalSubmitted from (select count(DISTINCT date) as totalSubmitted, GROUP_CONCAT(DISTINCT sdwl.date) AS date,sa.deptID,
                        sa.staffName,
                        sdwl.staffId,
                        sdwl.status,
                        dept.deptName from staffDailyWorkLog sdwl
                INNER JOIN staffaccounts sa ON sa.staffID = sdwl.staffId
                INNER JOIN department dept ON dept.deptID = sa.deptID
                WHERE
                date BETWEEN '" . $fromDate . "' AND '" . $toDate . "'
                    AND status = 'SUBMITTED' ";
        $sqlCount = "SELECT count(staffId) as totalRecord FROM ( select date,
                    staffName,
                    staffId,
                    deptName,
                    deptID,
                    totalSubmitted from (select count(DISTINCT date) as totalSubmitted, GROUP_CONCAT(DISTINCT sdwl.date) AS date,sa.deptID,
                
                            sa.staffName,
                            sdwl.staffId,
                            sdwl.status,
                            dept.deptName from staffDailyWorkLog sdwl
                    INNER JOIN staffaccounts sa ON sa.staffID = sdwl.staffId
                    INNER JOIN department dept ON dept.deptID = sa.deptID
                    WHERE
                        date BETWEEN '" . $fromDate . "' AND '" . $toDate . "'
                    AND status = 'SUBMITTED' ";
        if ($deptId) {
            $cond .= "AND sa.deptID=$deptId ";
        }
        if ($workLogStaffDetailsRequest->staffName) {
            $cond .= "AND sa.staffName like '%$workLogStaffDetailsRequest->staffName%' ";
        }
        $cond .= "group by sdwl.staffId) AS submittedList";
        $sqlCount .= $cond . " ) as submitted ";
        $order = "";
        if ($workLogStaffDetailsRequest->sortBy) {
            $order = " ORDER BY $workLogStaffDetailsRequest->sortBy $workLogStaffDetailsRequest->sortOrder";
        }
        $sql .= $cond . $order;
        $sqlCount .= $order;
        $workLogStaffDetails->totalRecords = $this->executeQueryForObject($sqlCount)->totalRecord;
        if ($workLogStaffDetailsRequest->isExport) {
            $workLogStaffDetails->endIndex = $workLogStaffDetails->totalRecords;
        } else {
            $sql .= " LIMIT $workLogStaffDetailsRequest->startIndex,$workLogStaffDetailsRequest->endIndex";
        }
        try {
            $workLogStaffDetails->staffs = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $workLogStaffDetails;
    }
    /**
     * get Submitted staff daily work log by staff id and by from and to dates
     *
     * @param int $staffId
     * @param string $date
     * @throws ProfessionalException
     */
    public function getWorkLogSubmittedByStaffAndByDate($staffId, $from, $to)
    {
        $staffId = $this->realEscapeString($staffId);
        $from = $this->realEscapeString($from);
        $to = $this->realEscapeString($to);
        $from = date('Y-m-d', strtotime($from));
        $to = date('Y-m-d', strtotime($to));
        $workLog = [];
        $sql = "select * from staffDailyWorkLog WHERE date BETWEEN '$from' AND '$to' AND staffId = $staffId AND status='SUBMITTED' order by date desc,hourId asc";
        try {
            $workLog = $this->executeQueryForList($sql, $this->mapper [StaffServiceMapper::GET_STAFF_WORK_LOG_REPORT]);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $workLog;
    }
    /**
     * get Not Submitted staff daily work log by staff id and by from and to dates
     *
     * @param int $staffId
     * @param string $date
     * @throws ProfessionalException
     */
    public function getWorkLogNotSubmittedByStaffAndByDate($staffId, $from, $to)
    {
        $staffId = $this->realEscapeString($staffId);
        $from = $this->realEscapeString($from);
        $to = $this->realEscapeString($to);
        $from = date('Y-m-d', strtotime($from));
        $to = date('Y-m-d', strtotime($to));
        $workLog = [];
        $sql = "select * from staffDailyWorkLog WHERE date BETWEEN '$from' AND '$to' AND staffId=$staffId AND status='NOT_SUBMITTED' order by date desc,hourId asc";
        try {
            $workLog = $this->executeQueryForList($sql, $this->mapper [StaffServiceMapper::GET_STAFF_WORK_LOG_REPORT]);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $workLog;
    }
    
    /**
     * Checks if the staff is a tutor
     *
     * @param int $staffId
     * @return boolean
     * @throws ProfessionalException
     */
    public function isTutor($staffId)
    {
        $staffId = $this->realEscapeString($staffId);
        $sql = "SELECT COUNT(staffID) as count from batch_tutor bt 
                INNER JOIN batches ba on bt.semID = ba.semID 
                AND ba.batchID = bt.batchID  where staffID = $staffId";
        try {
            $count = $this->executeQueryForObject($sql)->count;
            if ($count) {
                return true;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return false;
    }
    /**
     * Get all previous batches assigned to the staff
     *
     * @param int $staffId
     * @return object|array|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffAssignedPreviousBatches($staffId, $deptId)
    {
        $staffId = $this->realEscapeString($staffId);
        $deptId = $this->realEscapeString($deptId);
        $sql = "select distinct (sr.batchID), bat.batchName from sbs_relation sr inner join batches bat on sr.batchID = bat.batchID where sr.semId not in (select semID from batches where batchID = bat.batchID)  and  isPseudosubject =0 and sr.sbsID NOT IN (SELECT sbsID FROM pseudosubjects_sbs) and staffID = $staffId and deptID =  $deptId";
        try {
            $batchDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $batchDetails;
    }
    /**
     * Get all previous semesters assigned to the staff by batch
     *
     * @param int $staffId
     * @param int $batchId
     * @throws ProfessionalException
     */
    public function getStaffAssignedPreviousSemByBatchId($staffId, $batchId)
    {
        $staffId = $this->realEscapeString($staffId);
        $batchId = $this->realEscapeString($batchId);
        $sql = "select distinct sr.semID, semName from sbs_relation sr inner join batches bat on sr.batchID = bat.batchID left join semesters se on se.semID = sr.semID where sr.semId not in (select semID from batches where batchID = bat.batchID)  and  isPseudosubject =0 and sr.sbsID NOT IN (SELECT sbsID FROM pseudosubjects_sbs) and staffID = $staffId and bat.batchId = $batchId";
        try {
            $semDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $semDetails;
    }
    /**
     * Get all previous subjects assigned to the staff
     *
     * @param int $staffId
     * @param int $deptId
     * @param int $batchId
     * @param int $semId
     * @param int $subjectCode
     * @return object|array|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffAssignedPreviousSubjects($staffRequest)
    {
        $staffRequest = $this->realEscapeObject($staffRequest);
        if ($staffRequest->deptId) {
            $sql_dept = " and bat.deptId = $staffRequest->deptId";
        }
        if ($staffRequest->batchId) {
            $sql_batch = " and bat.batchID = $staffRequest->batchId";
        }
        if ($staffRequest->semId) {
            $sql_sem = " and sr.semID = $staffRequest->semId";
        }
        if ($staffRequest->subjectCode) {
            $sql_sub = " and subjectName like \"$staffRequest->subjectCode%\"";
        }
        $sql = "select 
        sr.sbsID,sr.subjectID, subjectName, subjectDesc, GROUP_CONCAT(bat.batchID) as batchID , GROUP_CONCAT(batchName) as batchName ,sr.semID, GROUP_CONCAT(semName) as semName, IF(psbs.pseudosubjectID is null, 0, 1) as isPseudosubject,psbs.pseudosubjectID, 0 AS isPseudosubjectBatch
        from sbs_relation sr 
        inner join batches bat on sr.batchID = bat.batchID 
        inner join semesters se on se.semID = sr.semID 
        inner join subjects sub on sub.subjectID = sr.subjectID
        left join pseudosubjects_sbs psbs on psbs.sbsID = sr.sbsID
        where sr.semId not in (select semID from batches where batchID = bat.batchID) and bat.batchHide=0 AND sr.csID = 0 and staffID = $staffRequest->staffId $sql_dept $sql_batch $sql_sem $sql_sub GROUP BY IFNULL(psbs.pseudosubjectID, sr.sbsID) limit $staffRequest->startIndex$staffRequest->endIndex ";
//         $sql_count = "
//                 select sr.sbsID
//                 from sbs_relation sr 
//                 inner join batches bat on sr.batchID = bat.batchID 
//                 left join subjects sub on sub.subjectID = sr.subjectID
//                 left join pseudosubjects_sbs psbs on psbs.sbsID = sr.sbsID
//                 where sr.semId not in (select semID from batches where batchID = bat.batchID) and bat.batchHide=0 AND sr.csID = 0 and staffID = $staffRequest->staffId $sql_dept $sql_batch $sql_sem $sql_sub GROUP BY IFNULL(psbs.pseudosubjectID, sr.sbsID)";
        try {
            $showPseudoSubbatches = CommonService::getInstance()->getSettings(SettingsConstents::PSEUDO_SUBJECT_NBA_SETTINGS, SettingsConstents::SHOW_PSEUDO_SUBBATCHES);
            $subjectDetails->subjects = $this->executeQueryForList($sql);
            if($showPseudoSubbatches){
                foreach ($subjectDetails->subjects as $subject) {
                    if($subject->isPseudosubject){
                        $sql="SELECT 
                        sr.sbsID,
                        sr.subjectID,
                        subjectName,
                        subjectDesc,
                        bat.batchID as batchID,
                        batchName as batchName,
                        sr.semID,
                        semName as semName,
                        IF(psbs.pseudosubjectID IS NULL, 0, 1) AS isPseudosubject,
                        psbs.pseudosubjectID,
                        1 AS isPseudosubjectBatch,
                        psbs.sbsID AS psSbsID
                    FROM
                        pseudosubjects_sbs psbs
                            INNER JOIN
                        sbs_relation sr ON psbs.sbsID = sr.sbsID
                            INNER JOIN
                        batches bat ON sr.batchID = bat.batchID
                            INNER JOIN
                        semesters se ON se.semID = sr.semID
                            INNER JOIN
                        subjects sub ON sub.subjectID = sr.subjectID
                    WHERE
                        psbs.pseudosubjectID = $subject->pseudosubjectID and staffID = $staffRequest->staffId";
                        $subjects = $this->executeQueryForList($sql);
                        $subjectDetails->subjects=array_merge($subjectDetails->subjects,$subjects);
                    }
                }
            }
//             $subjectDetails->totalRecords = $this->executeQueryForObject($sql_count);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $subjectDetails;
    }
    /**
     * Get all previous departments assigned to the staff
     *
     * @param int $staffId
     * @return object|array|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffAssignedPreviousDepartments($staffId)
    {
        $staffId = $this->realEscapeString($staffId);
        $sql = "select distinct dp.deptID, dp.deptName from sbs_relation sr inner join batches bat on sr.batchID = bat.batchID left join department dp on dp.deptID = bat.deptID left join subjects sub on sub.subjectID = sr.subjectID  where sr.semId not in (select semID from batches where batchID = bat.batchID)  and bat.batchHide=0 AND sr.csID = 0 and staffID = $staffId";
        try {
            $deptDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $deptDetails;
    }
    /**
     *
     * @param int $subjectId
     * @param int $batchId
     * @param int $staffId
     * @return object|array|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffDetailsBySubjectId($subjectId, $batchId, $staffId)
    {
        $staffId = $this->realEscapeString($staffId);
        $batchId = $this->realEscapeString($batchId);
        $subjectId = $this->realEscapeString($subjectId);
        $sql = "select sbsID, sr.staffID, batchID, subjectID, semID from sbs_relation sr inner join staffaccounts sa on sr.staffID = sa.staffID where subjectID = $subjectId and sr.staffID = $staffId and batchID = $batchId";
        try {
            $staffDetails = $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /**
     *
     * @param WorkLogPreferenceRequest $workLogPreferenceRequest
     * @return \com\linways\core\ams\professional\response\workLogPreferenceResponse
     * @throws ProfessionalException
     */
    public function getWorkLogEditPreference($workLogPreferenceRequest)
    {
        $workLogPreferenceRequest = $this->realEscapeObject($workLogPreferenceRequest);
        $workLogPreferenceResponse = new WorkLogPreferenceResponse ();
        $sqlCount = "select count(sa.staffID) as totalRecords from staffaccounts sa LEFT JOIN workLogEditPreference wp ON wp.staffId=sa.staffID WHERE sa.isPrincipal=0 AND sa.isResigned=0 ";
        $sql = "select sa.staffID, sa.staffName, dept.deptName, if(wp.staffId,1,0) as canEdit from staffaccounts sa LEFT JOIN department dept ON dept.deptID=sa.deptID LEFT JOIN workLogEditPreference wp ON wp.staffId=sa.staffID WHERE sa.isPrincipal=0 AND sa.isResigned=0 ";
        if ($workLogPreferenceRequest->deptId) {
            $cond = "AND sa.deptID=$workLogPreferenceRequest->deptId ";
        }
        if ($workLogPreferenceRequest->staffName) {
            $cond .= "AND sa.staffName like '%$workLogPreferenceRequest->staffName%' ";
        }
        $sqlCount .= $cond;
        $sql .= $cond;
        if ($workLogPreferenceRequest->sortBy) {
            $sql .= "ORDER BY $workLogPreferenceRequest->sortBy $workLogPreferenceRequest->sortOrder ";
        }
        if (!$workLogPreferenceRequest->isExport) {
            $sql .= "LIMIT $workLogPreferenceRequest->startIndex$workLogPreferenceRequest->endIndex";
        }
        try {
            $workLogPreferenceResponse->totalRecords = $this->executeQueryForObject($sqlCount)->totalRecords;
            $workLogPreferenceResponse->staffList = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $workLogPreferenceResponse;
    }
    /**
     * add worklog edit preference
     *
     * @param WorkLogEditPreference $workLogEditPreference
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function addWorkLogEditPreference($workLogEditPreference)
    {
        $workLogEditPreference = $this->realEscapeObject($workLogEditPreference);
        $sql = "INSERT INTO workLogEditPreference (staffId, createdBy, createdDate, updatedBy, updatedDate) VALUES ($workLogEditPreference->staffId$workLogEditPreference->createdBy, utc_timestamp(), $workLogEditPreference->updatedBy, utc_timestamp())";
        try {
            return $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * delete staff from work log edit preference
     *
     * @param int $staffId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function deleteWorkLogEditPreference($staffId)
    {
        $staffId = $this->realEscapeString($staffId);
        $sql = "DELETE FROM workLogEditPreference WHERE staffId=$staffId";
        try {
            return $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * check if staff can edit worklog
     *
     * @param int $staffId
     * @return boolean
     * @throws ProfessionalException
     */
    public function canStaffEditWorkLogPreference($staffId)
    {
        $staffId = $this->realEscapeString($staffId);
        $canEdit = false;
        $sql = "SELECT id FROM workLogEditPreference WHERE staffId=$staffId";
        try {
            $id = $this->executeQueryForObject($sql)->id;
            if ($id) {
                $canEdit = true;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $canEdit;
    }
    /**
     *
     * @param unknown $unMarkedStaffRequest
     * @return array this service is copied from ams-professional-web.
     * @throws ProfessionalException
     */
    public function searchUnMarkedFaculties($unMarkedStaffRequest)
    {
        $staffs = new SearchUnMarkedStaffResponse ();
        if (!$unMarkedStaffRequest == NULL) {
            $sql_staff_limit = "SELECT
                distinct sr.staffID
            FROM
                sbs_relation sr
                    INNER JOIN
                staffaccounts sa ON sa.staffID = sr.staffID
                    INNER JOIN
                batch_timetable bt ON bt.sbsID =sr.sbsID
                    INNER JOIN
                subjects s ON s.subjectID = sr.subjectID
                    INNER JOIN
                batches bs ON bs.batchID = bt.batchID
                left join attendance_confirm ac on ac.hour =bt.hourID AND ac.batchID=bs.batchID AND bt.timetableDate = ac.attendanceDate
                WHERE ac.batchID is null ";
            $sql_staff_count = "SELECT
                count(distinct sr.staffID) AS totalRecord
            FROM
                sbs_relation sr
                    INNER JOIN
                staffaccounts sa ON sa.staffID = sr.staffID
                    INNER JOIN
                batch_timetable bt ON bt.sbsID =sr.sbsID
                    INNER JOIN
                subjects s ON s.subjectID = sr.subjectID
                    INNER JOIN
                batches bs ON bs.batchID = bt.batchID
                left join attendance_confirm ac on ac.hour =bt.hourID AND ac.batchID=bs.batchID AND bt.timetableDate = ac.attendanceDate
                WHERE ac.batchID is null ";
            $sql = "SELECT
                sa.staffID, sa.staffName, s.subjectID, s.subjectName, bs.batchID, bs.batchName, bt.timetableDate, bt.hourID, sr.sbsID, sr.semID
            FROM
                sbs_relation sr
                    INNER JOIN
                staffaccounts sa ON sa.staffID = sr.staffID
                    INNER JOIN
                batch_timetable bt ON bt.sbsID =sr.sbsID
                    INNER JOIN
                subjects s ON s.subjectID = sr.subjectID
                    INNER JOIN
                batches bs ON bs.batchID = bt.batchID
                    LEFT JOIN
                suspended_hours sh ON sh.batchID = bt.batchID
                    AND sh.hour = bt.hourID
                    AND sh.suspendedDate = bt.timetableDate
                    AND sh.semID = bt.semID
                   LEFT JOIN
                lms_calender lc ON (lc.batchID = bt.batchID
                    OR lc.batchID = 0) AND lc.flag IN (1,3)
                    AND bt.timetableDate BETWEEN FROM_UNIXTIME(lc.timeStart, '%Y-%m-%d') AND FROM_UNIXTIME(lc.timeEnd, '%Y-%m-%d')
                LEFT JOIN attendance_confirm ac on ac.hour =bt.hourID AND ac.batchID=bs.batchID AND bt.timetableDate = ac.attendanceDate
                WHERE ac.batchID is null AND lc.eventID IS NULL and sh.hour IS NULL ";
            $sql_cond = "";
            if ($unMarkedStaffRequest->deptId) {
                $sql_cond .= " AND bs.deptID =$unMarkedStaffRequest->deptId ";
            }
            if ($unMarkedStaffRequest->staffID) {
                $sql_cond .= " AND sa.staffID =$unMarkedStaffRequest->staffID ";
            }
            if ($unMarkedStaffRequest->batchId) {
                $sql_cond .= " AND sr.batchID =$unMarkedStaffRequest->batchId ";
            }
            if ($unMarkedStaffRequest->semId) {
                $sql_cond .= " AND sr.semID =$unMarkedStaffRequest->semId ";
            }
            if ($unMarkedStaffRequest->sbsId) {
                $sql_cond .= " AND sr.sbsID =$unMarkedStaffRequest->sbsId ";
            }
            if (!$unMarkedStaffRequest->toDate) {
                $sql_cond .= " AND bt.timetableDate ='" . date('Y-m-d', strtotime($unMarkedStaffRequest->fromDate)) . "' ";
            } else {
                $sql_cond .= " AND bt.timetableDate BETWEEN '" . date('Y-m-d', strtotime($unMarkedStaffRequest->fromDate)) . "' AND '" . date('Y-m-d', strtotime($unMarkedStaffRequest->toDate)) . "' ";
            }
            $sql_staff_count .= $sql_cond;
            $staffs->totalRecords = $this->executeQueryForObject($sql_staff_count)->totalRecord;
            if ($unMarkedStaffRequest->export) {
                $unMarkedStaffRequest->endIndex = $staffs->totalRecords;
            }
            $sql_staff_limit .= $sql_cond . " order by sa.staffName LIMIT $unMarkedStaffRequest->startIndex,$unMarkedStaffRequest->endIndex";
            $staffIdRes = $this->executeQueryForList($sql_staff_limit);
            foreach ($staffIdRes as $staffIdItem) {
                $staffIds [] = $staffIdItem->staffID;
            }
            if ($staffIds) {
                $sql .= $sql_cond . " AND sa.staffID IN (" . implode(',', $staffIds) . ") order by sa.staffName, bs.batchName, bt.timetableDate, bt.hourID";
                try {
                    $unMarkedstaffs = $this->executeQueryForList($sql);
                    $unMarkedStaff = [];
                    if ($staffs != NULL && count($staffs) > 0) {
                        foreach ($unMarkedstaffs as $staff) {
                            if (isset ($unMarkedStaff [$staff->staffID]) && $unMarkedStaff [$staff->staffID]) {
                                if (isset ($unMarkedStaff [$staff->staffID]->subjectDetails [$staff->sbsID]) && $unMarkedStaff [$staff->staffID]->subjectDetails [$staff->sbsID]) {
                                    $unMarkedStaff [$staff->staffID]->subjectDetails [$staff->sbsID]->count++;
                                    $unMarkedStaff [$staff->staffID]->subjectDetails [$staff->sbsID]->hours [$staff->timetableDate] [] = $staff->hourID;
                                } else {
                                    $subjectDetails = new \stdClass ();
                                    $subjectDetails->sbsId = $staff->sbsID;
                                    $subjectDetails->subjectName = $staff->subjectName;
                                    $subjectDetails->subjectId = $staff->subjectID;
                                    $subjectDetails->batchId = $staff->batchID;
                                    $subjectDetails->semId = $staff->semID;
                                    $subjectDetails->batchName = $staff->batchName;
                                    $subjectDetails->count = 1;
                                    $subjectDetails->hours [$staff->timetableDate] [] = $staff->hourID;
                                    $unMarkedStaff [$staff->staffID]->subjectDetails [$staff->sbsID] = $subjectDetails;
                                }
                            } else {
                                $staffDetails = new \stdClass ();
                                $staffDetails->staffId = $staff->staffID;
                                $staffDetails->name = $staff->staffName;
                                $staffDetails->subjectDetails = [];
                                $subjectDetails = new \stdClass ();
                                $subjectDetails->sbsId = $staff->sbsID;
                                $subjectDetails->subjectId = $staff->subjectID;
                                $subjectDetails->batchId = $staff->batchID;
                                $subjectDetails->semId = $staff->semID;
                                $subjectDetails->subjectName = $staff->subjectName;
                                $subjectDetails->batchName = $staff->batchName;
                                $subjectDetails->count = 1;
                                $subjectDetails->hours [$staff->timetableDate] [] = $staff->hourID;
                                $staffDetails->subjectDetails [$staff->sbsID] = $subjectDetails;
                                $unMarkedStaff [$staff->staffID] = $staffDetails;
                            }
                        }
                    }
                    $staffs->staffs = $unMarkedStaff;
                } catch (\Exception $e) {
                    throw new ProfessionalException (ProfessionalException::QUERY_EXECUTION_FAILED, $e->getMessage());
                }
            }
        }
        return $staffs->staffs;
    }
    /**
     * Check if student suggestion mandatory
     * in faculty evaluation
     *
     * @param int $evaluationTypeId
     * @return boolean
     * @throws ProfessionalException
     */
    public function isFacultyEvalStudentSuggestionMandatory($evaluationTypeId)
    {
        $evaluationTypeId = $this->realEscapeString($evaluationTypeId);
        $sql = "SELECT student_suggestion FROM staffeval_type WHERE eval_typeID = $evaluationTypeId";
        try {
            $suggestion = $this->executeQueryForObject($sql)->student_suggestion;
            if ($suggestion == 1) {
                return true;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return false;
    }
    /**
     * Create or Update StaffProfile Info
     *
     * @param StaffProfileInfo $staffProfileInfo
     * @return MySqlResult
     * @throws ProfessionalException
     */
    public function upsertStaffProfileInfo($staffProfileInfo)
    {
        $staffProfileInfo = $this->realEscapeObject($staffProfileInfo);
        if ($staffProfileInfo->id) {
            if ($staffProfileInfo->sectionInfo) {
                $update_sectionInfo = " sectionInfo = '$staffProfileInfo->sectionInfo',";
            }
            if ($staffProfileInfo->sectionName) {
                $update_sectionName = " sectionName = '$staffProfileInfo->sectionName',";
            }
            $sql = "UPDATE staff_profile_info SET $update_sectionName $update_sectionInfo staffId = $staffProfileInfo->staffId, updatedBy = $staffProfileInfo->updatedBy, updatedDate = UTC_TIMESTAMP() WHERE id = $staffProfileInfo->id";
        } else {
            $sql = "INSERT INTO staff_profile_info ( sectionName, sectionInfo, sectionOrder, staffId, createdBy, createdDate, updatedBy, updatedDate) VALUES ('$staffProfileInfo->sectionName', '$staffProfileInfo->sectionInfo', $staffProfileInfo->sectionOrder$staffProfileInfo->staffId$staffProfileInfo->createdBy, UTC_TIMESTAMP(), $staffProfileInfo->updatedBy, UTC_TIMESTAMP())";
        }
        try {
            return $this->executeQuery($sql, true);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Delete staff profile info
     *
     * @param int $id
     * @return MySqlResult
     * @throws ProfessionalException
     */
    public function deleteStaffProfileInfo($id)
    {
        $id = $this->realEscapeString($id);
        $sql = "DELETE FROM staff_profile_info WHERE id = $id";
        try {
            return $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Get staff profile section details by staffId
     *
     * @param int $staffId
     * @return unknown
     * @throws ProfessionalException
     */
    public function getStaffProfileSectionInfoByStaffId($staffId)
    {
        $staffId = $this->realEscapeString($staffId);
        $sql = "SELECT id, sectionName, sectionInfo, sectionOrder, staffName FROM staff_profile_info pi INNER JOIN staffaccounts sa ON pi.staffId = sa.staffID WHERE pi.staffId = $staffId ORDER By sectionOrder";
        try {
            $staffProfileDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffProfileDetails;
    }
    /**
     * Get staff profile info by sectionId
     *
     * @param int $sectionId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffProfileInfoBySectionId($sectionId)
    {
        $sectionId = $this->realEscapeString($sectionId);
        $sql = "SELECT id, sectionName, sectionInfo, sectionOrder FROM staff_profile_info WHERE id = $sectionId";
        try {
            $staffSectionInfo = $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffSectionInfo;
    }
    /**
     * Get staff Pubilc profile details
     *
     * @param int $staffId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffPublicProfileDetails($staffId)
    {
        $staffId = $this->realEscapeString($staffId);
        $sql = "select sa.staffID,sa.dateOfJoining,sa.lectureType,l1.typeName, staffAccount, staffName, staffEmail, staffGender, staffBirthday, staffPhone, sa.deptID as deptId, dep.deptName, departmentDesc, myImage, bloodGroup, academicDesignationID as staffDesigId, sd.name as staffDesigName, sd.description as staffDesigDesc,pi.id, pi.sectionName, pi.sectionInfo, pi.sectionOrder from staffaccounts sa inner JOIN staff_profile_info pi ON pi.staffId = sa.staffID inner join department dep on dep.deptID = sa.deptID left join staff_designation sd ON sd.id = sa.academicDesignationID left join lectureTypes l1 ON l1.id=sa.lectureType where isResigned = 0 and pi.staffId = $staffId ORDER By sectionOrder";
        try {
            $staffPublicProfileDetails = $this->executeQueryForObject($sql, false, $this->mapper [StaffServiceMapper::GET_STAFF_PUBLIC_PROFILE]);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffPublicProfileDetails;
    }
    /**
     * Get staff Pubilc profile details
     *
     * @param int $staffId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffPublicProfileViewDetails($staffId)
    {
        $staffId = $this->realEscapeString($staffId);
        $sql = "SELECT 
        sa.staffName,
        sa.deptID as departmentId,
        sa.myImage as photo,
        sd.name as designation,
        sa.staffEmail,
        dep.departmentDesc as departmentName,
        sa.fieldOfSpecialization as specialization,
        sq.qualificationName as qualification
    FROM
        staffaccounts sa
            LEFT JOIN
        staffqualification sq ON sq.qualificationID = sa.qualificationID
            LEFT JOIN
        department dep ON dep.deptID = sa.deptID
            LEFT JOIN
        staff_designation sd ON sd.id = sa.academicDesignationID
    WHERE
        isResigned = 0 and sa.staffId = $staffId
    ORDER BY - list_order DESC , FIELD(isPrincipal,9,8,5,4,1,2,6,3,7,0) , isFaculty ASC , isHOD ASC
    LIMIT 0 , 50;";
        try {
            $staffDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /**
     * Search staff by staffName
     *
     * @param string $staffName
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function searchStaffByStaffName($staffName)
    {
        $staffName = $this->realEscapeString($staffName);
        $sql = "SELECT staffID, staffAccount, staffName, staffEmail, staffGender, staffBirthday, staffPhone FROM staffaccounts WHERE staffName like '$staffName'";
        try {
            $staffDetails = $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /*
     * Check if the mail id belongs to any staff
     * @param string $emailId
     * @throws ProfessionalException
     * @return boolean
     */
    public function getStaffIdByMailId($emailId)
    {
        $emailId = trim($this->realEscapeString($emailId));
        $sql = "SELECT staffID, staffName FROM staffaccounts WHERE staffEmail = '$emailId'";
        try {
            $staffDetails = $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /**
     * Update staff password
     *
     * @param int $staffId
     * @param string $password
     * @return MySqlResult
     * @throws ProfessionalException
     */
    public function updateStaffPassword($staffId, $password)
    {
        $staffId = $this->realEscapeString($staffId);
        $password = $this->realEscapeString($password);
        $sql = "UPDATE staffaccounts SET staffPassword = '" . md5($password) . "' WHERE staffID = $staffId";
        try {
            return $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * get staff details
     *
     * @param GetStaffRequest $staffRequest
     * @return \com\linways\core\ams\professional\response\GetStaffResponse
     * @throws ProfessionalException
     */
    public function getStaffDetailsByDeptId($staffRequest)
    {
        $staffRequest = $this->realEscapeObject($staffRequest);
        $staffResponse = new GetStaffResponse ();
        if ($staffRequest->deptId != 0) {
            $cond = " and sa.deptID = $staffRequest->deptId";
        }
        $sql = "select sa.staffID, staffAccount, staffName, staffEmail, staffGender, staffBirthday, staffPhone, sa.deptID as deptId, dep.deptName, departmentDesc, myImage, bloodGroup, academicDesignationID as staffDesigId, sd.name as staffDesigName, sd.description as staffDesigDesc from staffaccounts sa inner join department dep on dep.deptID = sa.deptID left join staff_designation sd ON sd.id = sa.academicDesignationID where isResigned = 0 $cond ORDER BY -list_order DESC, FIELD (isPrincipal, 9, 8, 5, 4, 1, 2,6, 3, 7, 0), isFaculty ASC, isHOD ASC";
        $sql_count = "select count(staffID) as count from (select sa.staffID from staffaccounts sa inner join department dep on dep.deptID = sa.deptID left join staff_designation sd ON sd.id = sa.academicDesignationID where isResigned = 0 $cond) as records";
        $sql .= " limit $staffRequest->startIndex$staffRequest->endIndex";
        try {
            $staffResponse->staffs = $this->executeQueryForList($sql, $this->mapper [StaffServiceMapper::GET_STAFF_DETAILS_BY_ID]);
            $staffResponse->totalRecords = $this->executeQueryForObject($sql_count)->count;
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffResponse;
    }
    /**
     * get tutor details by staffId
     *
     * @param int $staffId
     * @throws ProfessionalException
     */
    public function getTutorDetailsByStaffId($staffId)
    {
        $staffId = $this->realEscapeString($staffId);
        $sql = "select bt.staffID, staffName ,bt.batchID,batchName, bt.semID, sa.deptID from batch_tutor bt inner join batches ba on ba.batchID = bt.batchID inner join staffaccounts sa on sa.staffID = bt.staffID where bt.staffID = $staffId";
        try {
            $tutorDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $tutorDetails;
    }
    /**
     * Get staff details for hour swap
     *
     * @param int $batchId
     * @param int $semId
     * @param string $timetableDate
     * @param int $hourId
     * @return object|array|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffsDetailsForHourSwap($batchId, $semId, $timetableDate, $hourId)
    {
        $sql = "SELECT sa.staffID,sa.staffName,sub.subjectID,sub.subjectName, sr.sbsID,ba.batchID, ba.batchName,ba.semID,IF(tmCustom.staffID IS NULL,1,0) 
             AS available, sa.myImage, sa.staffGender FROM
    sbs_relation sr 
    INNER JOIN batches ba ON ba.batchID = sr.batchID AND sr.semID = ba.semID AND ba.batchID = $batchId AND sr.semID = $semId
    INNER JOIN staffaccounts sa ON sa.staffID = sr.staffID
    INNER JOIN subjects sub ON sr.subjectID = sub.subjectID
    LEFT JOIN (SELECT 
    DISTINCT sa.staffID
FROM
    sbs_relation sr 
    INNER JOIN batches ba ON ba.batchID = sr.batchID AND sr.semID = ba.semID AND ba.batchID = $batchId AND sr.semID = $semId
    INNER JOIN staffaccounts sa ON sa.staffID = sr.staffID
    INNER JOIN subjects sub ON sr.subjectID = sub.subjectID
    left JOIN sbs_relation sbs ON sbs.staffID = sa.staffID
    INNER JOIN batch_timetable bt ON bt.sbsID = sbs.sbsID AND timetableDate = '$timetableDate' AND hourID = $hourId AND bt.sbsID is not null) tmCustom on tmCustom.staffID =sr.staffID";
        try {
            $staffDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /**
     * Create staff monthly report
     * @param StaffMonthlyReport $monthlyReport
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function createStaffMonthlyReport($monthlyReport)
    {
        $monthlyReport = $this->realEscapeObject($monthlyReport);
        $sql = "INSERT INTO staffMonthlyReport (name, fromDate, toDate, sbsId, createdBy, createdDate, updatedBy, updatedDate) VALUE ('$monthlyReport->name', '$monthlyReport->fromDate', '$monthlyReport->toDate', $monthlyReport->sbsId$monthlyReport->createdBy, UTC_TIMESTAMP(), $monthlyReport->updatedBy, UTC_TIMESTAMP())";
        try {
            $monthlyReport->id = $this->executeQueryForObject($sql, true);
            $this->createStaffMonthlyRepParticulars($monthlyReport);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $monthlyReport->id;
    }
    /**
     *
     * create staff monthly report particulars to be shown in the report
     * @param int $repId
     * @param array $particulars
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function createStaffMonthlyRepParticulars($monthlyReport)
    {
        $monthlyReport = $this->realEscapeObject($monthlyReport);
        $particulars = $monthlyReport->particulars;
        foreach ($particulars as $particular)
            $insertVal .= "($monthlyReport->id, '$particular', $monthlyReport->createdBy, UTC_TIMESTAMP(), $monthlyReport->updatedBy, UTC_TIMESTAMP()), ";
        $insertVal = rtrim($insertVal, ", ");
        $sql = "INSERT INTO staffMonthlyReportParticulars (reportId, particular, createdBy, createdDate, updatedBy, updatedDate) VALUES $insertVal";
        try {
            return $this->executeQueryForObject($sql, true);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Update StaffMonthly report
     * @param StaffMonthlyReport $monthlyReport
     * @return MySqlResult
     * @throws ProfessionalException
     */
    public function updateStaffMonthlyReport($monthlyReport)
    {
        $monthlyReport = $this->realEscapeObject($monthlyReport);
        $sql = "UPDATE staffMonthlyReport SET name = '$monthlyReport->name', fromDate = '$monthlyReport->fromDate', toDate = '$monthlyReport->toDate', sbsId = $monthlyReport->sbsId, updatedBy = $monthlyReport->updatedBy, updatedDate = '$monthlyReport->updatedDate' WHERE id = $monthlyReport->id";
        try {
            $this->executeQuery($sql);
            $this->deleteStaffMonthlyRepParticularsByRepId($monthlyReport->id);
            $this->createStaffMonthlyRepParticulars($monthlyReport);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return true;
    }
    /**
     * Delete  staff monthly report particulars
     * @param int $repId
     * @return MySqlResult
     * @throws ProfessionalException
     */
    public function deleteStaffMonthlyRepParticularsByRepId($repId)
    {
        $repId = $this->realEscapeString($repId);
        $sql = "DELETE FROM staffMonthlyReportParticulars WHERE reportId = $repId";
        try {
            return $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Create staff monthly report details
     * @param StaffMonthlyReportDetails $reportDetails
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function createStaffMonthlyReportDetails($reportDetails)
    {
        $reportDetails = $this->realEscapeObject($reportDetails);
        $sql = "INSERT INTO staffMonthlyReportDetails (reportId, name, value, createdBy, createdDate, updatedBy, updatedDate) VALUE ($reportDetails->reportId, '$reportDetails->name', '$reportDetails->value', $reportDetails->createdBy, '$reportDetails->createdDate', $reportDetails->updatedBy, '$reportDetails->updatedDate')";
        try {
            return $this->executeQueryForObject($sql, true);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Get all reports created for an sbsID
     * @param int $sbsId
     * @return object|array|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffMonReportsBySbsId($sbsId)
    {
        $sbsId = $this->realEscapeObject($sbsId);
        $sql = "select * from staffMonthlyReport where sbsId = $sbsId";
        try {
            return $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Get Staff monthly report details
     * @param int $reptId
     * @return object|array|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffMonthlyReportDetailsByRepId($reptId)
    {
        $reptId = $this->realEscapeString($reptId);
        $sql = "select * from staffMonthlyReportDetails where reportId = $reptId";
        try {
            $reportDetails = $this->executeQueryForList($sql);
            foreach ($reportDetails as $reportDetail) {
                $reportFieldValue[$reportDetail->name] = $reportDetail->value;
            }
            return $reportFieldValue;
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Get staff monthly report by reportId
     * @param int $reptId
     * @return object|array|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffMonthlyReportByReportId($reptId)
    {
        $reptId = $this->realEscapeString($reptId);
        $sql = "SELECT sr.id, name, fromDate, toDate, sbsId, sp.id as particularId, reportId, particular FROM staffMonthlyReport sr inner join staffMonthlyReportParticulars sp on sr.id = sp.reportId where reportId = $reptId";
        try {
            return $this->executeQueryForObject($sql, false, $this->mapper[StaffServiceMapper::GET_STAFF_MONTHLY_REPORT_DETAILS]);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Delete staffmonthly report details
     * @param int $reptId
     * @return MySqlResult
     * @throws ProfessionalException
     */
    public function deleteStaffMonthlyReportDetails($reptId)
    {
        $reptId = $this->realEscapeString($reptId);
        $sql = "DELETE FROM staffMonthlyReportDetails WHERE reportId = $reptId";
        try {
            return $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Delete staffmonthly report
     * @param int $reptId
     * @return MySqlResult
     * @throws ProfessionalException
     */
    public function deleteStaffMonthlyReport($reptId)
    {
        $reptId = $this->realEscapeString($reptId);
        $sql = "DELETE FROM staffMonthlyReport where id = $reptId";
        try {
            return $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Get all monthly reports of a staff
     * @param int $staffId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function getAllMonthlyRepOfAStaff($staffId, $fromday = null, $endday = null, $subjectId = null, $deptID = null, $staffIDs = null,$myId = null)
    {
        $condition = "";
        if ($fromday && $endday) {
            $condition = " AND ((smr.fromDate BETWEEN '$fromday' AND '$endday') OR (smr.toDate BETWEEN '$fromday' AND '$endday')) ";
        }
        if ($subjectId) {
            $condition .= " AND sr.subjectID = '$subjectId";
        }
        if ($deptID) {
            if((int)$myId){
                $staffSql = "select group_concat(hp.batchIDs) as batches from staffaccounts st
                inner join batches bat on bat.deptID != st.deptID 
                inner join hodPrivileges hp on FIND_IN_SET(bat.batchID,hp.batchIDs) and st.staffID = hp.staffID
                where st.staffID = '".(int)$myId."' and st.isHOD >= 1 group by st.staffID;";
                $batchIDs = $this->executeQueryForObject($staffSql)->batches;
            }
            if(!empty($batchIDs)){
                $condition .= " AND (b.deptID = '$deptID' OR b.batchId in (".$batchIDs.") OR st.deptID = '$deptID' ) ";
            }else{
                $condition .= " AND (b.deptID = '$deptID' OR st.deptID = '$deptID') ";
            }
        }
        if ($staffId) {
            $condition .= " AND sr.staffID = '$staffId";
        }
        if ($staffIDs) {
            $condition .= " AND sr.staffID in ($staffIDs";
        }
        $staffId = (int)$this->realEscapeString($staffId);
        $sql = "SELECT dept.deptID,dept.deptName,dept.departmentDesc,smr.id, smr.name, smr.fromDate, smr.toDate, smr.sbsId, sp.id AS particularId, sp.reportId,sp.particular, sr.subjectID, sr.batchID, sr.staffID,st.staffName,st.staffAccount,mrd.id as report_details_id,mrd.name as report_details_name ,mrd.value as report_details_value
            FROM staffMonthlyReport smr 
            INNER JOIN staffMonthlyReportParticulars sp ON smr.id = sp.reportId 
            INNER JOIN sbs_relation sr ON smr.sbsID = sr.sbsID
            INNER JOIN staffaccounts st ON st.staffID = sr.staffID
            INNER JOIN batches b ON sr.batchID = b.batchID AND b.semID = sr.semID
            INNER JOIN department dept ON dept.deptID = b.deptID
            LEFT JOIN staffMonthlyReportDetails mrd ON mrd.reportId = smr.id
            WHERE b.isPassOut = 0 AND dept.deptShow = 1 $condition
            ORDER BY dept.deptID,sr.subjectID,fromDate;";
        try {
            return $this->executeQueryForList($sql, $this->mapper[StaffServiceMapper::GET_STAFF_MONTHLY_REPORT_DETAILS_STAFF]);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Get staff monthly report by reportId
     * @param array $reptId
     * @return object|array|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffMonthlyReportByReportIds($reptIds)
    {
        $reptIds = $this->realEscapeArray($reptIds);
        $sql = "SELECT sr.id, name, fromDate, toDate, sbsId, sp.id as particularId, reportId, particular FROM staffMonthlyReport sr inner join staffMonthlyReportParticulars sp on sr.id = sp.reportId where reportId in (" . implode(",", $reptIds) . ")";
        try {
            return $this->executeQueryForList($sql, $this->mapper[StaffServiceMapper::GET_STAFF_MONTHLY_REPORT_DETAILS]);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * get staffs assigned to as pseudosubject
     * @param int $pseudosubID
     * @return object|array|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffDetailsAssignedToPseudoSub($pseudosubId)
    {
        $pseudosubId = $this->realEscapeString($pseudosubId);
        $sql = "SELECT pss.pseudosubjectID, sbsr.staffID,bth.batchID,batchName, sbsr.semID, psbs.sbsID,sbsr.subjectID, pss.subjectName, sa.staffName FROM sbs_relation sbsr inner join batches bth on sbsr.batchID=bth.batchID inner join pseudosubjects_sbs psbs on sbsr.sbsID=psbs.sbsID  inner join pseudosubjects pss on psbs.pseudosubjectID=pss.pseudosubjectID inner join staffaccounts sa on sa.staffID = sbsr.staffID WHERE pss.pseudosubjectID = $pseudosubId order by bth.batchID";
        try {
            return $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Create quick report privilege to staff
     * @param int $staffId
     * @param array $reports
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function createQuickReportPrivilegeToStaff($staffId, $reports)
    {
        $staffId = $this->realEscapeString($staffId);
        $reports = $this->realEscapeArray($reports);
        foreach ($reports as $report) {
            $values[] = "(" . $staffId . ",'" . $report . "')";
        }
        $sqlValues = implode(",", $values);
        $sql = "INSERT INTO quick_reports_staff_authorization (staffId, quickReportName) VALUES $sqlValues";
        try {
            return $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Delete quick report privilege to staff
     * @param int $staffId
     * @param string $report
     * @return unknown
     * @throws ProfessionalException
     */
    public function deleteQuickReportPrivilegeToStaff($staffId, $report)
    {
        $staffId = $this->realEscapeString($staffId);
        $report = $this->realEscapeString($report);
        $sql = "DELETE FROM quick_reports_staff_authorization WHERE staffId = " . $staffId . " AND quickReportName = '" . $report . "'";
        try {
            return $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Method for getting all quick report authorisation by staffId.
     * @param number $staffId
     * @return MySqlResult
     * @throws ProfessionalException
     * @author gadheyan
     */
    public function getQuickReportAuthorisationByStaffId($staffId)
    {
        $sql = "";
        $quickReportAuthorisationList = null;
        $staffId = $this->realEscapeString($staffId);
        $sql = "SELECT * FROM quick_reports_staff_authorization WHERE staffId =  $staffId";
        try {
            $quickReportAuthorisationList = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $quickReportAuthorisationList;
    }
    /**
     * Method for getting staffName, subjectName from sbs_relation table
     * @input $semId,$batchIds
     * @author Ranjith Balachandran @modified by Kishan Suresh
     */
    public function getStaffDetailsFromSbsRelation($semId, $batchIds, $evalType, $subjectCategories = null)
    {
        $staffDetails = [];
        $evalType = strtoupper($evalType);
        $semId = $this->realEscapeString($semId);
        if (gettype($batchIds) == "array") {
            $batchIds = implode(',', $batchIds);
        }
        $batchIds = $this->realEscapeString($batchIds);
        $subjectCategories = $this->realEscapeArray($subjectCategories);
        $condition = "";
        if (!empty($subjectCategories)) {
            $condition = " INNER JOIN subject_category sc ON sc.subjectcatID = s.subjectcatID AND sc.subjectcatID IN (" . implode(',', $subjectCategories) . ")";
        }
        try {
            switch ($evalType) {
                case "FACULTY":
                    $sql = 
                    "SELECT 
                        sa.staffID as staffId,sa.staffName as staffName, s.subjectDesc as subjectDesc,s.subjectName as subjectName,b.batchName,sr.sbsID as sbsId,b.batchID as batchId, s.subjectID 
                    FROM staffaccounts sa 
                        INNER JOIN sbs_relation sr ON sa.staffID = sr.staffID 
                        INNER JOIN subjects s ON s.subjectID = sr.subjectID $condition 
                        INNER JOIN batches b ON b.batchID = sr.batchID AND sr.semID = b.semID
                    WHERE sr.batchID IN (" . $batchIds . ") AND sr.semID = $semId 
                    GROUP BY sa.staffID,b.batchID 
                    ORDER BY sa.staffID,b.batchID ASC";
                break;
                case "COURSE":
                    $sql = 
                    "SELECT 
                        sa.staffID as staffId,sa.staffName as staffName, s.subjectDesc as subjectDesc,s.subjectName as subjectName,b.batchName,sr.sbsID as sbsId,b.batchID as batchId, s.subjectID 
                    FROM staffaccounts sa 
                        INNER JOIN sbs_relation sr ON sa.staffID = sr.staffID 
                        INNER JOIN subjects s ON s.subjectID = sr.subjectID $condition 
                        INNER JOIN batches b ON b.batchID = sr.batchID AND sr.semID = b.semID
                    WHERE sr.batchID IN (" . $batchIds . ") AND sr.semID = $semId 
                    GROUP BY sr.subjectID,b.batchID 
                    ORDER BY sr.subjectID,b.batchID ASC";
                break;
                case "BOTH":
                    $sql = 
                    "SELECT 
                        sa.staffID as staffId,sa.staffName as staffName, s.subjectDesc as subjectDesc,s.subjectName as subjectName,b.batchName,sr.sbsID as sbsId,b.batchID as batchId, s.subjectID 
                    FROM staffaccounts sa 
                        INNER JOIN sbs_relation sr ON sa.staffID = sr.staffID 
                        INNER JOIN subjects s ON s.subjectID = sr.subjectID $condition 
                        INNER JOIN batches b ON b.batchID = sr.batchID AND sr.semID = b.semID
                    WHERE sr.batchID IN (" . $batchIds . ") AND sr.semID = $semId 
                    ORDER BY sa.staffID,sr.subjectID,b.batchID ASC";
                break;
            }
            $staffDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /**
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     * @author Vishnu M
     */
    public function getStaffDetailsByDeptIdAndName($deptId, $staffName)
    {
        $semIddeptId = $this->realEscapeString($deptId);
        $staffName = $this->realEscapeString($staffName);
        $staffDetails = [];
        $sql = "SELECT staffID, staffName, staffEmail, isHOD, isPrincipal FROM staffaccounts WHERE isResigned = 0 AND deptID = " . $deptId . " AND staffName LIKE '%" . $staffName . "%'";
        try {
            $staffDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /**
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     * @author gadheyan
     */
    public function getPrincipalDetails()
    {
        $getPrincipalDetails = null;
        $sql = "SELECT sa.staffName as principalName, sa.staffID, sa.staffPhone, sa.staffEmail, sa.salutation from staffaccounts sa  where sa.isPrincipal = 1 AND sa.isResigned = 0";
        try {
            $getPrincipalDetails = $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $getPrincipalDetails;
    }
    /**
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     * @author gadheyan
     */
    public function getErpAdminDetails()
    {
        $getErpAdminDetails = null;
        $sql = "SELECT sa.staffName as erpAdminName,sa.staffID,sa.staffPhone from staffaccounts sa  where sa.isPrincipal = 7";
        try {
            $getErpAdminDetails = $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $getErpAdminDetails;
    }
    /**
     * @param unknown $deptID
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     * @author sujesh
     */
    public function getHodDetailsByDeptID($deptID)
    {
        $sql = "";
        $deptID = $this->realEscapeString($deptID);
        // $staff = "";
        $hod = NULL;
        $sql = "SELECT sa.isHod,sa.staffName,sa.staffID,sa.staffPhone,sa.staffEmail from staffaccounts sa where sa.deptID=$deptID and sa.isHod = 1 and sa.isResigned=0";
        try {
            $hod = $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $hod;
    }
    /**
     * Search Staff
     *
     * @param SearchStaffRequest
     * @return SearchStaffResponse
     */
    public function searchStaffDetails($searchStaffRequest)
    {
        $response = new SearchStaffResponse ();
        $data = NULL;
        $sqlCount = "SELECT count(sa.staffID) as totalRecords";
        $fromCondition = 
            FROM staffaccounts sa
            LEFT JOIN staffQualificationDetails sqd on sqd.staffaccounts_id = sa.staffID 
            LEFT JOIN staffqualification sq ON sqd.staffqualification_id = sq.qualificationID
              LEFT JOIN staff_designation sd ON sd.id IN (sa.academicDesignationID)
            LEFT JOIN religion r ON sa.religionId = r.religionID
            LEFT JOIN department dp ON dp.deptID = sa.deptID WHERE sa.staffID IS NOT NULL AND sa.isResigned = 0";
        $sqlSearch = "
            SELECT sa.staffID as staffId, sa.dateOfJoining as dateOfJoining, sa.staffGender as staffGender, dp.departmentDesc, r.religionName, sa.staffName as staffName, sa.staffAccount as staffAccount, sq.qualificationName, sd.name AS designationName, sa.bloodGroup as bloodGroup, sa.panNumber as panNo, sa.aadharNumber as adharNo, sqd.id as qualificationDetailId, sq.qualificationName as qualificationName, sqd.year, sqd.percentage, sqd.instituteName
                ";
        // From condtion added
        $sqlCount .= $fromCondition;
        $sqlSearch .= $fromCondition;
        if (!empty ($searchStaffRequest)) {
            // QualificationId
            if (!empty ($searchStaffRequest->qualificationId)) {
                $data .= " AND sqd.staffqualification_id IN ($searchStaffRequest->qualificationId)";
            }
            // Date of Joining
            if (!empty ($searchStaffRequest->dateOfJoining)) {
                $data .= " AND sa.dateOfJoining = '$searchStaffRequest->dateOfJoining";
            }
            // DesignationId
            if (!empty ($searchStaffRequest->designationId)) {
                $data .= " AND FIND_IN_SET ($searchStaffRequest->designationId, sa.academicDesignationID) ";
            }
            // Gender
            if (!empty ($searchStaffRequest->gender)) {
                $data .= " AND sa.staffGender = '$searchStaffRequest->gender";
            }
            // Department
            if (!empty ($searchStaffRequest->departmentId)) {
                $data .= " AND sa.deptID = $searchStaffRequest->departmentId";
            }
            // Religion
            if (!empty ($searchStaffRequest->religionId)) {
                $data .= " AND sa.religionId = $searchStaffRequest->religionId";
            }
            // PAN Number
            if (!empty ($searchStaffRequest->panNo)) {
                $data .= " AND sa.panNumber = '$searchStaffRequest->panNo";
            }
            // Adhar Number
            if (!empty ($searchStaffRequest->adharNo)) {
                $data .= " AND sa.aadharNumber = '$searchStaffRequest->adharNo";
            }
            // Blood Group
            if (!empty ($searchStaffRequest->bloodGroup)) {
                $data .= " AND sa.bloodGroup = '$searchStaffRequest->bloodGroup'";
            }
            if (!empty($searchStaffRequest->staffName)) {
                $data .= " AND sa.staffName like '%$searchStaffRequest->staffName%'";
            }
            if (!empty($searchStaffRequest->sortBy)) {
                // Set data to count and select query
                $sqlCount .= $data . " group by sa.staffID ORDER BY sa.$searchStaffRequest->sortBy $searchStaffRequest->sortOrder";
                $data .= " ORDER BY sa.$searchStaffRequest->sortBy $searchStaffRequest->sortOrder";
            } else {
                // Set data to count and select query
                $sqlCount .= $data . " group by sa.staffID ORDER BY sa.isFaculty $searchStaffRequest->sortOrder, sa.isHOD $searchStaffRequest->sortOrder, sa.isPrincipal $searchStaffRequest->sortOrder";
                $data .= " ORDER BY sa.isFaculty $searchStaffRequest->sortOrder, sa.isHOD $searchStaffRequest->sortOrder, sa.isPrincipal $searchStaffRequest->sortOrder";
            }
            // Add Pagination
            if (!$searchStaffRequest->isExport) {
                $pagination = " LIMIT $searchStaffRequest->startIndex,$searchStaffRequest->endIndex";
            }
            $sqlSearch .= $data . $pagination;
            try {
                $response->totalRecords = $this->executeQueryForObject($sqlCount)->totalRecords;
                $response->staffdetails = $this->executeQueryForList($sqlSearch, $this->mapper[StaffServiceMapper::GET_QULIFICTION_DETAILS_OF_STAFF]);
                //$response->staffdetails = $this->executeQueryForList($sqlSearch);
            } catch (\Exception $e) {
                throw new ProfessionalException ($e->getCode(), $e->getMessage());
            }
        } else {
            throw new ProfessionalException (ProfessionalException::INVALID_REQUEST, "SearchStaffRequest is null!");
        }
        return $response;
    }
    /**
     * Method for deleting staff achievement docs
     * @param unknown $achievementIds
     * @param unknown $staffId
     * @throws ProfessionalException
     * @author Vishnu M
     */
    public function deleteStaffAchievementDocs($achievementIds, $staffId)
    {
        $sql = '';
        $achievementIds = $this->realEscapeString($achievementIds);
        $staffId = $this->realEscapeString($staffId);
        try {
            $sql = "DELETE FROM staff_achievements_docs WHERE staffachievements_staffdetails_id IN ($achievementIds) AND staffaccounts_id = $staffId";
            $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Returns staff details by account
     *
     * @param string $staffAccount
     * @return object|array|$objectList[]
     * @throws ProfessionalException
     * @author sanoop
     */
    public function getStaffDetailsByAccount($staffAccount)
    {
        $staffAccount = $this->realEscapeString($staffAccount);
        $sql = "SELECT sa.*,d.deptID as deptId ,d.deptName,d.departmentDesc,hd.designationID as hrDesigId,
                hd.designationName as hrDesigName, hd.designationDesc as hrDesigDesc ,sd.id as staffDesigId,
                sd.name as academicDesignation, sd.description as staffDesigDesc, hs.sectionId, hs.sectionName,
                hs.sectionDesc FROM staffaccounts sa LEFT JOIN department d ON d.deptID = sa.deptID
                LEFT JOIN hr_designations hd ON hd.designationID = sa.designationID LEFT JOIN staff_designation sd
                ON sd.id = sa.academicDesignationID LEFT JOIN hr_sections hs ON hs.sectionID=sa.sectionID
                WHERE sa.staffAccount='$staffAccount'";
        try {
            return $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Method for validating DutyLeavePrivileges object.
     * @param DutyLeavePrivileges $dlp
     * @throws ProfessionalException
     * @author gadheyan
     */
    private function ValidateDutyLeavePrivilegesObject($dlp)
    {
        if ($dlp != NULL) {
            if ($dlp->staffID == NULL) {
                throw new ProfessionalException(ProfessionalException::DUTY_LEAVE_PRIVILEGES_STAFF_ID_NOT_DEFINED, "DUTY_LEAVE_PRIVILEGES_STAFF_ID_NOT_DEFINED");
            }
            if ($dlp->batchID == NULL) {
                throw new ProfessionalException(ProfessionalException::DUTY_LEAVE_PRIVILEGES_BATCH_ID_NOT_DEFINED, "DUTY_LEAVE_PRIVILEGES_BATCH_ID_NOT_DEFINED");
            }
            if ($dlp->deptID == NULL) {
                throw new ProfessionalException(ProfessionalException::DUTY_LEAVE_PRIVILEGES_DEPARTMENT_ID_NOT_DEFINED, "DUTY_LEAVE_PRIVILEGES_DEPARTMENT_ID_NOT_DEFINED");
            }
        } else {
            throw new ProfessionalException(ProfessionalException::DUTY_LEAVE_PRIVILEGES_OBJECT_NOT_DEFINED, "DUTY_LEAVE_PRIVILEGES_OBJECT_NOT_DEFINED");
        }
    }
    /**
     * Method for fetching all duty leave privileges associated with a staff.
     * @param unknown $staffId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     * @author gadheyan
     */
    public function getAllDutyLeavePrivilegeOfStaff($staffId)
    {
        $sql = "";
        $staffObject = null;
        $staffId = $this->realEscapeString($staffId);
        try {
            $sql = "SELECT dlp.*,bat.batchName,bat.semID FROM duty_leave_privileges dlp
                    INNER JOIN batches bat ON dlp.batchID = bat.batchID WHERE dlp.staffID=$staffId";
            $staffObject = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffObject;
    }
    /**
     * Method for granting duty leave privileges to a particular staff for a particular batch
     * under a department
     * @param DutyLeavePrivileges $dlp
     * @author gadheyan
     */
    public function grantDutyLeavePrivileges($dlp)
    {
        $sql = "";
        $lastInsertedId = NULL;
        $this->ValidateDutyLeavePrivilegesObject($dlp);
        $dlp = $this->realEscapeObject($dlp);
        try {
            $sql = "INSERT INTO duty_leave_privileges(staffID,deptID,batchID) VALUES(" . $dlp->staffID . "," . $dlp->deptID . "," . $dlp->batchID . ")";
            $lastInsertedId = $this->executeQuery($sql, 'TRUE');
        } catch (\Exception $e) {
            throw new ProfessionalException(ProfessionalException::QUERY_EXECUTION_FAILED, $e->getMessage());
        }
        return $lastInsertedId;
    }
    /**
     * Method for fetching all duty leave privileges by given conditions.
     * @param DutyLeavePrivileges $dlp
     * @return object|$objectList[]
     * @throws ProfessionalException
     * @author gadheyan
     */
    public function getDutyLeavePrivileges($dlp)
    {
        $sql = "";
        $dlpObjectList = null;
        foreach ($dlp as $key => $value) {
            $dlp->$key = $this->realEscapeString($value);
        }
        if ($dlp->deptID == NULL) {
            throw new ProfessionalException(ProfessionalException::DEPARTMENT_ID_NOT_DEFINED, "DEPARTMENT_ID_NOT_DEFINED");
        }
        if ($dlp->staffID == NULL) {
            throw new ProfessionalException(ProfessionalException::STAFF_ID_NOT_DEFINED, "STAFF_ID_NOT_DEFINED");
        }
        try {
            $sql = "SELECT * FROM duty_leave_privileges WHERE deptID=" . $dlp->deptID . " AND staffID=" . $dlp->staffID;
            $dlpObjectList = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $dlpObjectList;
    }
    /**
     * Method to remove privilege of a staff to mark duty leave of a particular batch and
     * department.
     * @param DutyLeavePrivileges $dlp
     * @throws ProfessionalException
     * @author gadheyan
     */
    public function removeDutyLeavePrivileges($dlp)
    {
        $sql = "";
        foreach ($dlp as $key => $value) {
            $dlp->$key = $this->realEscapeString($value);
        }
        try {
            $sql = "DELETE FROM duty_leave_privileges WHERE staffID=" . $dlp->staffID . " AND deptID=" . $dlp->deptID . " AND batchID=" . $dlp->batchID;
            $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * method to getting staff details with guideship (PhD)
     * @return StaffList
     * @throws ProfessionalException
     * @author Ranjith Balachandran
     */
    public function getStaffDetailsWithPhDGuideShip()
    {
        $sql = '';
        $staffList = [];
        $sql = "SELECT staffID, staffName FROM staffaccounts WHERE isGuide = 1";
        try {
            $staffList = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffList;
    }
    /**
     * method to get staff designation by staffId
     * @param $staffId
     * @return $designation
     */
    public function getStaffDesignationByStaffId($staffId)
    {
        $staffId = $this->realEscapeObject($staffId);
        $designation = null;
        $designationObj = null;
        $sql = "SELECT isHOD, isPrincipal,isFaculty,other_designation FROM staffaccounts WHERE staffID = '$staffId'";
        try {
            $designationObj = $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        if ($designationObj->isFaculty == 1) {
            $designation = "staff";
        }
        if ($designationObj->isFaculty == 2) {
            return $designationObj->other_designation;
        }
        if ($designationObj->isHOD == 1) {
            $designation = "hod";
        }
        if ($designationObj->isHOD == 2) {
            $designation = "ahod";
        }
        if ($designationObj->isHOD == 3){
            
            $designation = "depthod";
        }
        if ($designationObj->isPrincipal == 1) {
            $designation = "principal";
        }
        if ($designationObj->isPrincipal == 2) {
            $designation = "viceprincipal";
        }
        if ($designationObj->isPrincipal == 3) {
            $designation = "dean";
        }
        if ($designationObj->isPrincipal == 4) {
            $designation = "director";
        }
        if ($designationObj->isPrincipal == 5) {
            $designation = "manager";
        }
        if ($designationObj->isPrincipal == 6) {
            $designation = "academiccoordinator";
        }
        if ($designationObj->isPrincipal == 7) {
            $designation = "erpadmin";
        }
        if ($designationObj->isPrincipal == 8) {
            $designation = "ceo";
        }
        if ($designationObj->isPrincipal == 9) {
            $designation = "chairman";
        }
        if ($designationObj->isPrincipal == 10) {
            $designation = "welfareOfficer";
        }
        if ($designationObj->isPrincipal == 11) {
            $designation = "financeOfficer";
        }
        $amsRoleTypes = json_decode(CommonService::getInstance()->getSettings(SettingsConstants::ADMIN,SettingsConstants::AMS_ROLES_TYPES));
        return CommonUtil::objArraySearch($amsRoleTypes,"role",$designation)->display;
    }
    /**
     * Is staff assigned to pseudosubject
     * @param int $pseudosubId
     * @param int $staffId
     * @return boolean
     * @throws ProfessionalException
     */
    public function isStaffAssignedToPseudoSub($pseudosubId, $staffId)
    {
        $pseudosubId = $this->realEscapeString($pseudosubId);
        $staffId = $this->realEscapeString($staffId);
        $sql = "SELECT psbs.sbsID FROM sbs_relation sbsr inner join pseudosubjects_sbs psbs on sbsr.sbsID=psbs.sbsID WHERE psbs.pseudosubjectID = " . $pseudosubId . " and sbsr.staffID = " . $staffId;
        try {
            if ($this->executeQueryForObject($sql)) {
                return true;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return false;
    }
    /**
     * Is staff assigned to pseudosubject by subjectId batchId staffId
     * @param int $batchId
     * @param int $semId
     * @param int $subjectId
     * @param int $staffId
     * @return boolean
     * @throws ProfessionalException
     */
    public function isStaffAssignedToPseudoSubBySBS($batchId, $semId, $subjectId, $staffId)
    {
        $batchId = $this->realEscapeString($batchId);
        $semId = $this->realEscapeString($semId);
        $subjectId = $this->realEscapeString($subjectId);
        $staffId = $this->realEscapeString($staffId);
        $sql = " select sr.staffID from  sbs_relation sr  where sr.staffID = $staffId and sr.batchID = $batchId and sr.semID = $semId and isPseudosubject=1 and sr.subjectID = $subjectId";
        try {
            if ($this->executeQueryForObject($sql)->staffID) {
                return true;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return false;
    }
    /**
     *
     * Get All staff working or taking classes under a department.
     *
     * @param deptID
     * @return $stafflist
     * @author Kishan
     */
    function getAssignedStaffByDepartment($deptID, $sortBy = 'staffName', $sortOrder = 'ASC')
    {
        $stafflist = null;
        $criteria = null;
        $criteria1 = "";
        $deptID = $this->realEscapeString($deptID);
        $sql = "SELECT DISTINCT sa.staffID ,sa.staffName,sa.staffPhone,sa.staffAccount FROM sbs_relation sr INNER JOIN staffaccounts sa ON sr.staffID = sa.staffID WHERE sr.batchID IN (SELECT batchID FROM batches WHERE deptID = '$deptID' AND isPassOut = 0) AND sa.isResigned = 0";
        if ($deptID == null) {
            throw new ProfessionalException(ProfessionalException::DEPARTMENT_ID_NOT_DEFINED, "DEPARTMENT_ID_NOT_DEFINED");
        }
        $criteria = " ORDER BY $sortBy $sortOrder";
        $sql .= $criteria;
        try {
            $stafflist = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $stafflist;
    }
    /**
     * Method for saving staff qualification details in staffQualificationDetails
     * @param Int $staffid
     * @param String $staffqualificationDetailsStr
     * @return true
     * @throws ProfessionalException
     * @author Vishnu M
     */
    public function insertStaffQualificationDetails($staffId, $staffqualificationDetailsStr)
    {
        $sql = null;
        $staffId = $this->realEscapeString($staffId);
        try {
            $sql = "DELETE FROM staffQualificationDetails WHERE staffaccounts_id = $staffId";
            $this->executeQuery($sql);
            if ($staffqualificationDetailsStr) {
                $sql = "INSERT INTO staffQualificationDetails ( staffaccounts_id, staffqualification_id, instituteName, university, percentage, year, createdBy, createdDate, updatedBy, updatedDate ) VALUES " . $staffqualificationDetailsStr . "";
                $this->executeQuery($sql);
            }
        } catch (\Exception $e) {
            throw new ProfessionalException(ProfessionalException::QUERY_EXECUTION_FAILED, $e->getMessage());
        }
        return true;
    }
    /**
     * Method for getting staff qualifications by staffId
     * @param int $staffId
     * @return object $qualificationDetails
     * @throws PeofessionalException
     * @author Vishnu M
     */
    public function getStaffQualificationDetailsByStaffId($staffId)
    {
        $sql = null;
        $staffId = $this->realEscapeString($staffId);
        $qualificationDetails = [];
        $sql = "SELECT sqd.id, sqd.staffqualification_id AS qualificationId, sqd.instituteName, sqd.university, sqd.percentage, sqd.year, sq.qualificationName FROM staffQualificationDetails sqd inner join staffqualification sq ON sq.qualificationID=sqd.staffqualification_id WHERE sqd.staffaccounts_id = $staffId";
        try {
            $qualificationDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new PeofessionalException($e->getCode(), $e->getMessage());
        }
        return $qualificationDetails;
    }
    /**
     * Method for deleteing a staff qualification for a staffId
     * @param Int $staffId , $qualificationId
     * @return Boolean
     * @throws ProfessionalException
     * @author Vishnu M
     */
    public function deleteStaffQualification($qualificationId, $staffId)
    {
        $sql = null;
        $staffId = $this->realEscapeString($staffId);
        $qualificationId = $this->realEscapeString($qualificationId);
        $sql = "DELETE FROM staffQualificationDetails WHERE staffqualification_id = $qualificationId AND staffaccounts_id = $staffId";
        try {
            $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return true;
    }
    /**
     * Get lecture types
     *
     * @return object|array|$objectList[]
     * @throws ProfessionalException
     * @author Ranjith Balachandran
     */
    public function getLectureTypes()
    {
        $lectureTypes = [];
        $query = "SELECT id, typeName FROM lectureTypes";
        try {
            $lectureTypes = $this->executeQueryForList($query);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $lectureTypes;
    }
    /**
     * Method for checking whether this staff naac report entry permission
     * @param Int $staffId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     * @author Vishnu M
     */
    public function checkStaffHasNaacReportEntryPermission($staffId)
    {
        $sql = '';
        $isStaffHasPermission = null;
        $staffId = $this->realEscapeString($staffId);
        try {
            $sql = "SELECT asp.staff_id AS staffId FROM auth_staffaccounts_permission asp INNER JOIN auth_permission ap ON (asp.auth_permission_id = ap.id) WHERE ap.module = 'NAAC' AND staff_id = " . $staffId . " ";
            $isStaffHasPermission = $this->executeQueryForObject($sql)->staffId;
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $isStaffHasPermission;
    }
    /**
     * Method for checking whether this staff naac report entry permission
     * @param Int $staffId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     * @author
     */
    public function checkStaffHasExatAccessPermission($staffId)
    {
        $sql = '';
        $isStaffHasPermission = null;
        $staffId = $this->realEscapeString($staffId);
        try {
            $isStaffHasPermission = PermissionService::getInstance()->staffHasPermission($staffId,["ACCESS_EXAT"]);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $isStaffHasPermission;
    }
    /**
     * Check user has centralized attendance privillege
     * @param int $staffId
     * @return boolean
     * @throws ProfessionalException
     */
    public function hasCentrAttendPrivilege($staffId)
    {
        $hasPrivillegae = false;
        $staffId = $this->realEscapeString($staffId);
        $sql = "SELECT id FROM centralized_attendance_privilege WHERE staffID=$staffId";
        try {
            $isStaffHasPermission = $this->executeQueryForObject($sql)->id;
            $hasPrivillegae = empty($isStaffHasPermission) ? false : true;
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $hasPrivillegae;
    }
    /**
     * @param $staffId
     * @param $date
     * @return array
     * @throws \Exception
     */
    public function getFacultyAttendanceShiftDetails($staffId, $date)
    {
        $this->realEscapeString($staffId);
        $this->realEscapeString($date);
        v::intVal()->check($staffId);
        v::date('Y-m-d')->check($date);
        $actualInTime = null;
        $actualOutTime = null;
        $sql_shift_exception = "select actualIntime,actualOuttime 
                                from staffAttn_shiftException 
                                where staffID='$staffId
                                and exceptionDate='$date'";
        $res = $this->executeQueryForObject($sql_shift_exception);
        if (!empty($res)) {
            $actualInTime = $res->actualIntime;
            $actualOutTime = $res->actualOuttime;
        } else {
            $sql_shift_details = "select actualIntime, actualOuttime 
                                  from staffAttn_shiftDetails 
                                  where staffID='$staffId
                                  and '$date' between fromDate and toDate";
            $res = $this->executeQueryForObject($sql_shift_details);
            if (!empty($res)) {
                $actualInTime = $res->actualIntime;
                $actualOutTime = $res->actualOuttime;
            }
        }
        return [$actualInTime, $actualOutTime];
    }
    /**
     * To mark the attendance of staffs.
     * Used by api to mark faculty attendance.
     * Implemented based on professional-web/admin/staffattn/staffattn.php
     * @param StaffAttendance $staffAttendance
     */
    public function saveFacultyAttendance($staffAttendance)
    {
        $this->realEscapeObject($staffAttendance);
        $validator = v::attribute('staffId', v::optional(v::intVal()))
            ->attribute('staffAccount', v::optional(v::stringType()->length(1, 50)))
            ->attribute('biometricId', v::optional(v::stringType()))
            ->attribute('date', v::date('Y-m-d'))
            ->attribute('inTime', v::optional(v::date('H:i:s')))
            ->attribute('outTime', v::optional(v::date('H:i:s')));
        $validator->check($staffAttendance);
        if (empty($staffAttendance->staffId) && empty($staffAttendance->staffAccount) && empty($staffAttendance->biometricId))
            throw new ProfessionalException("ID_REQUIRED", "Atleast one of staffId, username, biometricId is required");
        if (empty($staffAttendance->inTime) && empty($staffAttendance->outTime))
            throw new ProfessionalException("INVALID_TIME", "Atleast one of inTime or outTime is required");
        if (!empty($staffAttendance->staffId)) {
            $sql = "select staffAccount from staffaccounts where staffID='$staffAttendance->staffId' and isResigned=0";
            $res = $this->executeQueryForObject($sql);
            $staffAttendance->staffAccount = $res->staffAccount;
        } elseif (!empty($staffAttendance->staffAccount)) {
            $sql = "select staffID from staffaccounts where staffAccount='$staffAttendance->staffAccount' and isResigned=0";
            $res = $this->executeQueryForObject($sql);
            $staffAttendance->staffId = $res->staffID;
        } elseif (!empty($staffAttendance->biometricId)) {
            try {
                $staffAttendance->staffId = BioMetricService::getInstance()->getUserIdByBioMetricCredentials(UserType::STAFF, $staffAttendance->biometricId, $staffAttendance->deviceId);
            } catch (\Exception $e) {
                $staffAttendance->staffId = null;
            }
            if (!empty($staffAttendance->staffId)) {
                $sql = "select staffAccount from staffaccounts where staffID='$staffAttendance->staffId' and isResigned=0";
                $res = $this->executeQueryForObject($sql);
                $staffAttendance->staffAccount = $res->staffAccount;
            }
        }
        if (empty($staffAttendance->staffId) || empty($staffAttendance->staffAccount))
            throw new ProfessionalException("INVALID_STAFF_LOGIN_ID", "Invalid staff login id");
        $sql = "select punchDate as date, 
                punchIn as inTime, 
                punchOut as outTime 
                from staff_attendance 
                where staffAccount='$staffAttendance->staffAccount
                and punchDate='$staffAttendance->date'";
        $existingRecord = $this->executeQueryForObject($sql);
        $sql = "";
        if ($existingRecord) {
            /**
             * If entry for this date already exists.
             * 1. check new inTime is less than current one then update inTime
             * 2. check new outTime is greater than current one in db then update the outTime
             * This is to store the first inTime and last outTime for a day and ignoring anything in between.
             */
            $change = new \stdClass();
            $dbWriteRequired = false;
            if (!empty($staffAttendance->inTime)) {
                $newInTime = \DateTime::createFromFormat('H:i:s', $staffAttendance->inTime);
                $existingInTime = \DateTime::createFromFormat('H:i:s', $existingRecord->inTime);
                if (empty($existingInTime) || $existingRecord->inTime == "00:00:00" || $newInTime < $existingInTime) {
                    $dbWriteRequired = true;
                    $change->inTime = $staffAttendance->inTime;
                } else {
                    $change->inTime = $existingRecord->inTime;
                }
            }
            if (!empty($staffAttendance->outTime)) {
                $newOutTime = \DateTime::createFromFormat('H:i:s', $staffAttendance->outTime);
                $existingOutTime = \DateTime::createFromFormat('H:i:s', $existingRecord->outTime);
                if (empty($existingOutTime) || $existingRecord->outTime == "00:00:00" || $newOutTime > $existingOutTime) {
                    $dbWriteRequired = true;
                    $change->outTime = $staffAttendance->outTime;
                } else {
                    $change->outTime = $existingRecord->outTime;
                }
            }
            $sql = "update staff_attendance set staffAccount=staffAccount";
            if ($change->inTime)
                $sql .= ", punchIn='$change->inTime'";
            if ($change->outTime)
                $sql .= ", punchOut='$change->outTime'";
            $sql .= " where staffAccount='$staffAttendance->staffAccount' and punchDate='$staffAttendance->date'";
            if ($dbWriteRequired) {
                $this->executeQuery($sql);
                $this->logger->info(Events::API_STAFF_ATTENDANCE_UPDATED, ["attendance" => $staffAttendance]);
            }
        } else {
            list($actualInTime, $actualOutTime) = $this->getFacultyAttendanceShiftDetails($staffAttendance->staffId, $staffAttendance->date);
            $sql = "insert into staff_attendance 
                    (staffAccount, punchDate, punchIn, punchOut, actualpunchIn, actualpunchOut) 
                    values ('$staffAttendance->staffAccount', 
                    '$staffAttendance->date', 
                    '$staffAttendance->inTime', 
                    '$staffAttendance->outTime', 
                    '$actualInTime', 
                    '$actualOutTime')";
            $this->executeQuery($sql);
            $this->logger->info(Events::API_STAFF_ATTENDANCE_INSERTED, ["attendance" => $staffAttendance]);
        }
    }
    public function pushSaveBulkFacultyAttendanceToTaskQueue($staffList)
    {
        $ackId = null;
        $attendanceUpload = new BiometricAttendanceUploadRequest();
        $attendanceUpload->request = json_encode($staffList);
        $attendanceUpload->status = BiometricAttendanceUploadRequestStatus::PENDING;
        $attendanceUpload->requestType = BiometricAttendanceUploadRequestType::STAFF_ATTENDANCE_BULK_UPLOAD;
        try {
            $ackId = BiometricService::getInstance()->createNewBiometricAttendanceUploadRequest($attendanceUpload);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        $requestParams = new \stdClass();
        $requestParams->staffList = $staffList;
        $requestParams->acknowledgementId = $ackId;
        $params = [];
        $taskQueue = new AMSTaskQueue();
        $params = ['className' => 'com\linways\core\ams\professional\service\StaffService', 'methodName' => 'saveBulkFacultyAttendance', 'methodParams' => [$requestParams]];
        try {
            $taskQueue->enqueue('EXECUTE SERVICE', $params);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $ackId;
    }
    /**
     * Undocumented function
     *
     * @param [type] $request
     * @return void
     * @throws ProfessionalException
     */
    public function saveBulkFacultyAttendance($request)
    {
        $failedRecords = [];
        $staffList = $request->staffList;
        $ackId = $request->acknowledgementId;
        try {
            $staffList = $this->realEscapeObject($staffList);
        } catch (\Exception $e) {
        }
        foreach ($staffList as $staff) {
            $staff = (object)$staff;
            $staffAttendance = new StaffAttendance();
            $staffAttendance->staffId = $staff->staffId;
            $staffAttendance->staffAccount = $staff->loginId;
            $staffAttendance->biometricId = $staff->biometricId;
            $staffAttendance->deviceId = $staff->deviceId;
            $staffAttendance->date = $staff->date;
            $staffAttendance->inTime = $staff->inTime;
            $staffAttendance->outTime = $staff->outTime;
            try {
                $this->saveFacultyAttendance($staffAttendance);
            } catch (ValidationException $e) {
                $staffAttendance->error['message'] = $e->getMessage();
            } catch (\Exception $e) {
                $errorId = uniqid("LIN_API_");
                $logger = AMSLogger::getLogger();
                $logger->error("STAFF_ATTENDANCE_API_ERROR", [
                    "errorId" => $errorId,
                    "code" => $e->getCode(),
                    "msg" => $e->getMessage(),
                    "trace" => $e->getTraceAsString()
                ]);
                $staffAttendance->error['message'] = "Unknown error occurred. Please contact Linways Technical support team with this id: " . $errorId;
            }
            if (!empty($staffAttendance->error)) {
                $failedRecords[] = $staffAttendance;
            }
        }
        $attendanceUpload = new BiometricAttendanceUploadRequest();
        $attendanceUpload->id = $ackId;
        $attendanceUpload->status = BiometricAttendanceUploadRequestStatus::SUCCESS;
        if (!empty($failedRecords)) {
            if (count($failedRecords) < count($staffList)) {
                $attendanceUpload->status = BiometricAttendanceUploadRequestStatus::PARTIALLY_FAILED;
            } else {
                $attendanceUpload->status = BiometricAttendanceUploadRequestStatus::FAILED;
            }
        }
        $attendanceUpload->response = json_encode([
            "status" => $attendanceUpload->status,
            "failedRecords" => $failedRecords
        ]);
        try {
            BiometricService::getInstance()->updateBiometricAttendanceUploadRequest($attendanceUpload);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @param array $departmentIds
     * @param bool $excludeResigned
     * @return array|Object|Staff[]
     * @throws ProfessionalException
     */
    public function getStaffByDepartments($departmentIds, $excludeResigned = true)
    {
        $staffs = [];
        $departmentIds = $this->realEscapeArray($departmentIds);
        if (!is_array($departmentIds)) {
            throw new ProfessionalException(ProfessionalException::INVALID_ARGUMENT_TYPE, "Expected array, but got " . gettype($departmentIds));
        }
        $sql = "SELECT staffID,staffName,staffCode FROM staffaccounts 
                WHERE deptID IN (" . implode(",", $departmentIds) . ") ";
        if ($excludeResigned) {
            $sql .= " AND isResigned=0";
        }
        try {
            $staffs = $this->executeQueryForList($sql, $this->mapper[StaffServiceMapper::GET_STAFF_ACCOUNTS_BY_DEPARTMENT_IDS]);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffs;
    }
    /**
     * Returns staffs under departments with department details
     * @param $departmentIds
     * @param bool $excludeResigned
     * @return array|Object
     * @throws ProfessionalException
     */
    public function getStaffDetailsByDepartments($departmentIds, $excludeResigned = true)
    {
        $staffs = [];
        $departmentIds = $this->realEscapeArray($departmentIds);
        if (!is_array($departmentIds)) {
            throw new ProfessionalException(ProfessionalException::INVALID_ARGUMENT_TYPE, "Expected array, but got " . gettype($departmentIds));
        }
        $sql = "SELECT DISTINCT staffID as id,staffName as name,staffCode as code,deptName as departmentName
                FROM staffaccounts sa
                INNER JOIN department d on sa.deptID = d.deptID
                WHERE d.deptID IN (" . implode(",", $departmentIds) . ") ";
        if ($excludeResigned) {
            $sql .= " AND sa.isResigned=0";
        }
        try {
            $staffs = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffs;
    }
    /**
     * @param bool $excludeResigned
     * @return array|Object
     * @throws ProfessionalException
     * @author jithinvijayan
     */
    public function getStaffDetailsByDepartment($departmentId, $excludeResigned = true)
    {
        $staffs = [];
        $departmentId = $this->realEscapeString($departmentId);
        if (empty($departmentId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_DEPARTMENT_ID, "Invalid department details given");
        }
        $sql = "SELECT staffID as id, staffName as name,staffCode as code, staffEmail, staffPhone
                FROM staffaccounts WHERE deptID =$departmentId";
        if ($excludeResigned) {
            $sql .= " AND isResigned=0 ";
        } else {
            $sql .= " AND isResigned=1";
        }
        try {
            $staffs = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffs;
    }
    /**
     * HOD check The monthly report details and varify with the NOTES CHECK FLAG
     * @param $reptIds
     * @param $field
     * @param int $staffID
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function createUpdateHodNotesCheck($reptIds, $field, $staffID)
    {
        if (is_string($reptIds)) {
            $reptIds = $this->realEscapeString($reptIds);
        } else {
            $reptIds = $this->realEscapeObject($reptIds);
        }
        $field = $this->realEscapeObject($field);
        $staffID = $this->realEscapeObject($staffID);
        $Checksql = "select count(id) as id from staffMonthlyReportDetails where reportId='$reptIds' and name='notesChecked';";
        try {
            $check = $this->executeQueryForObject($Checksql)->id;
            if ($check == 0) {
                $sql = "INSERT INTO staffMonthlyReportDetails (reportId, name, value, createdBy, createdDate, updatedBy, updatedDate) VALUE (" . $reptIds . ",'" . $field["name"] . "','" . $field["value"] . "', $staffID, UTC_TIMESTAMP(), $staffID, UTC_TIMESTAMP())";
            } else {
                $sql = "Update staffMonthlyReportDetails set value='" . $field["value"] . "', updatedBy='" . $staffID . "', updatedDate=UTC_TIMESTAMP() where reportId='" . $reptIds . "' and name='notesChecked'";
            }
            return $this->executeQueryForObject($sql, true);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * get all staff with permissions with the authpermissionID and optionally by deptID
     * @param $authPermissionId
     * @param null $deptID
     * @return staffs
     * @throws ProfessionalException
     * @throws ProfessionalException
     * @author Nandu
     */
    public function getAllStaffWithAuthPermissionId($authPermissionId, $deptID = NULL)
    {
        if ($deptID)
            $condition = "and s.deptID=$deptID";
        $sql = "SELECT s.staffID,asp.auth_permission_id,s.staffName,d.deptName,s.isHOD,d.deptName FROM auth_staffaccounts_permission asp 
        LEFT JOIN staffaccounts s on asp.staff_id = s.staffID 
        LEFT JOIN department d on d.deptID = s.deptID
        where auth_permission_id ='$authPermissionId$condition;";
        try {
            $staffs = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffs;
    }
    /**
     * @param StaffLoginRequest $request
     * @return Object|null|Staff
     * @throws ProfessionalException
     */
    public function verifyStaffAccountAndFetchDetails(StaffLoginRequest $request)
    {
        $request = $this->realEscapeObject($request);
        $response = null;
        $sql = "SELECT s.staffID,s.staffAccount,s.staffName,d.deptID as deptId,s.isHOD,s.isPrincipal,s.isResigned,
                d.deptName,s.staffLock,d.departmentDesc
                FROM staffaccounts s
                INNER JOIN department d ON d.deptID = s.deptID
                WHERE s.staffPassword ='$request->password'";
        if (!empty($request->staffAccount)) {
            $sql .= " AND s.staffAccount = '$request->staffAccount'";
        } elseif (!empty($request->email)) {
            $sql .= " AND s.staffEmail = '$request->email'";
        } else {
            throw new ProfessionalException(ProfessionalException::INVALID_USER_NAME_OR_PASSWORD, "Invalid user name or password");
        }
        try {
            $response = $this->executeQueryForObject($sql, false, $this->mapper[StaffServiceMapper::GET_STAFF_DETAILS_FOR_LOGIN]);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $response;
    }
    public function getStaffDetailsByBatchID($batchID = null, $deptID)
    {
        $batchID = $this->realEscapeString($batchID);
        $deptID = $this->realEscapeString($deptID);
        $condition = "";
        if ($batchID) {
            $condition .= " AND b.batchID='$batchID";
        }
        if ($deptID) {
            $condition .= " AND dept.deptID='$deptID";
        }
        $sql = "SELECT s.staffName,s.staffID,s.deptID,s.staffCode FROM sbs_relation sr
        INNER JOIN staffaccounts s ON s.staffID = sr.staffID 
        INNER JOIN batches b ON sr.batchID = b.batchID AND b.semID = sr.semID
        LEFT JOIN department dept ON dept.deptID = b.deptID
        WHERE s.isResigned = 0 AND b.isPassOut = 0 AND dept.deptShow = 1 $condition  
        GROUP BY sr.staffID order by s.deptID;";
        try {
            $staffs = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffs;
    }
    /**
     * Method for checking quick report is assigned for a staff.
     * @param number $staffId
     * @param string $ReportName
     * @return boolean
     * @throws ProfessionalException
     * @author Ajay
     */
    public function getQuickReportAuthorisationByStaffIdAndReportName($staffId, $ReportName)
    {
        $sql = "";
        $quickReportAuthorisation = null;
        $staffId = $this->realEscapeString($staffId);
        $ReportName = $this->realEscapeString($ReportName);
        $sql = "SELECT id FROM quick_reports_staff_authorization WHERE staffId =  $staffId and quickReportName = '$ReportName'";
        try {
            $quickReportAuthorisation = $this->executeQueryForObject($sql);
            if ($quickReportAuthorisation) {
                return true;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return false;
    }
    /**
     * Get Staff Phone number by staff Id
     * @param int $staffId
     * return string
     */
    public function getStaffPhoneById($staffId)
    {
        $staffPhone = null;
        $staffId = $this->realEscapeString($staffId);
        $sqlStaffPhone = null;
        try {
            $sqlStaffPhone = "SELECT staffPhone FROM staffaccounts WHERE staffID = '$staffId'";
            $sqlResponse = $this->executeQueryForObject($sqlStaffPhone);
            if ($sqlResponse != null) {
                $staffPhone = $sqlResponse->staffPhone;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffPhone;
    }
    /** Formways services **/
    /**
     *
     * @param unknown $id
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     * @author gadheyan
     */
    public function getStaffDetailsByIdForFormways($id)
    {
        $staffDetails = NULL;
        $id = $this->realEscapeString($id);
        $sql = "SELECT 
            sta.staffID AS value,
            sta.staffName AS label
        FROM
        staffaccounts sta
        WHERE sta.staffID = $id";
        try {
            $staffDetails = $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /**
     *
     * @param GetAllFacultiesRequest $request
     * @return array|object|$objectList[]
     * @throws ProfessionalException
     * @author gadheyan
     */
    public function getAllFacultiesForFormways(GetAllFacultiesRequest $request)
    {
        $staffs = [];
        $request = $this->realEscapeObject($request);
        $sql = "";
        $sql = "SELECT 
                staffID AS value, staffName AS label
                FROM
                staffaccounts WHERE 1=1 ";
        if ($request) {
            if ($request->id) {
                $sql .= " AND staffID = '$request->id'";
            } else if (!empty($request->ids)) {
                $sql .= " AND staffID IN ('" . implode("','", $request->ids) . "')";
            }
            if ($request->deptId) {
                $sql .= " AND deptID = '$request->deptId'";
            }
            if ($request->staffLock) {
                $sql .= " AND staffLock = $request->staffLock";
            }
        }
        try {
            $staffs = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffs;
    }
    public function getFacultiesForAttendanceExchange($request, $subjectType, $batchList)
    {
        $sql = "SELECT distinct sa.staffID AS staffId, sa.staffName AS name, sa.staffCode AS code, sa.myImage, sa.staffGender, dp.deptName FROM staffaccounts sa INNER JOIN department dp ON dp.deptID=sa.deptID LEFT JOIN sbs_relation sr ON sr.staffID=sa.staffID LEFT JOIN batches bt ON bt.batchID=sr.batchID AND bt.semID=sr.semID LEFT JOIN subbatch_sbs ss ON ss.sbsID=sr.sbsID LEFT JOIN subbatches sb ON sb.subbatchID=ss.subbatchID WHERE sa.staffID>0 AND isResigned=0";
        $cond = [];
        if ($request->SUBJECT_TYPE_SPECIFIC == 'true') {
            if ($subjectType == 'SUBBATCH_SUBJECT') {
                $cond[] = "(sb.subbatchID is not null AND sb.psID=0)";
            }
            if ($subjectType == 'PSEUDO_SUBJECT') {
                $cond[] = "sb.psID !=0";
            }
            if ($subjectType == 'NORMAL_SUBJECT') {
                $cond[] = "(sb.subbatchID is null AND sr.sbsID)";
            }
        }
        if ($request->TEACHING_FACULTY == 'true') {
            $cond[] = "sr.sbsID is not null";
        }
        if ($request->BATCH_SPECIFIC == 'true') {
            $cond[] = "sr.batchID IN (" . implode(', ', $batchList) . ")";
        }
        if (!empty($cond)) {
            $sql .= " AND " . implode(" AND ", $cond);
        }
        try {
            return $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * get staff list by subjectID,batchID and semID
     */
    public function getStaffListBySubjectID($subjectId, $batchId, $semesterId)
    {
        $subjectId = $this->realEscapeString($subjectId);
        $batchId = $this->realEscapeString($batchId);
        $semesterId = $this->realEscapeString($semesterId);
        $condition = "";
        $condition .= $subjectId ? " and sbs.subjectID = $subjectId " : "";
        $condition .= $batchId ? " and batchID = $batchId " : "";
        $condition .= $semesterId ? " and sbs.semID = $semesterId " : "";
        $sql = "select st.staffID, st.staffAccount, st.staffCode,st.staffName ,s.subjectID ,s.subjectDesc, sbs.sbsID from sbs_relation sbs
        inner join subjects s on s.subjectID = sbs.subjectID
        inner join staffaccounts st on st.staffID = sbs.staffID
        where 1=1 " . $condition . ";";
        try {
            return $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    public function getMonthlyReportSubmittedStaffsByBatchID($batchID, $deptID, $fromday = null, $endday = null)
    {
        $batchID = $this->realEscapeString($batchID);
        $deptID = $this->realEscapeString($deptID);
        $condition = "";
        if ($batchID) {
            $condition .= " AND b.batchID='$batchID";
        }
        if ($deptID) {
            $condition .= " AND dept.deptID='$deptID";
        }
        if ($fromday && $endday) {
            $condition = " AND ((mr.fromDate BETWEEN '$fromday' AND '$endday') OR (mr.toDate BETWEEN '$fromday' AND '$endday')) ";
        }
        $sql = "SELECT s.staffName,s.staffID,s.deptID,s.staffCode FROM sbs_relation sr
        INNER JOIN staffMonthlyReport mr on mr.sbsId = sr.sbsID 
        INNER JOIN staffaccounts s ON s.staffID = sr.staffID 
        INNER JOIN batches b ON sr.batchID = b.batchID AND b.semID = sr.semID
        LEFT JOIN department dept ON dept.deptID = b.deptID
        WHERE s.isResigned = 0 AND b.isPassOut = 0 AND dept.deptShow = 1 $condition  
        GROUP BY sr.staffID order by s.deptID;";
        try {
            $staffs = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffs;
    }
    public function getNotConformedStaffList($semId, $examTypeId, $courseTypeId, $batchStartYear = null)
    {
        $semId = $this->realEscapeString($semId);
        $examTypeId = $this->realEscapeString($examTypeId);
        $courseTypeId = $this->realEscapeString($courseTypeId);
        $batchStartYear = $this->realEscapeArray($batchStartYear);
        $condition = "";
        $batchStartYear = is_array($batchStartYear) ? implode(",", $batchStartYear) : $batchStartYear;
        if (empty($semId) || empty($examTypeId) || empty($courseTypeId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_REQUEST, "Invalid parameters");
        }
        if (!empty($batchStartYear)) {
            $condition = " AND b.batchStartYear IN ($batchStartYear)";
        }
        $sql = "SELECT
        e.examID,
        e.examName,
        sa.staffID,
        sa.staffName,
        sa.staffAccount,
        sa.staffEmail,
        sa.staffPhone,
        b.batchID,
        e.subbatchID,
        b.batchName,
        s.subjectID,
        s.subjectName,
        s.subjectDesc,
        s.syllabusName
    FROM
        exam e
    INNER JOIN sbs_relation sbsr ON
        sbsr.batchID = e.batchID
        AND sbsr.semID = e.semID
        AND sbsr.subjectID = e.subjectID
    INNER JOIN staffaccounts sa ON
        sa.staffID = sbsr.staffID
    INNER JOIN batches b ON
        b.batchID = e.batchID
        AND b.batchID = sbsr.batchID
    INNER JOIN subjects s ON
        s.subjectID = e.subjectID
        AND s.subjectID = sbsr.subjectID
    WHERE
        e.semID = $semId
        AND e.examTypeID = $examTypeId
        AND b.courseTypeID = $courseTypeId
        $condition
        AND e.examID NOT IN (
        SELECT
            examID
        FROM
            aprove_exam_marks
        WHERE
            semID = $semId
            AND examTypeID = $examTypeId
            AND batchID = e.batchID)";
        try {
            $staffs = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffs;
    }
    public function getNotConformedStaffListOfSubBatches($semId, $examTypeId, $courseTypeId, $subBatchId, $batchStartYear = null)
    {
        $semId = $this->realEscapeString($semId);
        $examTypeId = $this->realEscapeString($examTypeId);
        $courseTypeId = $this->realEscapeString($courseTypeId);
        $subBatchId = $this->realEscapeString($subBatchId);
        $batchStartYear = $this->realEscapeArray($batchStartYear);
        $condition = "";
        $batchStartYear = is_array($batchStartYear) ? implode(",", $batchStartYear) : $batchStartYear;
        if (empty($semId) || empty($examTypeId) || empty($courseTypeId) || empty($subBatchId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_REQUEST, "Invalid parameters");
        }
        if (!empty($batchStartYear)) {
            $condition = " AND b.batchStartYear IN ($batchStartYear)";
        }
        $sql = "SELECT
            e.examID,
            e.examName,
            sa.staffID,
            sa.staffName,
            sa.staffAccount,
            sa.staffEmail,
            sa.staffPhone,
            e.subbatchID,
            b.batchID,
            b.batchName,
            s.subjectID,
            s.subjectName,
            s.subjectDesc,
            s.syllabusName
        FROM
            exam e
        INNER JOIN subbatch_sbs ssbs ON
            ssbs.subbatchID = e.subbatchID
        INNER JOIN sbs_relation sbsr ON
            sbsr.batchID = e.batchID
            AND sbsr.semID = e.semID
            AND sbsr.subjectID = e.subjectID
            AND sbsr.sbsID = ssbs.sbsID
        INNER JOIN staffaccounts sa ON
            sa.staffID = sbsr.staffID
        INNER JOIN batches b ON
            b.batchID = e.batchID
            AND b.batchID = sbsr.batchID
        INNER JOIN subjects s ON
            s.subjectID = e.subjectID
            AND s.subjectID = sbsr.subjectID
        WHERE
            e.semID = $semId
            AND e.examTypeID = $examTypeId
            AND b.courseTypeID = $courseTypeId
            AND e.subbatchID IN ($subBatchId)
            $condition
            AND e.examID NOT IN (
            SELECT
                examID
            FROM
                aprove_exam_marks
            WHERE
                semID = $semId
                AND examTypeID = $examTypeId
                AND batchID = e.batchID)";
        try {
            $staffs = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffs;
    }
    public function getNotConformedSubBatchList($semId, $examTypeId, $courseTypeId, $batchStartYear = null)
    {
        $semId = $this->realEscapeString($semId);
        $examTypeId = $this->realEscapeString($examTypeId);
        $courseTypeId = $this->realEscapeString($courseTypeId);
        $batchStartYear = $this->realEscapeArray($batchStartYear);
        $condition = "";
        $batchStartYear = is_array($batchStartYear) ? implode(",", $batchStartYear) : $batchStartYear;
        if (empty($semId) || empty($examTypeId) || empty($courseTypeId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_REQUEST, "Invalid parameters");
        }
        if (!empty($batchStartYear)) {
            $condition = " AND b.batchStartYear IN ($batchStartYear)";
        }
        $sql = "SELECT
            e.subbatchID
        FROM
            exam e
        INNER JOIN batches b ON
            b.batchID = e.batchID
        LEFT JOIN aprove_exam_marks aem ON
            aem.examId = e.examID
        WHERE
            e.semID = $semId
            AND e.examTypeID = $examTypeId
            AND b.courseTypeID = $courseTypeId
            AND aem.id IS NULL
            AND e.subbatchID <> 0
            $condition";
        try {
            $subbatchIds = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $subbatchIds;
    }
    /**
     * for fetching total hours taken of specific worklogin Daily work log
     *
     * @param  $staffId
     * @param  $type
     * @param  $startDate
     * @param  $endDate
     * @return void
     */
    public function getCountOfWorkLogType($staffId, $type, $startDate, $endDate)
    {
        $staffId = $this->realEscapeString($staffId);
        $type = $this->realEscapeString($type);
        $startDate = $this->realEscapeString($startDate);
        $endDate = $this->realEscapeString($endDate);
        $sql = "SELECT count(*) as count FROM staffDailyWorkLog WHERE staffId=$staffId AND type='$type' AND date BETWEEN '$startDate' AND '$endDate";
        try {
            return $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    public function getTotalWorkLengthOfWorkLogType($staffId, $type, $startDate, $endDate)
    {
        $staffId = $this->realEscapeString($staffId);
        $type = $this->realEscapeString($type);
        $startDate = $this->realEscapeString($startDate);
        $endDate = $this->realEscapeString($endDate);
        $result = null;
        $sql = "SELECT startTime,endTime  FROM staffDailyWorkLog WHERE staffId=$staffId AND type='$type' AND date BETWEEN '$startDate' AND '$endDate";
        try {
            $result = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $result;
    }
    public function getAllStaffQualification()
    {
        $sql = "select qualificationID, qualificationName from staffqualification";
        try {
            return $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    public function updateStaffProfile($fieldList, $staffId)
    {
        $fieldList = $this->realEscapeArray($fieldList);
        $staffId = $this->realEscapeString($staffId);
        $sql = "UPDATE staffaccounts SET ";
        $value = [];
        foreach ($fieldList as $field) {
            if ($field->fieldType != 'table') {
                $value[] = "$field->columnName=" . ($field->value ? "'$field->value'" : 'null');
            }
        }
        $sql .= implode(', ', $value) . " WHERE staffID=" . $staffId;
        try {
            return $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * get examcontroller_admin details
     * @return examcontroller_admin details
     */
    public function getExamControllerDetails($adminId)
    {
        $examControllerDetails = null;
        $sql = "SELECT eca.adminName as adminName from examcontroller_admin eca where adminID = $adminId";
        try {
            $examControllerDetails = $this->executeQueryForObject($sql)->adminName;
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $examControllerDetails;
    }
    /**
     * @param $staffId
     * @return bool
     * @throws ProfessionalException
     */
    public function isHOD($staffId)
    {
        $staffId = (int)$this->realEscapeString($staffId);
        if (empty($staffId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_STAFF_ID, "Invalid staff details given");
        }
        $sql = "SELECT staffID FROM staffaccounts WHERE staffID  =$staffId AND isHOD=1";
        try {
            $staffId = $this->executeQueryForObject($sql)->staffID;
            return $staffId ? true : false;
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @param $staffId
     * @return bool
     * @throws ProfessionalException
     */
    public function isFacultyIsERPAdmin($staffId)
    {
        $staffId = (int)$this->realEscapeString($staffId);
        if (empty($staffId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_STAFF_ID, "Invalid staff details given");
        }
        $sql = "SELECT staffID FROM staffaccounts WHERE staffID  =$staffId AND isPrincipal=7";
        try {
            $staffId = $this->executeQueryForObject($sql)->staffID;
            return $staffId ? true : false;
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @param $staffId
     * @return bool
     * @throws ProfessionalException
     */
    public function isFacultyIsPrincipal($staffId)
    {
        $staffId = (int)$this->realEscapeString($staffId);
        if (empty($staffId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_STAFF_ID, "Invalid staff details given");
        }
        $sql = "SELECT staffID FROM staffaccounts WHERE staffID  =$staffId AND isPrincipal=1";
        try {
            $staffId = $this->executeQueryForObject($sql)->staffID;
            return $staffId ? true : false;
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @param $staffId
     * @return bool
     * @throws ProfessionalException
     */
    public function isFacultyIsPrincipalOrERPAdmin($staffId)
    {
        $staffId = (int)$this->realEscapeString($staffId);
        if (empty($staffId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_STAFF_ID, "Invalid staff details given");
        }
        $sql = "SELECT staffID FROM staffaccounts WHERE staffID  =$staffId AND (isPrincipal=1 OR isPrincipal=7)";
        try {
            $staffId = $this->executeQueryForObject($sql)->staffID;
            return $staffId ? true : false;
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @param $staffId
     * @return bool
     * @throws ProfessionalException
     */
    public function isFacultyIsHODOrPrincipalOrERPAdmin($staffId)
    {
        global $COLLEGE_CODE;
        $staffId = (int)$this->realEscapeString($staffId);
        if (empty($staffId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_STAFF_ID, "Invalid staff details given");
        }
        if($COLLEGE_CODE == "STMKANNUR")
        {
        $sql = "SELECT staffID FROM staffaccounts WHERE staffID  =$staffId 
                AND (isHOD=1 OR isPrincipal=1 OR isPrincipal>=3 OR isHOD=2 OR isHOD=3)";
        }
        else
        {
            $sql = "SELECT staffID FROM staffaccounts WHERE staffID  =$staffId 
                AND (isHOD=1 OR isPrincipal=1 OR isPrincipal>=3 OR isHOD=2)";
        }
        try {
            $staffId = $this->executeQueryForObject($sql)->staffID;
            return $staffId ? true : false;
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Get hod priveleges of staff by batchID
     * @param $batchID
     * @return object|array
     * @throws ProfessionalException
     */
    public function getStaffHodPrivelegesByBatch($batchID)
    {
        $batchID = $this->realEscapeString($batchID);
        $sql = "SELECT 
                    s.staffID, s.staffName, h.id
                FROM
                    staffaccounts s
                        LEFT JOIN
                    batches b ON s.deptID = b.deptID AND b.batchID = $batchID
                        LEFT JOIN
                    hodPrivileges h ON h.staffID = s.staffID
                        AND FIND_IN_SET($batchID, batchIDs)
                WHERE
                    isHOD > 0 AND isResigned != 1
                        AND b.batchID IS NULL";
        try {
            $staffDetails = $this->executeQueryForList($sql);
            return $staffDetails;
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function getAllStaffMailIdByRequest($request)
    {
        $staffIds = $request->staffIds ? " AND st.staffID in (" . implode(',', $request->staffIds) . ") " : "";
        $batchIds = $request->staffBatchIDs ? " AND sbs.batchID IN (" . implode(',', $request->staffBatchIDs) . ") " : "";
        $deptIds = $request->staffDeptIDs ? " AND st.deptID IN (" . implode(',', $request->staffDeptIDs) . ") " : "";
        $batchTu = $request->staffBatchIDs ? " AND bat.batchID IN (" . implode(',', $request->staffBatchIDs) . ") " : "";
        $batchStartYear = $request->yearID ? " AND bat.batchStartYear IN (" . implode(',', $request->yearID) . ") " : "";
        $batchDept = "";
        if(is_array($request->staffDeptIDs) && !empty($request->staffDeptIDs)){
            $batchDept = !empty($batchTu)?($request->staffDeptIDs ? " AND bat.deptID IN (" . implode(',', $request->staffDeptIDs) . ") " : ""):" AND st.deptID IN (". implode(',', $request->staffDeptIDs) . ") ";
        }
        if ($request->sentToHod)
            $unionSql[1] = " SELECT st.staffID,st.staffName,st.staffCode,st.staffEmail,st.staffPhone FROM staffaccounts st WHERE isHOD = 1 " . $deptIds;
        if ($request->sentToPrincipal)
            $unionSql[2] = " SELECT st.staffID,st.staffName,st.staffCode,st.staffEmail,st.staffPhone FROM staffaccounts st WHERE st.isPrincipal = 1 ";
        if ($request->sentToTutor)
            $unionSql[3] = " SELECT st.staffID,st.staffName,st.staffCode,st.staffEmail,st.staffPhone 
                             FROM staffaccounts st 
                                INNER join batch_tutor bt ON st.staffID = bt.staffID
                                INNER join batches bat ON bat.batchID = bt.batchID AND bat.semID = bt.semID
                                WHERE 1=1 $batchTu $deptIds GROUP BY st.staffID;";
        if (!empty($request->staffIds) || $request->allStaff) {
            $unionSql[0] = "SELECT st.staffID,st.staffName,st.staffCode,st.staffEmail,st.staffPhone FROM staffaccounts st
                LEFT JOIN sbs_relation sbs ON sbs.staffID = st.staffID 
                LEFT JOIN batches bat ON bat.batchID = sbs.batchID AND sbs.semID = bat.semID
                LEFT JOIN semesters sem ON sem.semID = sbs.semID 
                WHERE 1=1 $batchIds $batchDept $staffIds $batchStartYear GROUP BY st.staffID ;";
        }
        $sql = implode(' UNION DISTINCT ', $unionSql);
        try {
            if ((!empty($request->staffDeptIDs) || $request->allDept) && (!empty($request->staffBatchIDs) || $request->allBatch)) {
                $result = $sql ? $this->executeQueryForList($sql) : false;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $result;
    }
    public function createEmailLog($emailLog)
    {
        if ($emailLog) {
            if ($emailLog->attachments) {
                $attachments = " attachments, ";
                $attachmentData = '\'' . $emailLog->attachments . '\'' . ' ,';
            }
            $sql = "INSERT INTO email_log (context,module, subject, content, sent_to, filters, $attachments sent_date, createdByUserType, createdBy, createdDate, updatedByUserType, updatedDate, updatedBy) VALUES ('$emailLog->context','$emailLog->module', '$emailLog->subject', '$emailLog->content', '$emailLog->sent_to', '$emailLog->filters',$attachmentData UTC_TIMESTAMP(), '$emailLog->createdByUserType', '$emailLog->createdUserId', UTC_TIMESTAMP() , '$emailLog->updatedByUserType', UTC_TIMESTAMP() , '$emailLog->updatedUserId');";
            try {
                return $this->executeQuery($sql);
            } catch (\Throwable $e) {
                throw new ProfessionalException ($e->getCode(), $e->getMessage());
            }
        }
    }
    public function getEmailLogsByRequest($request)
    {
        $condition = "";
        $condition .= $request->userType ? " AND el.createdByUserType = '$request->userType" : "";
        $condition .= $request->startDate && $request->endDate ? " AND el.sent_date between '$request->startDate' and '$request->endDate" : "";
        $condition .= $request->context ? " AND el.context = '$request->context'" : "";
        $condition .= $request->userId ? "  AND el.createdBy = $request->userId " : "";
        $condition .= $request->id ? "  AND el.id = $request->id " : "";
        if ($condition) {
            $sql = "SELECT el.id, el.context, el.module, el.subject, el.content, el.sent_to, el.filters, el.attachments, el.sent_date, el.createdByUserType, el.createdBy, DATE_FORMAT(CONVERT_TZ(el.createdDate,'+00:00', @@global .time_zone), '%Y-%m-%d %H:%i:%s') AS createdDate, 
                    el.updatedByUserType, el.updatedDate, el.updatedBy ,st.staffName 
                    FROM email_log el
                    INNER JOIN staffaccounts st ON st.staffID = el.createdBy
                    WHERE 1 = 1 $condition ORDER BY el.id $request->order;";
        }
        try {
            return $condition ? $this->executeQueryForList($sql) : false;
        } catch (\Throwable $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * //approve subject plan....
     * @param $staffId
     * @return bool
     * @throws ProfessionalException
     */
    public function approveSubjectProposedPlan($request)
    {
        $request = $this->realEscapeObject($request);
        $approvalDetails = SubjectPlanService::getInstance()->getSubjectProposedPlanByRequest($request)[0];
        try 
        {
            if($approvalDetails)
            {
                $approvalDetails->approve = $approvalDetails->approve?0:1;
                $table = $request->isPseudosubject?" subjectplan_ps_proposed ":" subjectplan_proposed ";
                $sql = "UPDATE $table SET `approve`='$approvalDetails->approve', updated_by = '$request->currentStaff', updated_date = utc_timestamp() WHERE `topicID`='$approvalDetails->topicID' AND verify = 0";
            }
            if ($sql) {
                $this->executeQuery($sql);
                return $approvalDetails;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function approveAllSubjectProposedPlan($request)
    {
        $request = $this->realEscapeObject($request);
        $condition = "";
        try 
        {
            $condition .= $request->topicIds?" and sp.topicID in (".implode(',',$request->topicIds).") ":"";
            if ($request->fromDate && $request->toDate) {
                $fromDate = date("Y-m-d", strtotime($request->fromDate));
                $toDate = date("Y-m-d", strtotime($request->toDate));
                $condition .= " and sp.date between unix_timestamp('$fromDate') and unix_timestamp('$toDate')";
            } else if ($request->toDate) {
                $toDate = date("Y-m-d", strtotime($request->toDate));
                $condition .= " and sp.date <= unix_timestamp('$toDate')";
            } else if ($request->fromDate) {
                $fromDate = date("Y-m-d", strtotime($request->fromDate));
                $condition .= " and sp.date >= unix_timestamp('$fromDate')";
            }
            if($request->isPseudosubject)
            {
                $sql = "UPDATE  subjectplan_ps_proposed sp SET sp.approve='$request->status' WHERE sp.pssId = '$request->pseudosubjectId' AND sp.verify = 0 $condition ;";
            }
            else
            {
                $condition .= $request->sbsId?" and sbs.sbsID = $request->sbsId ":"";
                $condition .= $request->subjectId?" and sbs.subjectID = '$request->subjectId":""; 
                $condition .= $request->batchId?" and sbs.batchID = '$request->batchId":"";
                $condition .= $request->semId?" and sbs.semID = '$request->semId":"";
                $condition .= $request->staffId?" and sbs.staffId = $request->staffId ":"";
                $sql = "UPDATE subjectplan_proposed sp 
                    INNER JOIN sbs_relation sbs on sbs.sbsID = sp.sbsID
                    SET approve = '$request->status
                    WHERE sp.verify = 0 $condition;";
            }
            $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * get staff details
     *
     * @param Object $staffRequest
     * @return $staffDetails
     * @throws ProfessionalException
     */
    public function getAllFacultiesAndDetails($request)
    {
        $request = $this->realEscapeObject($request);
        $staffDetails = [];
        $staffRole = $this->getStaffRole();
        $request->departmentId?$where[] = " sta.deptID = ".$request->departmentId:null;
        $request->searchStaff?$where[] = " sta.staffName like \"%".$request->searchStaff."%\" ":null;
        $request->staffId?$where[] = " sta.staffId=".$request->staffId." ":null;
        $request->onlyTeachingStaffs?$where[] = " sta.staffID in (select distinct staffID from sbs_relation) ":null;
        $request->requireOldStaffs?null:$where[] = " sta.isResigned = 0 ";
        if($request->getPrincipals){
            if(!empty($request->isPrincipalArray)){
                $principalOrHod[] = " sta.isPrincipal in (".implode(",",$request->isPrincipalArray).")";
            }
            $orderBy [] = "sta.isPrincipal";
        }
        if($request->getHoDs){
            if(!empty($request->isHoDArray)){
                $principalOrHod[] = " sta.isHOD in (".implode(",",$request->isHoDArray).")";
            }
            $orderBy [] = "sta.isHOD";
        }
        if($request->getPrincipals || $request->getHoDs){
            $where[] = "(".implode(' OR ',$principalOrHod).")";
        }
        $limit = $request->enableLimit?" limit ".$request->startIndex.",".$request->endIndex:null;
        $role = null;
        if ($staffRole) {
            $role = " ,CASE";
            foreach ($staffRole as $key => $roles) {
                if ($roles->fieldName && $roles->value)
                    $role .= " WHEN sta." . $roles->fieldName . " = " . $roles->value . " THEN '" . $roles->returnValue . "'";
                else
                    $roleElse = " ELSE \"" . $roles->returnValue . "\"";
            }
            $role .= $roleElse . " END as staffRole";
        }
        $sql = "select sta.staffID,sta.staffName,sta.myImage,sta.staffGender,sta.staffAccount,dept.deptID,dept.deptName,hd.designationID,IF(hd.designationName is null, 'Not assigned', hd.designationName) as designationName,sta.staffPhone,sta.staffEmail,sta.staffCode,sd.name as staffDesignation, sta.isResigned, sta.staffAddress
        ".$role.
        from staffaccounts sta
        inner join department dept on dept.deptID = sta.deptID
        left join hr_designations hd on hd.designationID = sta.designationID
        left join staff_designation sd on sd.id = sta.academicDesignationID
        ".($where?" WHERE ".implode(' AND ',$where):"").($orderBy?" ORDER BY ".implode(',',$orderBy):"").$limit.";";
        $sql_count = "select count(sta.staffID) as staffCount
        from staffaccounts sta
        inner join department dept on dept.deptID = sta.deptID
        left join hr_designations hd on hd.designationID = sta.designationID
        ".($where?" WHERE ".implode(' AND ',$where):"");
        
        try {
            $response = new \stdClass();
            $response->staff_list = $this->executeQueryForList($sql);
            $response->staff_count = $this->executeQueryForObject($sql_count)->staffCount;
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $response;
    }
    public function getStaffRole()
    {
        $staffRole = '[{"fieldName":"isPrincipal","value":1,"returnValue":"Principal"},{"fieldName":"isPrincipal","value":2,"returnValue":"Vice Principal"},{"fieldName":"isPrincipal","value":3,"returnValue":"College Dean"},{"fieldName":"isPrincipal","value":4,"returnValue":"Director"},{"fieldName":"isPrincipal","value":5,"returnValue":"Manager"},{"fieldName":"isPrincipal","value":6,"returnValue":"Academic Coordinator"},{"fieldName":"isPrincipal","value":7,"returnValue":"ERP Admin"},{"fieldName":"isPrincipal","value":8,"returnValue":"CEO"},{"fieldName":"isPrincipal","value":9,"returnValue":"Chairman"},{"fieldName":"isPrincipal","value":10,"returnValue":"Welfare Officer"},{"fieldName":"isPrincipal","value":11,"returnValue":"Finance Officer"},{"fieldName":"isHOD","value":1,"returnValue":"HOD"},{"fieldName":"isHOD","value":2,"returnValue":"HOD In Charge"},{"fieldName":"isHOD","value":3,"returnValue":"Department Dean"},{"fieldName":null,"value":0,"returnValue":"Faculty"}]';
        return json_decode($staffRole);
    }
    /**
     * get all subject details by request
     *
     * @param Object $request
     * @return $subjectDetails
     * @throws ProfessionalException
     */
    public function getAllSubjectsAndStaffDetails($request)
    {
        $request = $this->realEscapeObject($request);
        $staffDetails = null;
        $where = [];
        $basicCondition = [];
        $pssJoin = [];
        $subJoin = [];
        $stdJoin = [];
        $request->staffId?$where[] = " sbs.staffID = $request->staffId ":"";
        $request->batchId?$where[] = " sbs.batchID = $request->batchId ":"";
        $request->sbsIds?$where[] = " sbs.sbsID in (".implode(',',$request->sbsIds).") ":"";
        $request->sbsId?$where[] = " sbs.sbsID = $request->sbsId ":"";
        $request->semId?$where[] = " sbs.semID = $request->semId ":"";
        $request->subjectId?$where[] = " sbs.subjectID = $request->subjectId ":"";
        $request->staffId?$basicCondition[] = " s.staffID = $request->staffId ":"";
        $request->sbsIds?$basicCondition[] = " s.sbsID in (".implode(',',$request->sbsIds).") ":"";
        $request->sbsId?$basicCondition[] = " s.sbsID = $request->sbsId ":"";
        $request->currentSubjects?$basicCondition[] = " s.semID = bat.semID ":"";
        $request->pseudoSubjectId?$basicCondition[] = " s.pseudosubjectID = $request->pseudoSubjectId ":"";
        $request->excludeTutorSubjects?$basicCondition[] = " su.subjectName <> '".SettingsConstants::SUBJECT_TUTOR."' ":"";
        $request->batchId?$basicCondition[] = " s.batchID = $request->batchId ":"";
        $request->semId?$basicCondition[] = " s.semId = $request->semId ":"";
        $request->subjectNameLike?$basicCondition[] = " su.subjectName like '$request->subjectNameLike%' ":"";
        $request->staffDeptId?$basicCondition[] = " st.deptID = $request->staffDeptId ":"";
        $request->subjectId?$basicCondition[] = " su.subjectID = $request->subjectId ":"";
        $request->batchDeptId?$basicCondition[] = " bd.deptID = $request->batchDeptId ":"";
        $request->pseudoSubjectdeptId?$basicCondition[] = " pd.deptID = $request->pseudoSubjectdeptId ":"";
        // groupBy subjectId to display only subjects studied by students
        $request->isEnabledStudentSubjectGrouping =  $request->isEnabledStudentSubjectGrouping?true:false;
        if($request->isEnabledStudentSubjectGrouping){
            $studentSubjectGroupBy =['sbs.batchID', 'sbs.semID', 'sbs.subjectID'];
        }
        if((int)$request->studentId){
            $pssJoin[] = 'INNER JOIN pseudosubjects_students std ON std.pseudosubjectID = ps.pseudosubjectID';
            $subJoin[] = 'INNER JOIN subbatch_student std ON std.subbatchID = sub.subbatchID';
            $stdJoin[] = 'INNER JOIN studentaccount std ON std.batchID = sbs.batchID';
            $request->studentId?$where[] = " std.studentID = $request->studentId ":"";
        }
        
        $sql = "SELECT s.sbsID,s.staffID,s.subjectID,s.batchID,s.subbatches,CASE WHEN s.pseudosubjectID IS NOT null THEN s.subjectName ELSE su.subjectName END as subjectName,s.batchType,CASE WHEN s.pseudosubjectID IS NOT null THEN s.subjectName ELSE su.subjectDesc END as subjectDesc,CASE WHEN s.semID = bat.semID THEN 1 ELSE 0 END AS currentBatch,st.staffName,st.staffCode,bat.batchName,bat.semID AS currentSemId,currentsem.semName AS currentSem,s.semID AS subjectSemId, sem.semName AS subjectSem,s.pseudosubjectID,s.sbsIds,s.batchIds,su.subjectName as subjectCode,bd.deptID as departmentId,bd.deptName as departmentName,pd.deptID as pDepartmentId, pd.deptName as pDepartmentName,su.subjectcatID as subjectCategoryId      
            FROM 
            (
                (    
                    SELECT sbs.sbsID, sbs.staffID, sbs.batchID, sbs.subjectID, sbs.semID, sbs.csID, sbs.isPseudosubject,null AS subbatches,ps.pseudosubjectID,ps.subjectName,'PseudoSubject' AS batchType,group_concat(distinct sbs.sbsID) as sbsIds,ps.hdl_deptID as handling_department, group_concat(distinct sbs.batchID) as batchIds
                    from pseudosubjects ps
                    INNER JOIN pseudosubjects_sbs psbs on ps.pseudosubjectID = psbs.pseudosubjectID
                    INNER JOIN sbs_relation sbs on psbs.sbsID = sbs.sbsID
                    ".implode(' AND ',$pssJoin)."
                    where ps.isFinalized = 1 ".($where?" AND ".implode(' AND ',$where):"")."
                    GROUP BY ps.pseudosubjectID, ".($studentSubjectGroupBy?"".implode(',',$studentSubjectGroupBy):"sbs.staffID")."
                )
                UNION ALL
                (
                    SELECT sbs.sbsID, sbs.staffID, sbs.batchID, sbs.subjectID, sbs.semID, sbs.csID, sbs.isPseudosubject,
                    concat('[',group_concat(JSON_OBJECT('subbatchID',sub.subbatchID,'subbatchName',sub.subbatchName)),']') AS subbatches,null AS pseudosubjectID, null AS subjectName, 'Sub-batch' AS batchType,group_concat(distinct sbs.sbsID) as sbsIds,null as handling_department, group_concat(distinct sbs.batchID) as batchIds
                    FROM subbatches sub
                    INNER JOIN subbatch_sbs ssbs ON ssbs.subbatchID = sub.subbatchID
                    INNER JOIN sbs_relation sbs ON sbs.sbsID = ssbs.sbsID AND sub.batchID = sbs.batchID 
                    ".implode(' AND ',$subJoin)."
                    WHERE sub.psID = 0 and ssbs.sbsID NOT IN (SELECT DISTINCT sbsID FROM pseudosubjects_sbs) ".($where?" AND ".implode(' AND ',$where):"")."
                    GROUP BY ".($studentSubjectGroupBy?"".implode(',',$studentSubjectGroupBy):"sbs.sbsID")."
                )
                UNION ALL
                (
                    SELECT sbs.sbsID, sbs.staffID, sbs.batchID, sbs.subjectID, sbs.semID, sbs.csID, sbs.isPseudosubject,null AS subbatches,null AS pseudosubjectID,null AS subjectName,'Subject' AS batchType,sbs.sbsID as sbsIds,null as handling_department, group_concat(distinct sbs.batchID) as batchIds
                    FROM sbs_relation sbs
                    ".implode(' AND ',$stdJoin)."
                    WHERE sbs.sbsID NOT IN (SELECT DISTINCT sbsID FROM subbatch_sbs) AND sbs.sbsID NOT IN (SELECT DISTINCT sbsID FROM pseudosubjects_sbs) ".($where?" AND ".implode(' AND ',$where):"")."
                    GROUP BY ".($studentSubjectGroupBy?"".implode(',',$studentSubjectGroupBy):"sbs.sbsID")."
                )
            ) AS s
            INNER JOIN batches bat ON bat.batchID = s.batchID
            INNER JOIN semesters currentsem ON currentsem.semID = bat.semID
            INNER JOIN semesters sem ON sem.semID = s.semID
            INNER JOIN subjects su ON su.subjectID = s.subjectID 
            INNER JOIN staffaccounts st ON st.staffID = s.staffID
            INNER JOIN department bd on bd.deptID = bat.deptID
            LEFT JOIN department pd on pd.deptID = s.handling_department
            " . ($basicCondition ? " WHERE " . implode(' AND ', $basicCondition) : "") . "
            GROUP BY s.sbsID,s.pseudosubjectID;";
        try {
            $staffDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    public function getSubjectPlanDetails($request)
    {
        $request = $this->realEscapeObject($request);
        $subjectPlans = new \stdClass();
        $subjectPlans->basicDetails = null;
        $subjectPlans->basicDetails = [];
        $subjectPlans->subjectPlans = [];
        $where = [];
        $orderBy = "desc";
        $isSession = CommonService::getInstance()->getSettings(SettingsConstants::SUBJECT_PLAN_SETTINGS, SettingsConstents::SUBJECT_PLAN_BY_SESSION);
        $sessionCase = $isSession ? "sp.session,":"";
        if(!empty($request->orderBy)){
            $orderBy = $request->orderBy;
        }
        if($request->fromDate && $request->toDate)
        {
            $where [] = " sp.date BETWEEN " . strtotime($request->fromDate) . " AND " . strtotime($request->toDate);
        }
        
        try 
        {
            if($request->subjectType == "pseudoSubjects")
            {
                $request->pseudoSubjectId?$where[] = " sp.pssId = $request->pseudoSubjectId ":"";
                $request->pseudoSubjectIds?$where[] = " sp.pssId in (".implode(',',$request->pseudoSubjectIds).") ":"";
                $request->mode?$where[] = " sp.mode = '$request->mode":"";
                $overAllSql = "SELECT count(sp.hour) as expectedHrs,count(subp.hour) as hrsTakenAttn,count(subp.isCovered) as topicCoverd,null as suspendedHrs,count(sp.hour) - count(subp.hour) as pendingHrs,count(sp.hour) - count(subp.hour) as neededHrs,count(cm.id) as materialGiven,count(cm1.id) as videoMatsGiven
                    FROM subjectplan_ps_proposed sp 
                    LEFT JOIN ps_subjectplan subp ON sp.topicID=subp.proposed_topicID 
                    LEFT JOIN ps_actual_plan_course_materials map ON map.actual_plan_id=subp.topicID
                    LEFT JOIN course_materials cm ON cm.id=map.course_material_id AND cm.is_active=1 
                    LEFT JOIN ps_proposed_plan_course_materials mpp ON mpp.proposed_plan_id=sp.topicID
                    LEFT JOIN course_materials cm1 ON  cm1.id=mpp.course_material_id AND cm.is_active=1 
                    LEFT JOIN ps_proposed_plan_video_materials pppvm on sp.topicID = pppvm.ps_proposed_plan_id
                    LEFT JOIN batch_video_repository bvr1 ON pppvm.video_repository_id = bvr1.id
                    LEFT JOIN ps_actual_plan_video_materials papvm on subp.topicID = papvm.ps_actual_plan_id    
                    LEFT JOIN batch_video_repository bvr on papvm.video_repository_id = bvr.id 
                    LEFT JOIN  (
                        SELECT MAX(isCovered) as finalStatus,proposed_topicID
                        FROM ps_subjectplan
                    ) AS temp ON temp.proposed_topicID=sp.topicID
                    ".($where?" WHERE ".implode(' AND ',$where):"")."
                    group by sp.pssId
                    ORDER BY $sessionCase sp.module,sp.date $orderBy,sp.hour;";
                $sql = "SELECT sp.topicID as proposedPlanId,subp.topicID as actualPlanId,FROM_UNIXTIME(sp.date, '%Y-%m-%d') as subjectPlanDate, sp.hour, sp.module, sp.topicName,'pseudoSubjects' as subjectType,sp.pssId as pseudoSubjectId,sp.topicDesc as proposedPlanTopicDesc, subp.topicDesc as actualPlanTopicDesc,sp.mode as mode_of_instruction,
                    case 
                    when subp.isCovered = '0' then 'Not covered'
                    when subp.isCovered = '1' then 'Partially covered'
                    when subp.isCovered = '2' then 'Fully covered'
                        else null 
                    END as covered,sp.isCovered, sp.day, sp.session,lr.path as actual_plan_url,lr1.path as proposed_plan_url, JSON_UNQUOTE(JSON_EXTRACT(sp.content, '$.learningOutcome')) AS learningOutcome,JSON_UNQUOTE(JSON_EXTRACT(sp.content, '$.skillDevelopment')) AS skillDevelopment, sp.pedagogy as teachingPedagogy
                    from subjectplan_ps_proposed sp
                    left join ps_subjectplan subp ON sp.topicID=subp.proposed_topicID and sp.pssId = subp.pssId
                    LEFT JOIN ps_proposed_plan_video_materials pppvm ON pppvm.ps_proposed_plan_id=sp.topicID
                    LEFT JOIN ps_actual_plan_video_materials papvm ON papvm.ps_actual_plan_id=subp.topicID
                    LEFT JOIN course_video_materials cvm ON cvm.id = papvm.video_repository_id
                    LEFT JOIN course_video_materials cvm1 ON cvm1.id = pppvm.video_repository_id
                    LEFT JOIN lin_resource lr ON lr.id = cvm.resource_id
                    LEFT JOIN lin_resource lr1 ON lr1.id = cvm1.resource_id
                    ".($where?" WHERE ".implode(' AND ',$where):"")."
                    ORDER BY $sessionCase sp.module,sp.date $orderBy,sp.hour ASC";
                if(!empty($where)){
                    $subjectPlans->basicDetails = $request->overallData?$this->executeQueryForList($overAllSql):null;
                    $subjectPlans->subjectPlans = $request->detailedData?$this->executeQueryForList($sql):null;
                }
            }
            else
            {
                $request->staffId?$where[] = " sr.staffID = '$request->staffId":"";
                $request->sbsId?$where[] = " sp.sbsID = '$request->sbsId":"";
                $request->batchId?$where[] = " sr.batchID = '$request->batchId":"";
                $request->semId?$where[] = " sr.semID = '$request->semId":"";
                $request->subjectId?$where[] = " sr.subjectID = '$request->subjectId":"";
                $request->mode?$where[] = " sp.mode = '$request->mode":"";
                $sql = "SELECT sp.sbsID,sp.topicID AS proposedPlanId,subp.topicID AS actualPlanId,FROM_UNIXTIME(sp.date, '%Y-%m-%d') AS subjectPlanDate, sp.hour, sp.module, sp.topicName, null as subjectType,sp.mode as mode_of_instruction,
                CASE 
                    WHEN subp.isCovered = '0' THEN 'Not covered'
                    WHEN subp.isCovered = '1' THEN 'Partially covered'
                    WHEN subp.isCovered = '2' THEN 'Fully covered'
                    else null 
                END AS covered,sp.isCovered, sp.day, sp.session,subp.topicDesc as actualPlanTopicDesc,sp.topicDesc as proposedPlanTopicDesc,lr.path as actual_plan_url,lr1.path as proposed_plan_url, JSON_UNQUOTE(JSON_EXTRACT(sp.content, '$.learningOutcome')) AS learningOutcome,JSON_UNQUOTE(JSON_EXTRACT(sp.content, '$.skillDevelopment')) AS skillDevelopment, sp.pedagogy as teachingPedagogy
                FROM subjectplan_proposed sp
                INNER JOIN sbs_relation sr ON sr.sbsID = sp.sbsID
                LEFT JOIN subjectplan subp ON sp.topicID = subp.proposed_topicID
                LEFT JOIN subject_actual_plan_video_materials sap ON sap.subject_actual_plan_id=subp.topicID
                LEFT JOIN course_video_materials cm ON cm.id=sap.video_repository_id
                LEFT JOIN subject_proposed_plan_video_materials spp ON spp.subject_proposed_plan_id=sp.topicID
                LEFT JOIN course_video_materials cm1 ON cm1.id=spp.video_repository_id
                LEFT JOIN lin_resource lr ON lr.id = cm.resource_id
                LEFT JOIN lin_resource lr1 ON lr1.id = cm1.resource_id
                ".($where?" WHERE ".implode(' AND ',$where):"")." ORDER BY $sessionCase sp.module,sp.date $orderBy,sp.hour ASC";
                $overAllSql = "SELECT count(sp.hour) as expectedHrs, count(sp.topicID) as noOfProposedPlans, count(ac.hour) as hrsTakenAttn, count(sh.hour) as suspendedHrs , count(sp.hour) - count(ac.hour) - count(sh.hour) as pendingHrs, count(sp.hour) - count(ac.hour) as neededHrs, count(sps.topicID) as subjectPlanCount,
                COUNT(CASE WHEN (sps.isCovered = 0) THEN 1 END) as notCovered,
                COUNT(CASE WHEN (sps.isCovered = 1) THEN 1 END) as partiallyCovered,
                COUNT(CASE WHEN (sps.isCovered = 2) THEN 1 END) as fullyCovered
                FROM subjectplan_proposed sp 
                inner join sbs_relation sr on sr.sbsID = sp.sbsID 
                left join subjectplan sps on sps.sbsID = sp.sbsID and sp.topicID = sps.proposed_topicID
                left join attendance_confirm ac on sp.sbsID = ac.sbsID and ac.attendanceDate = from_unixtime(sp.date) and sp.hour = ac.hour 
                left join suspended_hours sh on sh.suspendedDate = from_unixtime(sp.date) and sh.hour = sp.hour and sh.batchID = sr.batchID and sh.semID = sr.semID
                ".($where?" WHERE ".implode(' AND ',$where):"")."
                group by sp.sbsID
                order by $sessionCase sp.module,sp.date $orderBy,sp.hour;";
                if(!empty($where)){
                    $subjectPlans->subjectPlans = $request->detailedData?$this->executeQueryForList($sql):null;
                    $subjectPlans->basicDetails = $request->overallData?$this->executeQueryForObject($overAllSql):null;
                }
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $subjectPlans;
    }
    public function getSubjectCoursePlanDetails($request)
    {
        $request = $this->realEscapeObject($request);
        $subjectPlans = new \stdClass();
        $subjectPlans->basicDetails = null;
        $subjectPlans->basicDetails = [];
        $subjectPlans->subjectPlans = [];
        $where = [];
        $orderBy = "desc";
        $isSession = CommonService::getInstance()->getSettings(SettingsConstants::SUBJECT_PLAN_SETTINGS, SettingsConstents::SUBJECT_PLAN_BY_SESSION);
        $sessionCase = $isSession ? "sp.session,":"";
        if(!empty($request->orderBy)){
            $orderBy = $request->orderBy;
        }
        // if($request->fromDate && $request->toDate)
        // {
        //     $where [] = " sp.date BETWEEN " . strtotime($request->fromDate) . " AND " . strtotime($request->toDate);
        // }
        
        try 
        {
            if($request->subjectType == "pseudoSubjects")
            {
                $request->pseudoSubjectId?$where[] = " sp.pssId = $request->pseudoSubjectId ":"";
                $request->pseudoSubjectIds?$where[] = " sp.pssId in (".implode(',',$request->pseudoSubjectIds).") ":"";
                $request->mode?$where[] = " sp.mode = '$request->mode":"";
                $overAllSql = "SELECT count(sp.hour) as expectedHrs,count(subp.hour) as hrsTakenAttn,count(subp.isCovered) as topicCoverd,null as suspendedHrs,count(sp.hour) - count(subp.hour) as pendingHrs,count(sp.hour) - count(subp.hour) as neededHrs,count(cm.id) as materialGiven,count(cm1.id) as videoMatsGiven
                    FROM subjectplan_ps_proposed sp 
                    LEFT JOIN ps_subjectplan subp ON sp.topicID=subp.proposed_topicID 
                    LEFT JOIN ps_actual_plan_course_materials map ON map.actual_plan_id=subp.topicID
                    LEFT JOIN course_materials cm ON cm.id=map.course_material_id AND cm.is_active=1 
                    LEFT JOIN ps_proposed_plan_course_materials mpp ON mpp.proposed_plan_id=sp.topicID
                    LEFT JOIN course_materials cm1 ON  cm1.id=mpp.course_material_id AND cm.is_active=1 
                    LEFT JOIN ps_proposed_plan_video_materials pppvm on sp.topicID = pppvm.ps_proposed_plan_id
                    LEFT JOIN batch_video_repository bvr1 ON pppvm.video_repository_id = bvr1.id
                    LEFT JOIN ps_actual_plan_video_materials papvm on subp.topicID = papvm.ps_actual_plan_id    
                    LEFT JOIN batch_video_repository bvr on papvm.video_repository_id = bvr.id 
                    LEFT JOIN  (
                        SELECT MAX(isCovered) as finalStatus,proposed_topicID
                        FROM ps_subjectplan
                    ) AS temp ON temp.proposed_topicID=sp.topicID
                    ".($where?" WHERE ".implode(' AND ',$where):"")."
                    group by sp.pssId
                    ORDER BY $sessionCase sp.module,sp.date $orderBy,sp.hour;";
                $sql = "SELECT sp.topicID as proposedPlanId,subp.topicID as actualPlanId,FROM_UNIXTIME(sp.date, '%Y-%m-%d') as subjectPlanDate, sp.hour, sp.module, sp.topicName,'pseudoSubjects' as subjectType,sp.pssId as pseudoSubjectId,sp.topicDesc as proposedPlanTopicDesc, subp.topicDesc as actualPlanTopicDesc,sp.mode as mode_of_instruction,
                    case 
                    when subp.isCovered = '0' then 'Not covered'
                    when subp.isCovered = '1' then 'Partially covered'
                    when subp.isCovered = '2' then 'Fully covered'
                        else null 
                    END as covered,sp.isCovered, sp.day, sp.session,lr.path as actual_plan_url,lr1.path as proposed_plan_url, JSON_UNQUOTE(JSON_EXTRACT(sp.content, '$.learningOutcome')) AS learningOutcome,JSON_UNQUOTE(JSON_EXTRACT(sp.content, '$.skillDevelopment')) AS skillDevelopment, sp.pedagogy as teachingPedagogy
                    from subjectplan_ps_proposed sp
                    left join ps_subjectplan subp ON sp.topicID=subp.proposed_topicID and sp.pssId = subp.pssId
                    LEFT JOIN ps_proposed_plan_video_materials pppvm ON pppvm.ps_proposed_plan_id=sp.topicID
                    LEFT JOIN ps_actual_plan_video_materials papvm ON papvm.ps_actual_plan_id=subp.topicID
                    LEFT JOIN course_video_materials cvm ON cvm.id = papvm.video_repository_id
                    LEFT JOIN course_video_materials cvm1 ON cvm1.id = pppvm.video_repository_id
                    LEFT JOIN lin_resource lr ON lr.id = cvm.resource_id
                    LEFT JOIN lin_resource lr1 ON lr1.id = cvm1.resource_id
                    ".($where?" WHERE ".implode(' AND ',$where):"")."
                    ORDER BY $sessionCase sp.module,sp.date $orderBy,sp.hour ASC";
                if(!empty($where)){
                    $subjectPlans->basicDetails = $request->overallData?$this->executeQueryForList($overAllSql):null;
                    $subjectPlans->subjectPlans = $request->detailedData?$this->executeQueryForList($sql):null;
                }
            }
            else
            {
                $request->staffId?$where[] = " sr.staffID = '$request->staffId":"";
                $request->sbsId?$where[] = " sp.sbsID = '$request->sbsId":"";
                $request->batchId?$where[] = " sr.batchID = '$request->batchId":"";
                $request->semId?$where[] = " sr.semID = '$request->semId":"";
                $request->subjectId?$where[] = " sr.subjectID = '$request->subjectId":"";
                $request->mode?$where[] = " sp.mode = '$request->mode":"";
                $sql = "SELECT sp.sbsID,sp.topicID AS proposedPlanId,subp.topicID AS actualPlanId,FROM_UNIXTIME(sp.date, '%Y-%m-%d') AS subjectPlanDate, sp.hour, sp.module, sp.topicName, null as subjectType,sp.mode as mode_of_instruction,
                CASE 
                    WHEN subp.isCovered = '0' THEN 'Not covered'
                    WHEN subp.isCovered = '1' THEN 'Partially covered'
                    WHEN subp.isCovered = '2' THEN 'Fully covered'
                    else null 
                END AS covered,sp.isCovered, sp.day, sp.session,subp.topicDesc as actualPlanTopicDesc,sp.topicDesc as proposedPlanTopicDesc,lr.path as actual_plan_url,lr1.path as proposed_plan_url, JSON_UNQUOTE(JSON_EXTRACT(sp.content, '$.learningOutcome')) AS learningOutcome,JSON_UNQUOTE(JSON_EXTRACT(sp.content, '$.skillDevelopment')) AS skillDevelopment, sp.pedagogy as teachingPedagogy
                FROM subjectplan_proposed sp
                INNER JOIN sbs_relation sr ON sr.sbsID = sp.sbsID
                LEFT JOIN subjectplan subp ON sp.topicID = subp.proposed_topicID
                LEFT JOIN subject_actual_plan_video_materials sap ON sap.subject_actual_plan_id=subp.topicID
                LEFT JOIN course_video_materials cm ON cm.id=sap.video_repository_id
                LEFT JOIN subject_proposed_plan_video_materials spp ON spp.subject_proposed_plan_id=sp.topicID
                LEFT JOIN course_video_materials cm1 ON cm1.id=spp.video_repository_id
                LEFT JOIN lin_resource lr ON lr.id = cm.resource_id
                LEFT JOIN lin_resource lr1 ON lr1.id = cm1.resource_id
                ".($where?" WHERE ".implode(' AND ',$where):"")." ORDER BY $sessionCase sp.module,sp.date $orderBy,sp.hour ASC";
                $overAllSql = "SELECT count(sp.hour) as expectedHrs, count(sp.topicID) as noOfProposedPlans, count(ac.hour) as hrsTakenAttn, count(sh.hour) as suspendedHrs , count(sp.hour) - count(ac.hour) - count(sh.hour) as pendingHrs, count(sp.hour) - count(ac.hour) as neededHrs, count(sps.topicID) as subjectPlanCount,
                COUNT(CASE WHEN (sps.isCovered = 0) THEN 1 END) as notCovered,
                COUNT(CASE WHEN (sps.isCovered = 1) THEN 1 END) as partiallyCovered,
                COUNT(CASE WHEN (sps.isCovered = 2) THEN 1 END) as fullyCovered
                FROM subjectplan_proposed sp 
                inner join sbs_relation sr on sr.sbsID = sp.sbsID 
                left join subjectplan sps on sps.sbsID = sp.sbsID and sp.topicID = sps.proposed_topicID
                left join attendance_confirm ac on sp.sbsID = ac.sbsID and ac.attendanceDate = from_unixtime(sp.date) and sp.hour = ac.hour 
                left join suspended_hours sh on sh.suspendedDate = from_unixtime(sp.date) and sh.hour = sp.hour and sh.batchID = sr.batchID and sh.semID = sr.semID
                ".($where?" WHERE ".implode(' AND ',$where):"")."
                group by sp.sbsID
                order by $sessionCase sp.module,sp.date $orderBy,sp.hour;";
                if(!empty($where)){
                    $subjectPlans->subjectPlans = $request->detailedData?$this->executeQueryForList($sql):null;
                    $subjectPlans->basicDetails = $request->overallData?$this->executeQueryForObject($overAllSql):null;
                }
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $subjectPlans;
    }
    public function getStaffWorkingBatches($request)
    {
        $request->staffId?$where[]=" sbs.staffID = $request->staffId ":null;
        $request->sbsId?$where[]=" sbs.sbsID = $request->sbsId ":null;
        $request->hourId?$where[]=" ac.hour = $request->hourId ":null;
        if( $request->fromDate && $request->toDate )
        {
            $where[]=" ac.attendanceDate BETWEEN '".date('Y-m-d',strtotime($request->fromDate))."' AND '".date('Y-m-d',strtotime($request->toDate))."' ";
        }
        else
        {
            $request->fromDate?$where[]=" ac.attendanceDate >= '".date('Y-m-d',strtotime($request->fromDate))."' ":null;
            $request->toDate?$where[]=" ac.attendanceDate <= '".date('Y-m-d',strtotime($request->toDate))."' ":null;
        }
        try {
            if (!empty($where)) {
                $staffWorking = new \stdClass();
                    $sqlCount = "select sbs.sbsID,count(ac.batchID) as workinghours,sbs.batchID,bat.batchName,s.subjectID,s.subjectName,s.subjectDesc,sem.semName as semesterName 
                    from attendance_confirm ac
                    inner join sbs_relation sbs on ac.sbsID = sbs.sbsID 
                    inner join batches bat on sbs.batchID = bat.batchID 
                    inner join semesters sem on sem.semID = sbs.semID 
                    inner join subjects s on s.subjectID = sbs.subjectID
                    ".($where?" WHERE ".implode(' AND ',$where):"")."
                    group by ac.sbsID;";
                if($request->subjectType == 'subBatch'){
                    $sqlData = "select ac.attendanceDate,ac.hour,sbs.sbsID,sbs.batchID,sub.subbatchName,sub.subbatchID,bat.batchName,s.subjectID,s.subjectName,s.subjectDesc,sem.semName as semesterName,
                    group_concat(distinct (JSON_OBJECT('subbatchName',sub.subbatchName,'subbatchId',ac.subbatchId ))) as subbatch,count(CASE WHEN (att.isAbsent = 0) THEN 1 END) as presentCount,count(CASE WHEN (att.isAbsent = 1) THEN 1 END) as absentCount,count(CASE WHEN (att.isAbsent = 2) THEN 1 END) as dutyLeave,count(distinct std.studentID) as studentCount,
                    bat.batchStartYear
                    from attendance_confirm ac
                    inner join sbs_relation sbs on ac.sbsID = sbs.sbsID 
                    inner join subbatch_sbs ssbs on ssbs.sbsID = sbs.sbsID
                    inner join subbatches sub on sub.subbatchID = ssbs.subbatchID and ac.subbatchID = sub.subbatchID
                    inner join subbatch_student std on std.subbatchID = sub.subbatchID
                    inner join batches bat on sbs.batchID = bat.batchID
                    inner join semesters sem on sem.semID = sbs.semID 
                    inner join subjects s on s.subjectID = sbs.subjectID
                    left join attendance att on att.sbsID = sbs.sbsID and att.staffID = sbs.staffID and att.hour = ac.hour and ac.attendanceDate = att.attendanceDate and std.studentID = att.studentID
                    ".($where?" WHERE ".implode(' AND ',$where):"")."
                    group by ac.attendanceDate,ac.hour,ac.subbatchID
                    order by bat.batchStartYear desc,ac.attendanceDate desc,ac.hour;";
                }
                else
                {
                    $sqlData = "select ac.attendanceDate,ac.hour,sbs.sbsID,sbs.batchID,null as subbatchName,null as subbatchID,null as subbatch,bat.batchName,s.subjectID,s.subjectName,s.subjectDesc,sem.semName as semesterName,COUNT(CASE WHEN (att.isAbsent = 0) THEN 1 END) as presentCount,
                    COUNT(CASE WHEN (att.isAbsent = 1) THEN 1 END) as absentCount,count(distinct att.studentID) as studentCount,bat.batchStartYear
                    from attendance_confirm ac
                    inner join sbs_relation sbs on ac.sbsID = sbs.sbsID 
                    inner join batches bat on sbs.batchID = bat.batchID
                    inner join semesters sem on sem.semID = sbs.semID 
                    inner join subjects s on s.subjectID = sbs.subjectID
                    inner join attendance att on att.sbsID = sbs.sbsID and att.staffID = sbs.staffID and att.hour = ac.hour and ac.attendanceDate = att.attendanceDate 
                    ".($where?" WHERE ".implode(' AND ',$where):"")."
                    group by ac.hour,ac.attendanceDate order by bat.batchStartYear desc,ac.attendanceDate desc,ac.hour;";
                }
                $staffWorking->count = $request->overallData ? $this->executeQueryForList($sqlCount) : null;
                $staffWorking->data = $request->detailedData ? $this->executeQueryForList($sqlData) : null;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffWorking;
    }
    /**
     * //approve subject plan....
     * @param $staffId
     * @return bool
     * @throws ProfessionalException
     */
    public function approveSubjectProposedPlanByPrinciple($request)
    {
        $request = $this->realEscapeObject($request);
        try 
        {
            $table = $request->pseudosubjectId?" subjectplan_ps_proposed ":" subjectplan_proposed ";
            $sql = "UPDATE $table SET `verify`='$request->verify', updated_by = '$request->currentStaff', updated_date = utc_timestamp() WHERE `topicID`='$request->topicId' AND approve = 1";
            $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function approveAllSubjectProposedPlanByPrinciple($request)
    {
        $request = $this->realEscapeObject($request);
        try {
            if ($request->fromDate && $request->toDate) {
                $fromDate = date("Y-m-d", strtotime($request->fromDate));
                $toDate = date("Y-m-d", strtotime($request->toDate));
                $condition .= " and sp.date between unix_timestamp('$fromDate') and unix_timestamp('$toDate')";
            } else if ($toDate) {
                $toDate = date("Y-m-d", strtotime($request->toDate));
                $condition .= " and sp.date <= unix_timestamp('$toDate')";
            } else if ($request->fromDate) {
                $fromDate = date("Y-m-d", strtotime($request->fromDate));
                $condition .= " and sp.date >= unix_timestamp('$fromDate')";
            }
            $condition .= $request->hodApprovalRequired?" and sp.approve = 1 ":"";
            if($request->pseudosubjectId)
            {
                $sql = "UPDATE subjectplan_ps_proposed sp SET sp.verify='$request->verify' WHERE sp.pssId = '$request->pseudosubjectId' AND sp.approve = 1 $condition ;";
            }
            else
            {
                $condition .= $request->sbsId?" and sbs.sbsID = $request->sbsId ":"";
                $condition .= $request->subjectId?" and sbs.subjectID = '$request->subjectId":""; 
                $condition .= $request->batchId?" and sbs.batchID = '$request->batchId":"";
                $condition .= $request->semId?" and sbs.semID = '$request->semId":"";
                $condition .= $request->staffId?" and sbs.staffId = $request->staffId ":"";
                $sql = "UPDATE subjectplan_proposed sp 
                    INNER JOIN sbs_relation sbs on sbs.sbsID = sp.sbsID
                    SET sp.verify = '$request->verify
                    WHERE sp.approve = 1 $condition;";
            }
            $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @param $staffId
     * @return Object
     * @throws ProfessionalException
     */
    public function getStaffDepartmentDetails($staffId)
    {
        $staffId = $this->realEscapeString($staffId);
        if (empty($staffId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_STAFF_ID, "Invalid staff details given");
        }
        
        $sql = "SELECT sa.staffID as staffId,d.deptID as departmentId 
                FROM staffaccounts sa 
                INNER JOIN department d on sa.deptID = d.deptID 
                WHERE staffID= $staffId";
        try {
            return $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function getConsolidateStaffWorkingHours($request)
    {
        $request = $this->realEscapeObject($request);
        try 
        {
            $request->staffId?$where[] = " sbs.staffID = $request->staffId ":"";
            $request->batchId?$where[] = " sbs.batchID = $request->batchId ":"";
            $request->deptId?$where[] = " bat.deptID = $request->deptId ":"";
            $request->fromDate && $request->toDate?$where[] = " ac.attendanceDate between '$request->fromDate' and '$request->toDate":"";
            
            $sql = "select sbs.staffID,ac.attendanceDate,st.staffName,count(distinct ac.hour,sbs.subjectID) as dayCount from attendance_confirm ac
            inner join sbs_relation sbs on sbs.sbsID = ac.sbsID
            inner join staffaccounts st on st.staffID =  sbs.staffID
            inner join batches bat on bat.batchID = sbs.batchID
            ".($where?" WHERE ".implode(' AND ',$where):"")."
            group by ac.attendanceDate,sbs.staffID
            order by sbs.staffID,ac.attendanceDate;";
            return $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    function getStaffAchievementsByStaffId($staffId){
        $staffId = $this->realEscapeString($staffId);
        try {
            $sql = "SELECT t1.id, t1.notes, t1.achievement_date, t2.name as status, t3.name as category, t1.appraisal_staff_category_id, t3.mark FROM appraisal_staff_achievements t1, appraisal_staff_status t2, appraisal_staff_category t3 WHERE t1.staffaccounts_id = ".$staffId." AND t1.appraisal_status_id = t2.id AND t1.appraisal_staff_category_id = t3.id ORDER BY t1.id DESC;";
            return $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    
    function checkInstanceIsCorrect($request){
        try {
            //code...
            $response = new \stdClass();
            $response->isRightUrl = false;
            $response->higherAccess = false;
            if($request->userId && $request->staffId){
                $response->isRightUrl = $this->isFacultyIsHODOrPrincipalOrERPAdmin($request->staffId);
                $response->subjectAssigned = $this->isStaffAssignedToPseudoSub($request->pseudoSubjectId, $request->userId);
                $response->higherAccess = true;
                $response->staffId = $request->userId;
            }else{
                if($request->staffId){
                    $response->isRightUrl = true;
                    $response->subjectAssigned = $this->isStaffAssignedToPseudoSub($request->pseudoSubjectId, $request->staffId);
                    $response->staffId = $request->staffId;
                }else{
                    $response->subjectAssigned = false;
                }
            }
            return $response;
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Checks if the staff is or was a tutor
     *
     * @param int $staffId
     * @return boolean
     * @throws ProfessionalException
     */
    public function staffIsOrWasTutor($staffId)
    {
        $staffId = $this->realEscapeString($staffId);
        $sql = "SELECT COUNT(staffID) as count from batch_tutor bt 
                INNER JOIN batches ba on ba.batchID = bt.batchID  where staffID = $staffId";
        try {
            $count = $this->executeQueryForObject($sql)->count;
            if ($count) {
                return true;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return false;
    }
    /**
     * get staff details by subject
     *
     * @param int $subjectId
     * @param int $batchId
     * @param int $semId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffSbsBySubject($subjectId, $batchId, $semId, $subbatchID)
    {
        $batchId = $this->realEscapeString($batchId);
        $semId = $this->realEscapeString($semId);
        $subjectId = $this->realEscapeString($subjectId);
        $subbatchID = $this->realEscapeString($subbatchID);
        $subbatchCond = "";
        if ($subbatchID) {
            $subbatchCond = " and ss.subbatchID = $subbatchID";
        }
        $sql = "SELECT distinct sr.staffID, sr.sbsID from sbs_relation sr  left join subbatch_sbs ss on sr.sbsID = ss.sbsID where sr.subjectID=$subjectId AND sr.batchID=$batchId AND sr.semID=$semId  $subbatchCond ";
        try {
            $staffDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    
    /*
     * TODO::ASSROLL
     * Get all staff with the history of $request(ed) subject
     * @thows PrefessionalException
     */
    public function getAllStaffsWithPreviousHistoryOfaSubject($request){
        $request = $this->realEscapeObject($request);
        $subQuery = " SELECT null as staff_id, null as paperSubjectId, null as departmentId, null as subjectId ";
        $where = [];
        $request->getAllStaff ? "" : $where [] = " st.isResigned = 0 ";
        if ( $request->subjectPaperId || $request->subjectId ) {
            if ( $request->subjectId ) {
                $subjectId = $request->subjectId;
            } else {
                $subjectId = "SELECT ams_subject_id FROM cm_academic_paper_subjects WHERE id = '$request->subjectPaperId'";
            }
            $subQuery = "SELECT 
                            cm.staff_id, 
                            sg.paperSubjectId, 
                            sub.department_id as departmentId, 
                            sub.id as subjectId
                        FROM 
                            `cluster_members` cm
                                INNER JOIN 
                            `cluster_groups_relations` cg ON cg.cluster_id = cm.cluster_id
                                INNER JOIN 
                            `groups` sg ON sg.id = cg.groups_id
                                INNER JOIN 
                            `cm_academic_paper_subjects` aps ON aps.id = sg.paperSubjectId
                                INNER JOIN 
                            `v4_ams_subject` sub ON sub.id = aps.ams_subject_id
                                INNER JOIN 
                            `department` sd ON sd.deptID = sub.department_id
                        WHERE 
                            aps.ams_subject_id IN ($subjectId";
        }
        $sql = "SELECT 
                    st.staffID AS `id`,
                    st.staffName AS `name`,
                    if(sum(IF(st.staffID = ast.staff_id,1,0)),'true','false') AS `history_in_subject`,
                    case 
                        when sum(IF(st.staffID = ast.staff_id,1,0)) then 0 
                        when ast.departmentId = st.deptID then 1
                    else 2 end as _order,
                    st.staffCode AS `code`,
                    JSON_OBJECT('id',d.deptID,'name',d.deptName,'description',d.departmentDesc) AS `department`,
                    st.isResigned
                FROM 
                    `staffaccounts` st
                        INNER JOIN 
                    `department` d ON d.deptID = st.deptID
                        LEFT JOIN (
                            $subQuery
                        ) AS ast ON 1 = 1 
                ".(count($where) ? ' WHERE '.implode(' AND ',$where) : "")."
                GROUP BY st.staffID
                ORDER BY 
                    sum(IF(st.staffID = ast.staff_id,1,0)) DESC, 
                    ast.departmentId = st.deptID DESC;";
        try {
            $staffDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException(ProfessionalException::ERROR_FETCHING, "Error occurred while fetching staffs");
        }
        return $staffDetails ;
    }
    /**
     * get exammark external staff by examId
     *
     * @param int $examId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function  examMarkExternalStaffByExam($examId, $valuationCount = NULL)
    {
        $examId = $this->realEscapeString($examId);
        $valuationCount = $this->realEscapeString($valuationCount);
        $staffIds = "";
        try {
            if (($valuationCount == 2) || ($valuationCount == 3)){
                $sql = "SELECT distinct staffID from external_exammarks where examID = '$examId' and valuationCount='$valuationCount'";
            }else{
                $sql = "SELECT distinct staffID from exammarks_external where examID = '$examId'";
            }
           $staffIds = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffIds ;
    }
    /**
     * get exammark external staff by examId
     *
     * @param int $examId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function  assignExamValuationFaculty($request)
    {
        $request = $this->realEscapeObject($request);
        $staffIds = "";
        $result=null;
        $existing = new \stdClass;
        try {
            $staffIds = implode(",",$request->staffIds);
            //check staffs already assigned in any valuation type for the same exam
            if($request->valuationCountSelected == 2 || $request->valuationCountSelected == 3){
                $isExistSql = "SELECT examID,staffIDs,valuationType from externalexam_valuation_staffs where examID = '$request->examId' AND valuationCount='$request->valuationCountSelected'";
            }else{
                $isExistSql = "SELECT examID,staffIDs,valuationType from exam_valuation_staffs where examID = '$request->examId'";
            }
            if($request->enableValuationType){
                //Insert staff asignation with valuation type
                if ($request->valuationCountSelected == 2 || $request->valuationCountSelected == 3) {
                    $deleteSql = "DELETE from externalexam_valuation_staffs where examID = '$request->examId' AND valuationCount='$request->valuationCountSelected' AND valuationType='$request->enableValuationType'";
                    $this->executeQueryForObject($deleteSql);
                    $sql = "INSERT into externalexam_valuation_staffs(examID, staffIDs,valuationCount,valuationType) values('$request->examId', '$staffIds','$request->valuationCountSelected','$request->enableValuationType')";
                } else {
                    $deleteSql = "DELETE from exam_valuation_staffs where examID = '$request->examId' AND valuationType='$request->enableValuationType'";
                    $this->executeQueryForObject($deleteSql);
                    $sql = "INSERT into exam_valuation_staffs(examID, staffIDs,valuationType) values('$request->examId', '$staffIds','$request->enableValuationType')";
                }
                $alreadyAssined = $this->executeQueryForObject($isExistSql);
                if($alreadyAssined){
                    $existing->valuationType = $alreadyAssined->valuationType ? $alreadyAssined->valuationType : "NORMAL_VALUATION";
                    $existing->alreadyExist = true;
                    return $existing;
                }
                if ($request->staffIds) {
                    $this->executeQueryForObject($sql);
                }
            }else{
                //Insert staff asignation without valuation type
                if($request->valuationCountSelected == 2 || $request->valuationCountSelected == 3){
                    $deleteSql = "DELETE from externalexam_valuation_staffs where examID = '$request->examId' AND valuationCount='$request->valuationCountSelected' AND valuationType is null";
                    $this->executeQueryForObject($deleteSql);
                    $sql = "INSERT into externalexam_valuation_staffs(examID, staffIDs,valuationCount) values('$request->examId', '$staffIds','$request->valuationCountSelected')";
                }else{
                    $deleteSql = "DELETE from exam_valuation_staffs where examID = '$request->examId' AND valuationType is null ";
                    $this->executeQueryForObject($deleteSql);
                    $sql = "INSERT into exam_valuation_staffs(examID, staffIDs) values('$request->examId', '$staffIds')";
                    }
                if ($request->staffIds) {
                    $this->executeQueryForObject($sql);
                }
            }
            $result=true;
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $result;
    }
    /**
     * get staff By staffIds
     *
     * @param int $examId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function  getStaffByStaffIds($staffIds)
    {
        $staffIds = $this->realEscapeString($staffIds);
        $staffs = null;
        try {
            if ($staffIds) {
                $sql ="SELECT staffID as staffId,staffName from staffaccounts where staffID IN($staffIds)";
                $staffs = $this->executeQueryForList($sql);
            }
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return
        $staffs;
    }
    /**
     * get staff By staffIds
     *
     * @param int $examId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function  assignStudentsToExamValuationStaffs($request)
    {
        $request = $this->realEscapeObject($request);
        $insertValues = [];
        $insertValuesString="";
        $uncheckedStudentsString ="";
        $insertSql="";
        $deleteSql="";
        $adminId =$_SESSION['adminID'];
        try {
            if(!empty($request->selectedStudents)){
                foreach($request->selectedStudents as $selectedStudent){
                    $selectedStudent = (object)$selectedStudent;
                    $insertValues [] = "('$selectedStudent->studentID','$request->examRegId','$request->subjectId','$request->staffId','$request->valuationCount','$adminId','$request->examType')";
                }
                $insertValuesString = implode(",",$insertValues);
                $insertSql = "INSERT INTO examValuationStaffAssignedStudents(studentId,examRegId,subjectId,staffId,valuationCount,created_by,examType) VALUES $insertValuesString
                                ON DUPLICATE KEY UPDATE staffId = VALUES(staffId)";
                $this->executeQueryForObject($insertSql);
            }
            if(!empty($request->uncheckedStudents)){
                $uncheckedStudentsString = implode(",", array_column($request->uncheckedStudents, 'studentID'));
                $deleteSql = "DELETE from examValuationStaffAssignedStudents where examRegId='$request->examRegId' AND examType = '$request->examType' AND subjectId = '$request->subjectId' AND valuationCount = '$request->valuationCount' AND studentId IN($uncheckedStudentsString)";
                $this->executeQueryForObject($deleteSql);
            }
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return true;
    }
    /**
     * get Exams Assigned For Valuation By staff
     *
     * @param int $request
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function  getExamsAssignedForValuationByStaff($request)
    {
        $request = $this->realEscapeObject($request);
        $valuationCountCondition="";
        $condition = $groupBy = "";
        $examRegField = ($request->examType == ExamType::SUPPLY) ? "supply_examreg_id" : "examregID";
        if($request->valuationCount == 2 || $request->valuationCount == 3){
            $tableName = "externalexam_valuation_staffs evs";
            $valuationCountCondition = " AND evs.valuationCount='$request->valuationCount'";
        }else{
            $tableName ="exam_valuation_staffs evs";
        }
        if($request->examRegId){
            $condition .=" AND e.$examRegField IN ('$request->examRegId')";
        }
        if($request->batchId){
            $condition .=" AND e.batchID IN ('$request->batchId') ";
        }
        if($request->groupBySubject){
            $groupBy = "group by e.subjectID";
        }
        if(!$request->includeAllExams){
            $condition .=" AND e.examID not in (select exam_id from assignstaff_exam_group_relation)";
        }
        if($request->examId){
            $condition .= "AND e.examID IN ($request->examId)";
        }
        if($request->valuationCount){
            $valuationCountField = ", IF($request->valuationCount ,$request->valuationCount,1) as valuationCount";
        }
        if($request->staffId){
            $joinStaff = " AND FIND_IN_SET('$request->staffId',evs.staffIDs)";
        }
        if($request->valuationType){
            $condition .= "AND evs.valuationType = '$request->valuationType'";
        }
        if($request->deptId){
            $condition .= " AND s.hdl_deptID IN ($request->deptId)";
        }
        $exams = null;
        try {
                $sql = "SELECT 
                            e.batchID as 'batchId',
                            b.batchName,
                            b.batchDesc,
                            e.semID as 'semId',
                            e.examID AS examId, 
                            e.examName AS examName,
                            e.subjectID as 'subjectId',
                            s.subjectName,
                            s.subjectDesc,
                            evs.staffIDs,
                            e.examregID as examRegId
                            $valuationCountField
                        FROM
                            exam e 
                            INNER JOIN batches b ON b.batchID = e.batchID 
                            INNER JOIN subjects s ON s.subjectID = e.subjectID
                            INNER JOIN $tableName ON evs.examID = e.examID $joinStaff
                        WHERE
                            1 = 1
                            $condition $valuationCountCondition $groupBy";
                $exams = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $exams;
    }
    /**
     * get Students For Exam Valuation By Staff
     *
     * @param int $examId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function  getStudentsForExamValuationByStaff($request)
    {
        $request = $this->realEscapeObject($request);
        $getFalseNumber="";
        $falseNoField="";
        $failedStudentTables ="";
        $condition="";
        $failedStudentCondition ="sa.batchID = '$request->batchId'";
        $examRegField = ($request->examType == ExamType::SUPPLY) ? "exam_supplementary_id" : "examregID";
        $falseNumberJoin = $request->includeStudentWithoutFalseNumber ? " LEFT JOIN " : " INNER JOIN ";
        if($request->showStudentsByFalseNumber){
            if ($request->getRegularExamFalseNumber) {
                $getFalseNumber = "$falseNumberJoin examcontroller_false_number efn ON efn.studentID = esas.studentID AND efn.examregID = $request->regularExamRegId AND efn.examID = $request->regularExamId";
            }else{
                $getFalseNumber = "$falseNumberJoin examcontroller_false_number efn ON efn.studentID = esas.studentID AND efn.$examRegField = esas.examRegId AND efn.examID = '$request->examId'";
            }
            $falseNoField = " , efn.false_number AS falseNumber";
        }
        if($request->examId){
            $examIdValue = " , $request->examId as examId ";
        }
        if($request->examType == ExamType::SUPPLY){
            $failedStudentTables = "INNER JOIN exam_supplementary es ON es.id = esas.examRegId
                                    LEFT JOIN failed_students fs ON fs.studentID = esas.studentID AND FIND_IN_SET(es.semID, fs.hisSemestersInThisbatch)";
            $failedStudentCondition =" IF (fs.previousBatch, fs.previousBatch, sa.batchID) = '$request->batchId'";
        }
        $failedStudentCondition = $request->batchId ? $failedStudentCondition : " 1=1 ";
        if($request->studentIds){
            $condition .=" AND sa.studentID IN ($request->studentIds)";
        }
        if($request->staffId){
            $condition .=" AND esas.staffId='$request->staffId";
        }
        $studentList = [];
        try {
                $sql = "SELECT esas.studentId,
                                sa.regNo,sa.studentName,
                                esas.examRegId,
                                esas.subjectId,
                                esas.staffId,
                                esas.examType,
                                esas.valuationCount,
                                sa.batchID as batchId 
                                $falseNoField
                                $examIdValue
                                FROM examValuationStaffAssignedStudents esas
                                INNER JOIN studentaccount sa ON sa.studentID = esas.studentID
                                $getFalseNumber
                                $failedStudentTables 
                                WHERE esas.examRegId='$request->examRegId
                                and esas.subjectId='$request->subjectId'
                                and $failedStudentCondition
                                and esas.valuationCount='$request->valuationCount'
                                and esas.examType = '$request->examType'
                                $condition
                                ORDER BY sa.regNo";
                $studentList = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return  $studentList;
    }
    /**
     * get Batch Exam Valuation Dates
     *
     * @param int $examId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function  getBatchExamValuationDates($request)
    {
        $request = $this->realEscapeObject($request);
        $valuationDates = null;
        if($request->valuationCount == 1){
            $dateColumns = "firstval_Datestart as valStartDate,firstval_Dateend as valEndDate";
        }
        else if ($request->valuationCount == 2){
            $dateColumns = "secondval_Datestart as valStartDate,secondval_Dateend as valEndDate";
        }
        try {
            $sql = "SELECT $dateColumns
                           from valuationdates 
                           WHERE examregID='$request->examRegId' AND batchID='$request->batchId' AND examType = '$request->examType'";
            $valuationDates = $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return  $valuationDates;
    }
    /** method to get hod details by batchID
     *
     * @param int $batchID
     * @return Object staffdetails
     * @throws ProfessionalException
     */
    public function getHodDetailsByBatchId($batchID)
    {
        $batchID = $this->realEscapeString($batchID);
        $sql = "SELECT 
                    sa.isHod,
                    sa.staffName,
                    sa.staffID,
                    sa.staffPhone,
                    sa.staffEmail
                FROM
                    staffaccounts sa
                        INNER JOIN
                    department dept ON sa.deptID = dept.deptID
                        INNER JOIN
                    batches bth ON bth.deptID = dept.deptID
                WHERE
                    sa.isHOD = 1 AND bth.batchID = '$batchID";
        try {
            $staffDetails = $this->executeQueryForObject($sql);
            return $staffDetails;
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /** Method to get hod list by batchID
     * It returns HOD, HOD in-charge who all are not resigned
     *
     * @param int $batchID
     * @return Object staffdetails
     * @throws ProfessionalException
     */
    public function getHodListByBatchId($batchID)
    {
        $batchID = $this->realEscapeString($batchID);
        $sql = "SELECT 
                    sa.isHod,
                    sa.staffName,
                    sa.staffID,
                    sa.staffPhone,
                    sa.staffEmail
                FROM
                    staffaccounts sa
                        INNER JOIN
                    department dept ON sa.deptID = dept.deptID
                        INNER JOIN
                    batches bth ON bth.deptID = dept.deptID
                WHERE
                    sa.isHOD > 0 
                    AND sa.isResigned = 0 
                    AND bth.batchID = '$batchID";
        try {
            return $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    
    /**
     * method to get staff details who marked attendance
     *
     * @param Int batchID, semID, attendanceDate, hour
     * @return Object staffdetails
     * @throws ProfessionalException
     */
    public function getAttendanceMarkedStaffDetails($attendanceDate,$batchID,$semID,$hour)
    {
        $sql = "SELECT DISTINCT(a.staffID),sa.staffName, sa.staffCode,s.subjectID,CASE WHEN ps.pseudosubjectID IS NOT null THEN ps.subjectName ELSE s.subjectName END as subjectName,s.subjectDesc,s.subjectcatID,sbs.isPseudosubject  
                FROM attendance a 
                    INNER JOIN staffaccounts sa  ON a.staffID = sa.staffID 
                    INNER JOIN sbs_relation sbs ON sbs.sbsID = a.sbsID AND sbs.staffID = sa.staffID 
                    INNER JOIN subjects s ON s.subjectID = sbs.subjectID  
                    LEFT JOIN pseudosubjects_sbs psbs ON psbs.sbsID = sbs.sbsID
                    LEFT JOIN pseudosubjects ps ON ps.pseudosubjectID = psbs.pseudosubjectID
                WHERE  a.attendanceDate = '$attendanceDate'
                    AND a.hour = '$hour'
                    AND a.batchID = '$batchID'
                    AND a.semID = '$semID'";
        // $sql = "SELECT 
        //             sa.staffID , sa.staffName, sa.staffCode
        //         FROM
        //             staffaccounts sa
        //         WHERE
        //             sa.staffID in (SELECT DISTINCT
        //                     (staffID)
        //                 FROM
        //                     attendance
        //                 WHERE
        //                     attendanceDate = '$attendanceDate'
        //                         AND hour = '$hour'
        //                         AND batchID = '$batchID'
        //                         AND semID = '$semID')";
        
        try {
            $staffDetails = $this->executeQueryForList($sql);
            return $staffDetails;
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return false;
    }
    public function getCourseFileStaffDetails($request){
        $request = $this->realEscapeObject($request);
        $request->staffId?$where[]="sbs.staffID = '$request->staffId'":null;
        $request->sbsId?$where[]="ref.sbsID = '$request->sbsId'":null;
        $request->pseudoSubjectId?$where[]="css.psId = '$request->pseudoSubjectId'":null;
        try {
            if(!empty($where)){
                $sql = "SELECT 
                        css.objective, 
                        css.syllabus, 
                        css.outcome, 
                        css.notes, 
                        css.genral_in
                    FROM 
                        sbs_relation sbs
                    INNER JOIN 
                        coursefile_staff_settings css 
                        ON sbs.sbsID = css.sbsID
                    INNER JOIN 
                        sbs_relation ref
                        ON sbs.batchID = ref.batchID
                        AND sbs.subjectID = ref.subjectID
                    ".($where?" WHERE ".implode(' AND ',$where):"").";";
                return $this->executeQueryForObject($sql);
            }else{
                return false;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * get staff details by subject
     *
     * @param int $subjectId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffListBySubject($subjectId, $isResigned = NULL)
    {
        $subjectId = $this->realEscapeString($subjectId);
        $isResigned = $this->realEscapeString($isResigned);
        $sql = "SELECT distinct sa.staffID AS staffId, sa.staffName AS name, sa.staffCode AS code from staffaccounts sa inner join sbs_relation sr on sa.staffID = sr.staffID left join subbatch_sbs ss on sr.sbsID = ss.sbsID where sr.subjectID=$subjectId ";
        if (!is_null($isResigned)) {
            $sql = $sql . " AND sa.isResigned='$isResigned'";
        }
        try {
            $staffDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    
    public function getCourseFileObjectives($request){
        $request = $this->realEscapeObject($request);
        try{
            $request->sbsId?$where[]="cfdo.sbs_id = '$request->sbsId'":null;
            $request->pseudoSubjectId?$where[]="cfdo.pseudo_subject_id = '$request->pseudoSubjectId'":null;
            $request->id?$where[]="cfdo.id = '$request->id'":null;
            $request->batchId?$where[]="sbs.batchID = '$request->batchId'":null;
            $request->subjectId?$where[]="sbs.subjectID = '$request->subjectId'":null;
            $request->semId?$where[]="sbs.semID = '$request->semId'":null;
            $request->staffId?$where[]="sbs.staffID = '$request->staffId'":null;
            $sql = "SELECT 
                cfdo.id,
                cfdo.title,
                cfdo.description,
                cfdo.sbs_id AS sbsId,
                cfdo.pseudo_subject_id AS pseudoSubjectId,
                cfdo.disable,
                cfdo.context,
                cfdor.id AS course_resourse_id,
                cfdor.resourse_id,
                cfdor.disable AS course_resourse_disable,
                cfdor.title AS course_resourse_title
            FROM course_file_and_diary_objectives cfdo
            INNER JOIN sbs_relation sbs ON sbs.sbsID = cfdo.sbs_id
            LEFT JOIN course_file_and_diary_objectives_resourses cfdor ON cfdo.id = cfdor.course_objectives_id
            ".($where?" WHERE ".implode(' AND ',$where):"")."
            GROUP BY cfdo.id,cfdor.id;";
            $objectives = $this->executeQueryForList($sql, $this->mapper [StaffServiceMapper::GET_COURES_OBJETIVES]);
            foreach($objectives as $objective){
                foreach($objective->resourses as $resourse){
                    $request = new GetPreSignedUrlRequest();
                    $request->resourceId = $resourse->resourseId;
                    $request->secretKey = getenv("AWS_CLIENT_SECRET_KEY");
                    $request->accessKey =  getenv("AWS_ACCESS_KEY");
                    try {
                        $response = ResourceService::getInstance()->getPreSignedUrlByResourceId($request);
                    } catch (\Throwable $th) {}
                    $resourse->name = $response->name;
                    $resourse->url = $response->url;
                    $resourse->uploadedFileType = end(explode(".", $response->name));
                }
            }
            return $objectives;
        } catch (\Exception $e){
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    /**
     * create or update course_file_and_diary_objectives
     *
     * @return MySqlResult
     * @throws ProfessionalException
     */
    public function createOrUpdateCourseFileObjectives($request)
    {
        $request = $this->realEscapeObject($request);
        $request->description = htmlspecialchars_decode($request->description);
        try {
            $req = new \stdClass();
            if(!empty($request->id)){
                $req->id = $request->id;
                $this->updateCourseFileObjectives($request);
            }else{
                $req->id = $this->createCourseFileObjectives($request)->id;
            }
            return $this->getCourseFileObjectives($req);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    public function updateCourseFileObjectives($request){
        try {
            $sql = "
            UPDATE course_file_and_diary_objectives SET 
            title='$request->title', 
            description='$request->description', sbs_id='$request->sbsId', " .($request->pseudoSubjectId?"pseudo_subject_id='$request->pseudoSubjectId'":"pseudo_subject_id=NULL"). ", disable='$request->disable', updated_date=utc_timestamp(), context='$request->context
            WHERE id='$request->id';";
            return $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    public function createCourseFileObjectives($request){
        try {
            $sql = "INSERT INTO course_file_and_diary_objectives (title, description, sbs_id, pseudo_subject_id, disable, created_by, created_date, updated_by, updated_date, context
        ) values ('$request->title','$request->description','$request->sbsId',".($request->pseudoSubjectId?$request->pseudoSubjectId:"NULL").",$request->disable,$request->createdBy,utc_timestamp,$request->updatedBy,utc_timestamp(),'$request->context')";
            return $this->executeQuery($sql,true);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    public function deleteCourseFileObjectives($id){
        if((int)$id){
            try {
                $sql = "DELETE FROM course_file_and_diary_objectives WHERE id='$id';";
                $this->executeQuery($sql);
                return true;
            } catch (\Exception $e) {
                throw new ProfessionalException ($e->getCode(), $e->getMessage());
            }
        }else{
            return false;
        }
    }
    public function createCourseObjectiveResourses($request){
        try {
            $sql = "INSERT INTO `course_file_and_diary_objectives_resourses` (`title`, `course_objectives_id`, `resourse_id`, `uploded_date`, `disable`, `created_by`, `created_date`, `updated_by`, `updated_dated`) VALUES ('$request->title', '$request->objId', '$request->resourseId', utc_timestamp, '0', '$request->createdBy', utc_timestamp(), '$request->updatedBy', utc_timestamp());";
            return $this->executeQuery($sql,true);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        } 
    }
    public function deleteCourseFileObjectivesResourses($id){
        if((int)$id){
            try { 
                $sql = "SELECT resourse_id as resourseId from course_file_and_diary_objectives_resourses where id='$id';";
                $resourseId = $this->executeQueryForObject($sql)->resourseId;
                $removeRequest = new RemoveResourceRequest();
                $removeRequest->resourceId = $resourseId;
                // ResourceService::getInstance()->removeResource($removeRequest);
                $sql = "DELETE FROM course_file_and_diary_objectives_resourses WHERE id='$id';";
                $this->executeQuery($sql);
                return true;
            } catch (\Exception $e) {
                throw new ProfessionalException ($e->getCode(), $e->getMessage());
            }
        }else{
            return false;
        }
    }
     /**
     * get staff details by subject request
     *
     * @param int $request
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffListBySubjectRequest($request)
    {
        $request = $this->realEscapeObject($request);
        $resignCondition ="";
        $sql = "SELECT distinct sa.staffID AS staffId, sa.staffName AS name, sa.staffCode AS code from staffaccounts sa inner join sbs_relation sr on sa.staffID = sr.staffID left join subbatch_sbs ss on sr.sbsID = ss.sbsID where sr.subjectID=$request->subjectId ";
        if (!is_null($request->isResigned)) {
            $resignCondition = " AND sa.isResigned='$request->isResigned'";
            $sql = $sql . " AND sa.isResigned='$request->isResigned'";
        }
        if($request->valuationCount == 2 || $request->valuationCount == 3 || $request->considerExternalFaculty){
            $sql .= " UNION
                    SELECT sa.staffID AS staffId, sa.staffName AS name, sa.staffCode AS code from staffaccounts sa 
                    INNER JOIN department dp ON dp.deptID = sa.deptID
                    WHERE dp.departmentSpecialization ='".ExamType::EXTERNAL."$resignCondition";
        }
        try {
            $staffDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /**
     * get subjectwise Exam Valuation Dates
     * @param  $request
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function  getSubjectExamValuationDates($request)
    {
        $request = $this->realEscapeObject($request);
        $valuationDates = null;
        $dateColumns="";
        if ($request->valuationCount == 1) {
            $dateColumns = "firstval_Datestart as valStartDate,firstval_Dateend as valEndDate";
        } else if ($request->valuationCount == 2) {
            $dateColumns = "secondval_Datestart as valStartDate,secondval_Dateend as valEndDate";
        } else if ($request->valuationCount == 3) {
            $dateColumns = "thirdval_Datestart as valStartDate,thirdval_Dateend as valEndDate";
        }
        $examRegField = $request->isSupply ? "supplyRegId" : "examRegId";
        try {
            $sql = "SELECT $dateColumns
                           from valuationDatesSubjectWise 
                           WHERE  $examRegField ='$request->examRegId' AND subjectId='$request->subjectId'";
            $valuationDates = $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return  $valuationDates;
    }
    public function getStaffDetailsByBatchDept($batchID = NULL, $deptID = NULL, $pseudoCond = NULL)
    {
        $batchID = $this->realEscapeString($batchID);
        $deptID = $this->realEscapeString($deptID);
        $pseudoCond = $this->realEscapeString($pseudoCond);
        $condition = "";
        $psJoin = "";
        $sJoin = "INNER JOIN batches b ON sr.batchID = b.batchID AND b.semID = sr.semID
            LEFT JOIN department dept ON dept.deptID = b.deptID ";
        if($pseudoCond == "1"){
            $condition = " AND sr.isPseudoSubject='$pseudoCond' AND ps.isFinalized = 1  AND b.isPassOut = 0 AND dept.deptShow = 1 ";
            if ($deptID) {
                $condition .= "  AND ps.hdl_deptID = '$deptID'";
            }
            $psJoin .= " INNER JOIN pseudosubjects_sbs psbs on psbs.sbsID = sr.sbsID
            INNER JOIN pseudosubjects ps on ps.pseudosubjectID = psbs.pseudosubjectID";
        }
        else{
            $condition .= " AND b.isPassOut = 0 AND dept.deptShow = 1 AND sr.isPseudoSubject='$pseudoCond'";
            if ($batchID) {
                $condition .= " AND b.batchID='$batchID";
            }
            if ($deptID) {
                $condition .= " AND dept.deptID='$deptID";
            }
        }
        $sql = "SELECT distinct(s.staffID),s.staffName,s.deptID,s.staffCode FROM sbs_relation sr
        INNER JOIN staffaccounts s ON s.staffID = sr.staffID ".$sJoin."
        ". $psJoin ."
        WHERE s.isResigned = 0 $condition  
        GROUP BY sr.staffID order by s.deptID;";
        try {
            $staffs = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $staffs;
    }
    /**
     * get Exam Reg Assigned For Valuation By staff
     *
     * @param int $request
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function  getExamRegAssignedForValuationByStaff($request)
    {
        $request = $this->realEscapeObject($request);
        $tableName = "exam_valuation_staffs evs";
        $exams = null;
        $examRegField = ($request->examType == ExamType::SUPPLY) ? "supply_examreg_id": "examregID";
        try {
            $sql = "SELECT 
                            e.$examRegField as examRegId
                        FROM
                            exam e 
                            INNER JOIN batches b ON b.batchID = e.batchID 
                            INNER JOIN $tableName ON evs.examID = e.examID AND FIND_IN_SET('$request->staffId',evs.staffIDs)
                        WHERE
                            1 = 1
                            UNION 
                            SELECT 
                            e.$examRegField as examRegId
                        FROM
                            exam e 
                            INNER JOIN batches b ON b.batchID = e.batchID 
                            INNER JOIN externalexam_valuation_staffs evs ON evs.examID = e.examID AND FIND_IN_SET('$request->staffId',evs.staffIDs)
                        WHERE
                            1 = 1";
            $exams = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $exams;
    }
     /**
     * Get All batch tutor details of the current sem
     * 
     * @param string $staffName
     * @return Array |NULL|
     * @throws ProfessionalException
     */
    public function getAllBatchTutor($staffName = NULL,$deptId = NULL,$start=0,$endIndex = 0){
        $staffName = $this->realEscapeString($staffName);
        $deptId = $this->realEscapeString($deptId);
        $cond = "";
        if($staffName){
            $cond .= " AND sa.staffName like '%$staffName%'";
        }
        if($deptId){
            $cond .= " AND dp.deptID = '$deptId'";
        }
        $limit = " limit $start$endIndex ";
        $sql = "SELECT sa.staffID,sa.staffName,deptName,sa.staffEmail,sa.staffPhone,sa.staffAccount,sa.staffCode,group_concat(b.batchName) as batchName FROM batch_tutor bt INNER JOIN staffaccounts sa ON sa.staffID = bt.staffID
        INNER JOIN batches b ON b.batchID=bt.batchID and b.semID = bt.semID
        INNER JOIN department dp ON dp.deptID=sa.deptID WHERE 1=1 $cond GROUP BY sa.staffID $limit";
        $sql_count = "SELECT count(distinct(sa.staffID)) as count FROM batch_tutor bt INNER JOIN staffaccounts sa ON sa.staffID = bt.staffID
        INNER JOIN batches b ON b.batchID=bt.batchID and b.semID = bt.semID
        INNER JOIN department dp ON dp.deptID=sa.deptID WHERE 1=1 $cond";
        try {
            $staffDetails = $this->executeQueryForList($sql);
            $totalRecords = $this->executeQueryForObject($sql_count)->count;
            $staff = new stdClass();
            $staff->staffDetails = $staffDetails;
            $staff->totalRecords = $totalRecords;
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staff;
    }
    /**
     * get all examcontroller_admin details
     * @return Array |NULL|
     */
    public function getAllExamControllerDetails()
    {
        $examControllerDetails = null;
        $sql = "SELECT adminID, adminName from examcontroller_admin";
        try {
            $examControllerDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $examControllerDetails;
    }
    /**
     * @author Sibin
     * get oe exam ExamValuationStudentMarkEntryStatus
     */
    public function getExamValuationStudentMarkEntryStatus($request)
    {
        $request = $this->realEscapeObject($request);
        $studentDetails="";
        $condition = "";
        $request->scrutinyId = (int)$request->scrutinyId;
        if($request->revaluationId){
            $condition .= " AND  oec.revaluation_id IN ($request->revaluationId)";
        }
        if($request->scrutinyId) {
            $condition .= " AND  oec.scrutiny_id IN ($request->scrutinyId)";
        }else{
            $condition .= " AND  oec.scrutiny_id IS NULL";
        }
        $sql = "SELECT e.examID,oe.id as oeExamId,oec.exam_mark as mark,oec.is_confirmed as markConfirm
                FROM exam e
                INNER JOIN oe_exams oe ON JSON_UNQUOTE(JSON_EXTRACT(oe.identifying_context, '$.examId')) = e.examID
                LEFT JOIN oe_exam_marks_confirm oec ON oec.oe_exams_id = oe.id 
                WHERE e.examID = '$request->examId' AND oec.valuation_count = '$request->valuationCount' AND oec.oe_users_id = '$request->studentId$condition";
        try {
            $studentDetails = $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $studentDetails;
    }
    /**
     * get getStudentAssignedStaffByExam
     *
     * @param int $request
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function  getStudentAssignedStaffByExam($request)
    {
        $request = $this->realEscapeObject($request);
        $joinTable = $condition = $staffIds = "";
        if($request->batchId){
            $joinTable .= " INNER JOIN studentaccount sa ON sa.studentID = evs.studentId ";
            $condition .= " AND sa.batchID IN ($request->batchId";
        }
        try {
            $sql = "SELECT distinct evs.staffId FROM examValuationStaffAssignedStudents evs
                    $joinTable
                    WHERE evs.examRegId IN ($request->examRegId) AND evs.subjectId IN ($request->subjectId
                    AND evs.valuationCount IN ($request->valuationCountSelected) AND evs.examType ='$request->examType'
                    $condition";
            $staffIds = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffIds;
    }
    /**
     * get exam registration by valuation date end
     *
     * @param int $request
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function  getExamRegistrationsByValuationDate($request)
    {
        $request = $this->realEscapeObject($request);
        $examRegIds = [];
        $valuationDateField = "firstval_Dateend";
        if($request->valuationCount == 2){
            $valuationDateField = "secondval_Dateend";
        }
        $condition = "";
        if($request->examType == ExamType::REGULAR){
            //$condition = "AND (examType ='$request->examType' OR examType='')";
            $sql = "SELECT examregID as examRegId FROM valuationdates 
                    WHERE  TIMESTAMP($valuationDateField,'23:59:59') > NOW()  $condition
                    GROUP BY examregID";
        }else{
            $sql="SELECT id as examRegId from exam_supplementary WHERE  TIMESTAMP(valuation_endDate,'23:59:59') > NOW()";
        }
        try {
            $examRegIds = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $examRegIds;
    }
    /**
     * Check exam controller technical support staff
     */
    public function checkExamControllerTechnicalSupportStaff($staffId)
    {
        $staffId = $this->realEscapeString($staffId);
        $staffDetails = "";
        $sql = "SELECT es.stafftypeID FROM examcontroller_admin ea INNER JOIN examcontroller_stafftype es ON (ea.stafftypeID = es.stafftypeID) WHERE ea.adminID = $staffId AND es.stafftypeCode = 'TECHNICAL_SUPPORT'";
        try {
            $staffDetails = $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /**
     * get question papper bank staffs by batch ,sem,subject
     * @param integer $subjectID
     * @param integer $batchID
     * @param integer $semID
     * @throws AMSException
     * @return $staffs
     */
    public function getQuestionPaperBankStaffByBatchSem($request)
    {
        $request = $this->realEscapeObject($request);
        $staffs = [];
        $condition = "";
        if ($request->batchId) {
            $condition .= " AND qpb.batchId IN ($request->batchId)";
        }
        if ($request->batchId) {
            $condition .= " AND qpb.semId IN($request->semId)";
        }
        if ($request->batchId) {
            $condition .= "  AND qpb.subjectId IN($request->subjectId)";
        }
        $sql = "SELECT sa.staffName FROM question_paper_bank qpb
                INNER JOIN question_paper_bank_faculty qpbf ON qpbf.question_paper_bank_id = qpb.id
                INNER JOIN staffaccounts sa ON sa.staffID = qpbf.staffId
                WHERE 1=1
                $condition
                AND qpbf.isBlock = 0";
        try {
            $staffs = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffs;
    }
    public function getActualSubjectPlanDetails($request)
    {
        $request = $this->realEscapeObject($request);
        $subjectPlans = new \stdClass();
        $subjectPlans->basicDetails = null;
        $subjectPlans->basicDetails = [];
        $subjectPlans->subjectPlans = [];
        $where = [];
        $orderBy = "desc";
        if(!empty($request->orderBy)){
            $orderBy = $request->orderBy;
        }
        if($request->fromDate && $request->toDate)
        {
            $where [] = " subp.date BETWEEN " . strtotime($request->fromDate) . " AND " . strtotime($request->toDate);
        }
        try 
        {
            if($request->subjectType == "pseudoSubjects")
            {
                $request->pseudoSubjectId?$where[] = " subp.pssId = $request->pseudoSubjectId ":"";
                $request->pseudoSubjectIds?$where[] = " subp.pssId in (".implode(',',$request->pseudoSubjectIds).") ":"";
                $overAllSql = "SELECT count(subp.hour) as hrsTakenAttn,count(cm.id) as materialGiven
                    FROM ps_subjectplan subp 
                    LEFT JOIN ps_actual_plan_course_materials map ON map.actual_plan_id=subp.topicID
                    LEFT JOIN course_materials cm ON cm.id=map.course_material_id AND cm.is_active=1 
                    LEFT JOIN ps_actual_plan_video_materials papvm on subp.topicID = papvm.ps_actual_plan_id    
                    LEFT JOIN batch_video_repository bvr on papvm.video_repository_id = bvr.id 
                    LEFT JOIN  (
                        SELECT MAX(isCovered) as finalStatus,proposed_topicID
                        FROM ps_subjectplan
                    ) AS temp 
                    ".($where?" WHERE ".implode(' AND ',$where):"")."
                    group by subp.pssId
                    ORDER BY subp.date $orderBy,subp.hour;";
                $sql = "SELECT subp.topicID as actualPlanId,FROM_UNIXTIME(subp.date, '%Y-%m-%d') as subjectPlanDate, subp.hour, subp.module, subp.topicName,'pseudoSubjects' as subjectType,subp.pssId as pseudoSubjectId, subp.topicDesc as actualPlanTopicDesc,subp.mode as mode_of_instruction,
                    case 
                    when subp.isCovered = '0' then 'Not covered'
                    when subp.isCovered = '1' then 'Partially covered'
                    when subp.isCovered = '2' then 'Fully covered'
                        else null 
                    END as covered,subp.isCovered, subp.day, subp.session,lr.path as actual_plan_url,lr.path as proposed_plan_url
                    from ps_subjectplan subp
                    LEFT JOIN ps_actual_plan_video_materials papvm ON papvm.ps_actual_plan_id=subp.topicID
                    LEFT JOIN course_video_materials cvm ON cvm.id = papvm.video_repository_id
                    LEFT JOIN lin_resource lr ON lr.id = cvm.resource_id
                    ".($where?" WHERE ".implode(' AND ',$where):"")."
                    ORDER BY subp.date $orderBy,subp.hour ASC";
                if(!empty($where)){
                    $subjectPlans->basicDetails = $request->overallData?$this->executeQueryForList($overAllSql):null;
                    $subjectPlans->subjectPlans = $request->detailedData?$this->executeQueryForList($sql):null;
                }
            }
            else
            {
                $request->staffId?$where[] = " sr.staffID = '$request->staffId":"";
                $request->sbsId?$where[] = " subp.sbsID = '$request->sbsId":"";
                $request->batchId?$where[] = " sr.batchID = '$request->batchId":"";
                $request->semId?$where[] = " sr.semID = '$request->semId":"";
                $request->subjectId?$where[] = " sr.subjectID = '$request->subjectId":"";
                $sql = "SELECT subp.sbsID,subp.topicID AS actualPlanId,FROM_UNIXTIME(subp.date, '%Y-%m-%d') AS subjectPlanDate, subp.hour, subp.module, subp.topicName, null as subjectType,subp.mode as mode_of_instruction,
                CASE 
                    WHEN subp.isCovered = '0' THEN 'Not covered'
                    WHEN subp.isCovered = '1' THEN 'Partially covered'
                    WHEN subp.isCovered = '2' THEN 'Fully covered'
                    else null 
                END AS covered,subp.isCovered, subp.day, subp.session,subp.topicDesc as actualPlanTopicDesc,lr.path as actual_plan_url
                FROM subjectplan subp
                INNER JOIN sbs_relation sr ON sr.sbsID = subp.sbsID
                LEFT JOIN subject_actual_plan_video_materials sap ON sap.subject_actual_plan_id=subp.topicID
                LEFT JOIN course_video_materials cm ON cm.id=sap.video_repository_id
                LEFT JOIN lin_resource lr ON lr.id = cm.resource_id
                ".($where?" WHERE ".implode(' AND ',$where):"")." ORDER BY subp.date $orderBy,subp.hour ASC";
                $overAllSql = "SELECT count(ac.hour) as hrsTakenAttn, count(sh.hour) as suspendedHrs, count(sps.topicID) as subjectPlanCount,
                COUNT(CASE WHEN (sps.isCovered = 0) THEN 1 END) as notCovered,
                COUNT(CASE WHEN (sps.isCovered = 1) THEN 1 END) as partiallyCovered,
                COUNT(CASE WHEN (sps.isCovered = 2) THEN 1 END) as fullyCovered
                FROM subjectplan sps
                inner join sbs_relation sr on sr.sbsID = sps.sbsID 
                left join attendance_confirm ac on sps.sbsID = ac.sbsID and ac.attendanceDate = from_unixtime(sps.date) and sps.hour = ac.hour 
                left join suspended_hours sh on sh.suspendedDate = from_unixtime(sps.date) and sh.hour = sps.hour and sh.batchID = sr.batchID and sh.semID = sr.semID
                ".($where?" WHERE ".implode(' AND ',$where):"")."
                group by sps.sbsID
                order by sps.date $orderBy,sps.hour;";
                if(!empty($where)){
                    $subjectPlans->subjectPlans = $request->detailedData?$this->executeQueryForList($sql):null;
                    $subjectPlans->basicDetails = $request->overallData?$this->executeQueryForObject($overAllSql):null;
                }
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $subjectPlans;
    }
    public function getActualSubjectCoverageDetails($request)
    {
        $request = $this->realEscapeObject($request);
        $subjectPlans = new \stdClass();
        $subjectPlans->basicDetails = null;
        $subjectPlans->basicDetails = [];
        $subjectPlans->subjectPlans = [];
        $where = [];
        $orderBy = "desc";
        if(!empty($request->orderBy)){
            $orderBy = $request->orderBy;
        }
        // if($request->fromDate && $request->toDate)
        // {
        //     $where [] = " subp.date BETWEEN " . strtotime($request->fromDate) . " AND " . strtotime($request->toDate);
        // }
        try 
        {
            if($request->subjectType == "pseudoSubjects")
            {
                $request->pseudoSubjectId?$where[] = " subp.pssId = $request->pseudoSubjectId ":"";
                $request->pseudoSubjectIds?$where[] = " subp.pssId in (".implode(',',$request->pseudoSubjectIds).") ":"";
                $overAllSql = "SELECT count(subp.hour) as hrsTakenAttn,count(cm.id) as materialGiven
                    FROM ps_subjectplan subp 
                    LEFT JOIN ps_actual_plan_course_materials map ON map.actual_plan_id=subp.topicID
                    LEFT JOIN course_materials cm ON cm.id=map.course_material_id AND cm.is_active=1 
                    LEFT JOIN ps_actual_plan_video_materials papvm on subp.topicID = papvm.ps_actual_plan_id    
                    LEFT JOIN batch_video_repository bvr on papvm.video_repository_id = bvr.id 
                    LEFT JOIN  (
                        SELECT MAX(isCovered) as finalStatus,proposed_topicID
                        FROM ps_subjectplan
                    ) AS temp 
                    ".($where?" WHERE ".implode(' AND ',$where):"")."
                    group by subp.pssId
                    ORDER BY subp.date $orderBy,subp.hour;";
                $sql = "SELECT subp.topicID as actualPlanId,FROM_UNIXTIME(subp.date, '%Y-%m-%d') as subjectPlanDate, subp.hour, subp.module, subp.topicName,'pseudoSubjects' as subjectType,subp.pssId as pseudoSubjectId, subp.topicDesc as actualPlanTopicDesc,subp.mode as mode_of_instruction,
                    case 
                    when subp.isCovered = '0' then 'Not covered'
                    when subp.isCovered = '1' then 'Partially covered'
                    when subp.isCovered = '2' then 'Fully covered'
                        else null 
                    END as covered,subp.isCovered, subp.day, subp.session,lr.path as actual_plan_url,lr.path as proposed_plan_url
                    from ps_subjectplan subp
                    LEFT JOIN ps_actual_plan_video_materials papvm ON papvm.ps_actual_plan_id=subp.topicID
                    LEFT JOIN course_video_materials cvm ON cvm.id = papvm.video_repository_id
                    LEFT JOIN lin_resource lr ON lr.id = cvm.resource_id
                    ".($where?" WHERE ".implode(' AND ',$where):"")."
                    ORDER BY subp.date $orderBy,subp.hour ASC";
                if(!empty($where)){
                    $subjectPlans->basicDetails = $request->overallData?$this->executeQueryForList($overAllSql):null;
                    $subjectPlans->subjectPlans = $request->detailedData?$this->executeQueryForList($sql):null;
                }
            }
            else
            {
                $request->staffId?$where[] = " sr.staffID = '$request->staffId":"";
                $request->sbsId?$where[] = " subp.sbsID = '$request->sbsId":"";
                $request->batchId?$where[] = " sr.batchID = '$request->batchId":"";
                $request->semId?$where[] = " sr.semID = '$request->semId":"";
                $request->subjectId?$where[] = " sr.subjectID = '$request->subjectId":"";
                $sql = "SELECT subp.sbsID,subp.topicID AS actualPlanId,FROM_UNIXTIME(subp.date, '%Y-%m-%d') AS subjectPlanDate, subp.hour, subp.module, subp.topicName, null as subjectType,subp.mode as mode_of_instruction,
                CASE 
                    WHEN subp.isCovered = '0' THEN 'Not covered'
                    WHEN subp.isCovered = '1' THEN 'Partially covered'
                    WHEN subp.isCovered = '2' THEN 'Fully covered'
                    else null 
                END AS covered,subp.isCovered, subp.day, subp.session,subp.topicDesc as actualPlanTopicDesc,lr.path as actual_plan_url
                FROM subjectplan subp
                INNER JOIN sbs_relation sr ON sr.sbsID = subp.sbsID
                LEFT JOIN subject_actual_plan_video_materials sap ON sap.subject_actual_plan_id=subp.topicID
                LEFT JOIN course_video_materials cm ON cm.id=sap.video_repository_id
                LEFT JOIN lin_resource lr ON lr.id = cm.resource_id
                ".($where?" WHERE ".implode(' AND ',$where):"")." ORDER BY subp.date $orderBy,subp.hour ASC";
                $overAllSql = "SELECT count(ac.hour) as hrsTakenAttn, count(sh.hour) as suspendedHrs, count(sps.topicID) as subjectPlanCount,
                COUNT(CASE WHEN (sps.isCovered = 0) THEN 1 END) as notCovered,
                COUNT(CASE WHEN (sps.isCovered = 1) THEN 1 END) as partiallyCovered,
                COUNT(CASE WHEN (sps.isCovered = 2) THEN 1 END) as fullyCovered
                FROM subjectplan sps
                inner join sbs_relation sr on sr.sbsID = sps.sbsID 
                left join attendance_confirm ac on sps.sbsID = ac.sbsID and ac.attendanceDate = from_unixtime(sps.date) and sps.hour = ac.hour 
                left join suspended_hours sh on sh.suspendedDate = from_unixtime(sps.date) and sh.hour = sps.hour and sh.batchID = sr.batchID and sh.semID = sr.semID
                ".($where?" WHERE ".implode(' AND ',$where):"")."
                group by sps.sbsID
                order by sps.date $orderBy,sps.hour;";
                if(!empty($where)){
                    $subjectPlans->subjectPlans = $request->detailedData?$this->executeQueryForList($sql):null;
                    $subjectPlans->basicDetails = $request->overallData?$this->executeQueryForObject($overAllSql):null;
                }
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $subjectPlans;
    }
    /**
     * get question  bank staffs by batch ,sem,subject
     * @throws ProfessionalException
     * @return $request
     */
    public function getQuestionBankPoolStaffByBatchSem($request)
    {
        $request = $this->realEscapeObject($request);
        $staffs = [];
        $condition = "";
        if ($request->batchId) {
            $condition .= " AND qpb.batchID IN ($request->batchId)";
        }
        if ($request->batchId) {
            $condition .= " AND qpb.semID IN($request->semId)";
        }
        if ($request->batchId) {
            $condition .= "  AND qpb.subjectID IN($request->subjectId)";
        }
        $sql = "SELECT qpb.staffID as id,sa.staffName as name FROM question_paper_pool qpb
                INNER JOIN staffaccounts sa ON sa.staffID = qpb.staffID
                WHERE 1=1
                $condition
                group by qpb.staffID";
        try {
            $staffs = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffs;
    }
    /**
     * copyQuestions From Staff
     * @throws ProfessionalException
     * @return $request
     */
    public function copyQuestionsFromStaff($request)
    {
        $request = $this->realEscapeObject($request);
        $fromCondition ="";
        if($request->moduleId){
            $fromCondition .= " AND qpp.question_paper_moduleID IN($request->moduleId)";  
        }
        $markCategoryTo = "question_paper_mark_categoryID";
        if($request->marksId){
            $fromCondition .= " AND qpp.question_paper_mark_categoryID IN($request->marksId)";
        }
        $moduleIdTo = $request->moduleIdTo ? "$request->moduleIdTo" :"question_paper_moduleID";
        $markCategoryTo = $request->marksIdTo ? "$request->marksIdTo":"question_paper_mark_categoryID";
        try {
            $sql = "INSERT INTO question_paper_pool (question_paper_bank_id,staffID,batchID,semID,subjectID,question_paper_moduleID,question_paper_mark_categoryID,isblocked,question,
                    att_path,question_paper_difficulty_levelID,cognitiveLevels,question_paper_sections_id,placeholder,enableEdit) 
                    SELECT '$request->question_paper_bank_idTo','$request->staffIdTo','$request->batchIdTo','$request->semIdTo','$request->subjectIdTo',$moduleIdTo,$markCategoryTo,isblocked,question,
                    att_path,question_paper_difficulty_levelID,cognitiveLevels,question_paper_sections_id,placeholder,0 FROM question_paper_pool qpp 
                    WHERE  qpp.subjectID = '$request->subjectId' AND qpp.batchID = '$request->batchId' AND qpp.semID = '$request->semId' AND qpp.staffID = '$request->staffId'
                    $fromCondition";
            $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
                throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return true;
    }
    /**
     * Unassign faculty from the subject or pseudo subject and sub-batch
     *
     * @param int $batchId
     * @param int $semId
     * @param int $staffId
     * @param int $subjectId
     * @return MySqlResult
     * @throws ProfessionalException
     */
    public function unassignFacultyFromSbs($batchId, $semId, $staffId, $subjectId)
    {
        $batchId = $this->realEscapeString($batchId);
        $semId = $this->realEscapeString($semId);
        $staffId = $this->realEscapeString($staffId);
        $subjectId = $this->realEscapeString($subjectId);
        try {
            foreach (array("psbs", "ssbs", "sbs") as $key => $value) {
                $sql = "DELETE $value FROM sbs_relation sbs
                LEFT JOIN subbatch_sbs ssbs ON ssbs.sbsID = sbs.sbsID
                LEFT JOIN pseudosubjects_sbs psbs ON psbs.sbsID = sbs.sbsID
                WHERE batchID = $batchId AND semID = $semId AND subjectID = $subjectId AND staffID = $staffId ";
                $this->executeQuery($sql);
            }
        } catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    
    /**
     * get sbsID from batchID AND subjectID, staffID , semID
     * @author Ranjith Balachandran
     * @param unknown $batchID
     * @param unknown $subjectID
     * @param unknown $staffID
     * @param unknown $semID
     * @throws ProfessionalException
     * @return object|array|\com\linways\base\util\$objectList[]
     */
    public function getSbsId($batchId,$subjectId,$staffId,$semId)
    {
        $batchId = $this->realEscapeString($batchId);
        $subjectId = $this->realEscapeString($subjectId);
        $staffId = $this->realEscapeString($staffId);
        $semId = $this->realEscapeString($semId);
        try{
            $query="SELECT sr.sbsID AS sbsId FROM sbs_relation sr WHERE sr.batchID = $batchId AND sr.semID = $semId AND sr.subjectID = $subjectId AND sr.staffID = $staffId";
            $response=$this->executeQueryForObject($query)->sbsId;
            return $response;
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    /**
     * method to getting staff details with guideship for dataImport (PhD)
     * @return StaffList
     * @throws ProfessionalException
     */
    public function getStaffDetailsWithPhDGuideShipForDataImport()
    {
        $sql = '';
        $staffList = [];
        $sql = "SELECT staffID as id, staffName as name FROM staffaccounts WHERE isGuide = 1";
        try {
            $staffList = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffList;
    }
    /**
     * Check if the staff is group tutor
     *
     * @param int $staffId
     * @return boolean
     * @throws ProfessionalException
     */
    public function isStaffGroupTutor($request)
    {
        $request = $this->realEscapeObject($request);
        $condition ="";
        $isTutor = false;
        if($request->staffId){  
            $condition .=" AND staffID= '$request->staffId";
        }
        $sql = "SELECT batchID FROM batch_tutor WHERE 1=1
                $condition GROUP BY batchID";
        try {
            $result = $this->executeQueryForList($sql);
            if(!empty($result)){
                $isTutor = true;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        if($request->getBatches){
            return $result;
        }else{
            return $isTutor;
        }
    }
    /**
     * Check if the staff account exist
     * @param string $staffAccount
     * @param $id
     * @return boolean 
     * @throws ProfessionalException
     */
    public function checkIfStaffAccountExist($staffAccount,$id){
        $staffAccount = $this->realEscapeString($staffAccount);
        $id = $this->realEscapeString($id);
        if(!empty($id)){
            $where[] = " sa.staffID <> $id ";
        }
        if(!empty($staffAccount)){
            $where[] = " sa.staffAccount = '$staffAccount";
        }
        else{
            throw new ProfessionalException(ProfessionalException::EMPTY_PARAMETERS,"Staff Account is Empty");
        }
        try{
            $sql = "SELECT sa.staffID from staffaccounts sa WHERE ".implode("AND",$where);
            $result = $this->executeQueryForList($sql);
            if(!empty($result)){
                return true;
            }
            else{
                return false;
            }
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        } 
    }
    /**
     * method to getting question paper modules
     * @return StaffList
     * @throws ProfessionalException
     */
    public function getQuestionPaperModulesByRequest($request)
    {
        $request = $this->realEscapeObject($request);
        $sql = '';
        $result = [];
        if($request->groupByModule){
            $groupBy = " GROUP BY qpm.id ";
        }
        else if($request->groupByMarks){
            $groupBy = " GROUP BY qpmc.id";
        }
        if($request->getAll){
            if($request->groupByModule){
                $sql = "SELECT qpm.id as question_paper_moduleID,qpm.name as moduleName 
                    FROM question_paper_module qpm
                    WHERE  1 = 1
                    $groupBy";
            }else if($request->groupByMarks){
                $sql = "SELECT qpmc.id as question_paper_mark_categoryID,qpmc.name as markCategory 
                    FROM question_paper_mark_category qpmc 
                    WHERE  1=1
                    $groupBy";
            }
        }else{
                    $sql = "SELECT qpp.question_paper_bank_id,qpp.question_paper_moduleID,qpm.name as moduleName,qpp.question_paper_mark_categoryID,qpmc.name as markCategory FROM question_paper_pool qpp 
                    INNER JOIN question_paper_module qpm ON qpm.id = qpp.question_paper_moduleID
                    INNER JOIN question_paper_mark_category qpmc ON qpmc.id = qpp.question_paper_mark_categoryID
                    WHERE  qpp.subjectID = '$request->subjectId' AND qpp.batchID = '$request->batchId' AND qpp.semID = '$request->semId' AND qpp.staffID = '$request->staffId'
                    $groupBy";
        }
        try {
            $result = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $result;
    }
    /**
     * get question papper bank by batch ,sem,subject
     * @param integer $subjectID
     * @param integer $batchID
     * @param integer $semID
     * @throws AMSException
     * @return $qbankId
     */
    public function getQuestionPaperBankByBatchSem($request)
    {
        $request = $this->realEscapeObject($request);
        $condition = "";
        if ($request->batchId) {
            $condition .= " AND qpb.batchId IN ($request->batchId)";
        }
        if ($request->batchId) {
            $condition .= " AND qpb.semId IN($request->semId)";
        }
        if ($request->batchId) {
            $condition .= "  AND qpb.subjectId IN($request->subjectId)";
        }
        $sql = "SELECT qpb.id FROM question_paper_bank qpb
                WHERE 1=1
                $condition";
        try {
            $qbank = $this->executeQueryForObject($sql)->id;
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $qbank;
    }
    /**
     * get staff details by subject request
     *
     * @param int $request
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffListByRequest($request)
    {
        $request = $this->realEscapeObject($request);
        $condition ="";     
        $resignCondition = " AND sa.isResigned='$request->isResigned'";
        if($request->staffId){
            $condition .=" AND sa.staffID IN ($request->staffId)";  
        }     
        $sql = "SELECT sa.staffID AS staffId, sa.staffName AS name, sa.staffCode AS code from staffaccounts sa 
                INNER JOIN department dp ON dp.deptID = sa.deptID
                WHERE dp.departmentSpecialization ='" . ExamType::EXTERNAL . "$resignCondition";
        try {
            $staffDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    public function isExternalExaminer($staffId)
    {
        $condition = "";
        $resignCondition = " AND sa.isResigned='0'";
        if ($staffId) {
            $condition .= " AND sa.staffID IN ($staffId)";
        }
        $sql = "SELECT sa.staffID AS staffId, sa.staffName AS name, sa.staffCode AS code from staffaccounts sa 
                INNER JOIN department dp ON dp.deptID = sa.deptID
                WHERE dp.departmentSpecialization ='" . ExamType::EXTERNAL . "$condition "."$resignCondition";
        try {
            $staffDetails = $this->executeQueryForList($sql);
            if ($staffId) {
                return empty($staffDetails) ? false : true;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return false;
    }
     /** Get All Hod List in College
     * @param $request Object
     * @return $hodList Array
     */
    public function getHodListBasedOnRequest($request){
        $request = $this->realEscapeObject($request);
        $join = "";
        $where[] = " WHERE 1=1";
        if($request->psId){
            $join .= "INNER JOIN pseudosubjects ps ON ps.hdl_deptID = dept.deptID ";
            $request->psId?$where[] = " ps.pseudosubjectID = ".$request->psId." ":"";
        }
        if($request->batchId){
            $join .= " INNER JOIN batches ba ON ba.deptID = dept.deptID ";
            $request->batchId?$where[] = " ba.batchID = ".$request->batchId." ":"";
        }
        $request->includeResignedStaff?"":$where[] =  " sta.isResigned = 0 ";
        $request->deptId?$where[] = " sta.deptID = ".$request->deptId." ":"";
        if(!empty($request->hodTypes)){
            $where[] = " sta.isHod in (".implode(",",$request->hodTypes).") ";
        }
        else{
            $where[] = " sta.isHod = 1 ";
        }
        $sql = "SELECT sta.staffID,sta.staffName,sta.isHod,sta.staffPhone,sta.staffEmail,sta.deptID,sta.isResigned,sta.salutation from staffaccounts sta  INNER JOIN department dept ON dept.deptID = sta.deptID ";
        $sql .= $join;
        $sql .= implode(" AND ",$where);
        try {
            $hodList = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $hodList;
    }
    /**
     * Get All Principal List in College
     * @param $request Object
     * @return $principalList Array
     */
    public function getPrincipalListBasedOnRequest($request){
        $request = $this->realEscapeObject($request);
        $join = "";
        $where[] = " WHERE 1=1";
        $request->includeResignedStaff?"":$where[] =  " sa.isResigned = 0 ";
        if(!empty($request->principalTypes)){
            $where[] = " sa.isPrincipal in (".implode(",",$request->principalTypes).") ";
        }
        else{
            $where[] = " sa.isPrincipal = 1";
        }
        $sql = "SELECT sa.staffID,sa.staffName, sa.staffPhone, sa.staffEmail, sa.salutation,sa.isPrincipal,sa.isResigned,sa.deptID from staffaccounts sa";
        $sql .= implode(" AND ",$where);
        try {
            $principalList = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $principalList;
    }
    /**
     * method to getting staff details with subjects)
     * @return StaffList
     * @throws ProfessionalException
     */
    public function getSbsStaffDetails($request)
    {
        $request = $this->realEscapeObject($request);
        $sql = $conditions = $groupBy = '';
        $staffList = [];
        if($request->courseTypeId){
            $conditions .= " AND b.courseTypeID IN ($request->courseTypeId)";
        }
        if($request->coursePatternId){
            $conditions .= " AND b.patternID IN ($request->coursePatternId)";
        }
        if ($request->semId) {
            $conditions .= " AND sbs.semID IN ($request->semId)";
        }
        if ($request->batchStartYear) {
            $conditions .= " AND b.batchStartYear IN ($request->batchStartYear)";
        }
        if($request->groupByBatch){
            $groupBy = " group by b.batchID ";
        }
        $sql = "SELECT b.batchID as batchId,b.batchName,s.subjectID as subjectId,s.subjectName,s.subjectDesc,s.syllabusYear,sa.staffID,sa.staffName,ims.unique_code FROM batches b 
                INNER JOIN sbs_relation sbs ON sbs.batchID = b.batchID
                INNER JOIN subjects s ON s.subjectID = sbs.subjectID
                INNER JOIN staffaccounts sa ON sa.staffID = sbs.staffID
                LEFT JOIN internal_marks_submitted ims ON ims.batchID = b.batchID AND ims.semID = sbs.semID AND ims.subjectID = sbs.subjectID AND ims.staffID = sbs.staffID
                WHERE 1=1  $conditions
                $groupBy
                ORDER BY b.batchName,s.subjectName,sa.staffName";
        try {
            $staffList = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffList;
    }
    /**
     * Get all staffs 
     */
    public function getAllStaffs($isResigned = false){
        $sql = "SELECT s.staffID as id,
        CASE WHEN s.isResigned = 1 THEN concat(s.staffName,' ( Resigned )') ELSE s.staffName END AS name 
        FROM staffaccounts s";
        if($isResigned)
        {
            $sql .= " WHERE s.isResigned = 0 ";
        }
        $sql .= " ORDER BY s.staffName";
        try {
            return $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /*
     * method to find staff assigned to a valuation
     * @throws ProfessionalException
     */
    public function isStaffAssignedToValuation($request)
    {
        $request = $this->realEscapeObject($request);
        $sql = $conditions = '';
        $isAssigned = 0;
        if ($request->valuationType) {
            $conditions .= $request->valuationType ? " AND valuationType ='$request->valuationType'":" AND valuationType is null";
        }
        if($request->staffId){
            $conditions .=  " AND FIND_IN_SET('$request->staffId',staffIDs)";
        }
        if($request->examRegId){
            $examRegField = ($request->examType == "REGULAR") ? "examregID": "supply_examreg_id";
            $examIdCondition = "SELECT examID FROM exam WHERE $examRegField = $request->examRegId";
            $conditions .=" AND examID IN ($examIdCondition)";
        }
        if ($request->examId) {
            $conditions .= " AND examID IN ($request->examId)";
        }
        $sql1 = "SELECT examID,1 as valuationCount,staffIDs FROM exam_valuation_staffs WHERE 1=1  $conditions";
        $sql2 = "SELECT examID,valuationCount,staffIDs FROM externalexam_valuation_staffs WHERE 1=1  $conditions";
        try {
            $examList1 = $this->executeQueryForList($sql1);
            if(!empty($examList1)){
                $isAssigned = 1;
            }
            $examList2 = $this->executeQueryForList($sql2);
            if (!empty($examList2)) {
                $isAssigned = 1;
            }
            if($request->getValuationDetails){
                if(!empty($examList1) && empty($examList2)){
                    return $examList1;
                }
                if(!empty($examList2) && empty($examList1)){
                    return $examList2;
                }
            }
            else if ($request->getAllValuationDetails){
                $valuations = new stdClass;
                $valuations->valuation1 = $examList1;
                $valuations->valuation2 = $examList2;
                return $valuations;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $isAssigned;
    }
    /**
     * get auto asssign remove valuation stuents digital
     *
     * @param int $examId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function  autoAssignStudentsToExamValuationStaffs($request)
    {
        $request = $this->realEscapeObject($request);
        $insertValues = [];
        $insertValuesString = "";
        $insertSql = "";
        $deleteSql = "";
        $adminId = $_SESSION['adminID'];
        try {
            if ($request->removeStudents) {
                $deleteSql = "DELETE from examValuationStaffAssignedStudents where examRegId='$request->examRegId' AND examType = '$request->examType' AND subjectId = '$request->subjectId' AND valuationCount = '$request->valuationCount' AND staffId IN($request->staffId)";
                $this->executeQueryForObject($deleteSql);
            }else{
                if (!empty($request->selectedStudents)) {
                    foreach ($request->selectedStudents as $selectedStudent) {
                        $selectedStudent = (object)$selectedStudent;
                        $insertValues[] = "('$selectedStudent->studentID','$request->examRegId','$request->subjectId','$request->staffId','$request->valuationCount','$request->startDate','$request->endDate','$adminId','$request->examType')";
                    }
                    $insertValuesString = implode(",", $insertValues);
                    $insertSql = "INSERT INTO examValuationStaffAssignedStudents(studentId,examRegId,subjectId,staffId,valuationCount,valuationStartDate,valuationEndDate,created_by,examType) VALUES $insertValuesString
                                ON DUPLICATE KEY UPDATE staffId = VALUES(staffId),valuationStartDate = VALUES(valuationStartDate),valuationEndDate = VALUES(valuationEndDate),updated_by = VALUES(created_by)";
                    $this->executeQueryForObject($insertSql);
                }
            }
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return true;
    }
    /**
     * get staff By staffIds
     *
     * @param int $examId
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function  getAssignStudentsToExamValuationStaffDates($request)
    {
        $request = $this->realEscapeObject($request);
        $sql = "";
        $condition = "";
        if ($request->examType) {
            $condition .= " AND examType = '$request->examType'";
        }
        if ($request->examRegId) {
            $condition .= " AND examRegId IN ($request->examRegId)";
        }
        if ($request->subjectId) {
            $condition .= " AND subjectId IN ($request->subjectId)";
        }
        if ($request->valuationCount) {
            $condition .= " AND valuationCount IN ($request->valuationCount)";
        }
        if ($request->staffId) {
            $condition .= " AND staffId IN ($request->staffId)";
        }
        try {
            $sql = "SELECT valuationStartDate,valuationEndDate,count(studentId) as studentCount FROM examValuationStaffAssignedStudents 
                            WHERE 1=1 $condition";
            return $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * get staff By request
     *
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function  getDigitalValuationAssignedStaffs($request)
    {
        $request = $this->realEscapeObject($request);
        $sql = "";
        $condition = "";
        if ($request->examType) {
            $condition .= " AND examType = '$request->examType'";
        }
        if ($request->examRegId) {
            $condition .= " AND examRegId IN ($request->examRegId)";
        }
        if ($request->subjectId) {
            $condition .= " AND subjectId IN ($request->subjectId)";
        }
        if ($request->valuationCount) {
            $condition .= " AND valuationCount IN ($request->valuationCount)";
        }
        $allowReviewerIdChecking = true;
        try {
            if($request->reviewerId){
                if($request->getStaffsWithoutMapping){
                    $mappingCheck = " AND esas.properties->>'$.reviewerId' IS NOT NULL";
                    $sql = "SELECT esas.staffId,sa.staffName,properties from examValuationStaffAssignedStudents esas 
                    INNER JOIN staffaccounts sa ON sa.staffID = esas.staffId 
                    WHERE 1=1 $condition $mappingCheck group by  esas.staffId order by sa.staffID";
                    $mappingFound = $this->executeQueryForList($sql);
                    $allowReviewerIdChecking = $mappingFound ? $allowReviewerIdChecking : false;
                }
                $condition .= $allowReviewerIdChecking ? " AND esas.properties->>'$.reviewerId' = $request->reviewerId" :"";
            }
            $sql = "SELECT esas.staffId,sa.staffName,properties from examValuationStaffAssignedStudents esas 
                        INNER JOIN staffaccounts sa ON sa.staffID = esas.staffId 
                        WHERE 1=1 $condition group by  esas.staffId order by sa.staffID";
            return $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * get staff details by subject request
     *
     * @param int $request
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffListBySubjectDepartment($request)
    {
        $request = $this->realEscapeObject($request);
        $sql = "SELECT distinct sa.staffID AS staffId, sa.staffName AS name, sa.staffCode AS code 
                FROM subjects s
                INNER JOIN staffaccounts sa ON sa.deptID = s.hdl_deptID 
                where s.subjectID IN ($request->subjectId)";
        if (!is_null($request->isResigned)) {
            $sql = $sql . " AND sa.isResigned='$request->isResigned'";
        }
        try {
            $staffDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /**
     * get staff Assigned For Exam Valuation By 
     *
     * @param int $request
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function  getStaffAssignedForExamsValuation($request)
    {
        $request = $this->realEscapeObject($request);
        $valuationCountCondition = "";
        $condition = "";
        $examRegField = $request->isSupply ? "supply_examreg_id" : "examregID";
        if ($request->valuationCount == 2 || $request->valuationCount == 3) {
            $tableName = "externalexam_valuation_staffs evs";
            $valuationCountCondition = " AND evs.valuationCount='$request->valuationCount'";
        } else {
            $tableName = "exam_valuation_staffs evs";
        }
        if ($request->examRegId) {
            $condition .= " AND e.$examRegField IN ('$request->examRegId')";
        }
        if ($request->subjectId) {
            $condition .= " AND e.subjectID IN ('$request->subjectId') ";
        }
        if ($request->batchId) {
            $condition .= " AND e.batchID IN ('$request->batchId') ";
        }
        if ($request->semId) {
            $condition .= " AND e.semID IN ('$request->semId') ";
        }
        try {
            $sql = "SELECT 
                            e.batchID as 'batchId',
                            b.batchName,
                            b.batchDesc,
                            e.semID as 'semId',
                            e.examID AS examId, 
                            e.examName AS examName,
                            e.subjectID as 'subjectId',
                            s.subjectName,
                            s.subjectDesc,
                            evs.staffIDs,
                            e.examregID as examRegId,
                            e.supply_examreg_id as supplyRegId
                        FROM
                            $tableName
                            INNER JOIN exam e ON e.examID  = evs.examID 
                            INNER JOIN batches b ON b.batchID = e.batchID 
                            INNER JOIN subjects s ON s.subjectID = e.subjectID
                        WHERE
                            1 = 1
                            $condition $valuationCountCondition";
            $exams = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $exams;
    }
    /**
     * get staff valued details by exam reg
     *
     * @param int $request
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function getValuatedStaffDetailsByExamRegRequest($request)
    {
        $request = $this->realEscapeObject($request);
        $condition = "";
        $examTypeFied = $request->examType == "REGULAR" ? "examregID" : "supply_examreg_id";
        if ($request->examRegId) {
            $condition .= " AND e.$examTypeFied IN($request->examRegId)";
        }
        // if ($request->valuationCount) {
        //     $condition .= " AND oec.valuation_count IN($request->valuationCount)";
        // }
        // if ($request->reviewId) {
        //     $condition .= " AND oec.review_id IN ($request->reviewId)";
        // }
        if ($request->staffId) {
            $condition .= " AND sa.staffID IN ($request->staffId)";
        }
        $sql = "SELECT  sa.staffID,sa.staffName,count(oec.id) as valuatedCount,sa.ifscCode,sa.bankAccountNumber,sa.bankName,d.deptName from oe_exam_marks_confirm oec 
                INNER JOIN oe_exams oe ON oe.id = oec.oe_exams_id 
                INNER JOIN exam e ON e.examID = oe.identifying_context->>\"$.examId\"
                INNER JOIN staffaccounts sa ON sa.staffID = oec.created_by 
                INNER JOIN department d ON d.deptID = sa.deptID
                WHERE oec.revaluation_id IS NULL AND oec.is_confirmed =1  
                $condition
                GROUP BY sa.staffID ORDER BY sa.staffName";
        try {
            $staffDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $staffDetails;
    }
    /**
     * get staff details by unique code
     *
     * @param int $request
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffDetailsByUniqueCode($request){
        $request = $this->realEscapeObject($request);
        $sql = "SELECT  sa.staffID,sa.staffName,b.batchID,b.batchName,s.subjectID,s.subjectName,s.subjectDesc,s.syllabusYear,ims.semID,b.batchStartYear from internal_marks_submitted ims 
                INNER JOIN staffaccounts sa ON sa.staffID = ims.staffID  
                INNER JOIN batches b ON b.batchID = ims.batchID
                INNER JOIN subjects s ON s.subjectID = ims.subjectID
                WHERE ims.unique_code = '$request->uniqueCode'";
        try {
            $staffDetails = $this->executeQueryForList($sql);
            return $staffDetails;
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function getConsolidateStaffWorkingHoursForStaffWorkingHourReport($request)
    {
        $request = $this->realEscapeObject($request);
        try 
        {
            $request->staffId?$where[] = " sbs.staffID in ( $request->staffId":"";
            $request->batchId?$where[] = " sbs.batchID in ( $request->batchId":"";
            $request->deptId?$where[] = " bat.deptID = $request->deptId ":"";
            $request->fromDate && $request->toDate?$where[] = " ac.attendanceDate between '$request->fromDate' and '$request->toDate":"";
            $request->fromDate && $request->toDate?$where[] = " ac.attendanceDate NOT IN (SELECT FROM_UNIXTIME(timeStart, '%Y-%m-%d')from lms_calender lc where timeStart BETWEEN  UNIX_TIMESTAMP('$request->fromDate') and UNIX_TIMESTAMP('$request->toDate') and flag =3)":"";
            // $sql = "select sbs.staffID,ac.attendanceDate,st.staffName,count(distinct ac.hour,sbs.subjectID) as dayCount from attendance_confirm ac
            // inner join sbs_relation sbs on sbs.sbsID = ac.sbsID
            // inner join staffaccounts st on st.staffID =  sbs.staffID
            // inner join batches bat on bat.batchID = sbs.batchID
            // ".($where?" WHERE ".implode(' AND ',$where):"")."
            // group by ac.attendanceDate,sbs.staffID
            // order by sbs.staffID,ac.attendanceDate;";
            $cond = ($where?" WHERE ".implode(' AND ',$where):"");
            $sql  = "SELECT
                        sbs.staffID,
                        st.staffName,
                        bat.batchID ,
                        bat.batchName,
                        s.subjectID ,
                        s.subjectName,
                        s.subjectDesc,
                        ac.hour,
                        sbs.subjectID
                    from
                        attendance_confirm ac
                    inner join sbs_relation sbs on
                        sbs.sbsID = ac.sbsID
                    inner join staffaccounts st on
                        st.staffID = sbs.staffID
                    inner join batches bat on
                        bat.batchID = sbs.batchID
                    inner join subjects s on
                        s.subjectID = sbs.subjectID
                           ".$cond."
                    order by
                        sbs.staffID,
                        ac.attendanceDate";
            return $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    // External API - CALLED FROM LIN-API PROJECT
    public function getStaffDetailsForApi(){
        $sql = "SELECT s.staffName , s.staffCode , s.staffEmail ,s.staffPhone , s.staffAddress , d.deptName , sd.name as designation,  s.isResigned 
                from staffaccounts s 
                left join department d on d.deptID = s.deptID 
                left join staff_designation sd on sd.id = s.academicDesignationID ";
        try{
            return $this->executeQueryForList($sql);
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    
    // External API - CALLED FROM LIN-API PROJECT
    public function getClassTutorDetails(){
        $sql = "SELECT s.staffName, g.name as batchName, at.name as semesterName, 
                COUNT(gm.student_id) AS studentCount, d.deptName as departmentName, 
                vs.name AS schoolName
            FROM groups_tutor gt 
            INNER JOIN `groups` g ON g.id = gt.groups_id 
            INNER JOIN staffaccounts s ON s.staffID = gt.staff_id 
            INNER JOIN academic_term at ON at.id = gt.academic_term_id
            INNER JOIN department d ON d.deptID = s.deptID 
            INNER JOIN group_members gm ON gm.groups_id = g.id
            LEFT JOIN v4_school vs ON vs.id = d.school_id
            WHERE gm.academic_status IN ('ACTIVE')
            GROUP BY g.id, at.id ";
        try{
            return $this->executeQueryForList($sql);
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    
    // External API - CALLED FROM LIN-API PROJECT
    public function teachingPlanUploadStatusReport()
    {
        $whereQuery = "";
        $lpDateQuery = "";
        $tDateQuery = "";
        $apDateQuery = "";
        $scDateQuery = "";
        $groupByClausePp = " GROUP BY lpsp.cluster_id ";
        $groupByClauseAp = " GROUP BY lasp4.cluster_id ";
        $groupByClauseVt = " GROUP BY vt.cluster_id";
        $groupByClauseSc = " GROUP BY lasp.cluster_id";
        try {
           
            $whereQuery .= " AND g.academic_term_id = sg.academic_term_id";
            $sql = "SELECT DISTINCT c.id as clusterId , at.name AS academicTerm, s.staffID as staffId,vas.name as courseName,vas.code as courseCode,
                    caps.properties->>'$.credit' as credit,
                    caps.properties->>'$.hourSplitup' as hourSplitup,
                    s.staffName , c.name, p.id as programId, p.name as programName, g.id as groupId, g.name as section,
                    d.deptName as studentDepartment, d2.deptName as staffDepartment,d2.deptID as staffDeptId from cluster c
                    INNER JOIN cluster_members cm ON cm.cluster_id = c.id AND c.trashed IS NULL
                    INNER JOIN staffaccounts s ON s.staffID = cm.staff_id
                    INNER JOIN cluster_groups_relations cgr ON cgr.cluster_id = c.id
                    INNER JOIN `groups` sg ON sg.id = cgr.groups_id
                    INNER JOIN groups_relations gr ON gr.child_groups_id = sg.id
                    INNER JOIN group_members gm ON gm.groups_id = cgr.groups_id AND gm.academic_status = 'ACTIVE'
                    INNER JOIN `groups` g ON g.id = gr.parent_groups_id
                    INNER JOIN program p ON p.id = g.program_id
                    INNER JOIN program_department_relation pdr ON pdr.program_id = p.id
                    INNER JOIN department d ON d.deptID = pdr.department_id
                    INNER JOIN cm_academic_paper_subjects caps ON caps.id = sg.paperSubjectId
                    INNER JOIN v4_ams_subject vas ON vas.id = caps.ams_subject_id
                    INNER JOIN v4_ams_staff_department_relations vasdr ON vasdr.staff_id = s.staffID
                    INNER JOIN department d2 ON d2.deptID = vasdr.department_id
                    INNER JOIN academic_term at ON at.id = sg.academic_term_id
                    WHERE 1=1 ". $whereQuery  ;
            $clusterDetails = $this->executeQueryForList($sql,  $this->mapper[StaffServiceMapper::GET_CLUSTER_DETAILS]);
            foreach ($clusterDetails as $program) {
                $program->programName = html_entity_decode($program->programName);
                foreach($program->batchDetails as $batch){
                    foreach($batch->clusterDetails as $cluster){
                        $clusterIds[] = $cluster->clusterId;
                    }
                }
            }
            $sql = "SELECT lpsp.cluster_id , 
                        lpsp.created_by as staffId,
                        COUNT(id) as lpCount from lp_proposed_subject_plans lpsp
                    WHERE lpsp.cluster_id  IN ('" . implode("','", $clusterIds) . "') 
                        AND lpsp.name IS NOT NULL
                        AND lpsp.module_id IS NOT NULL
                        AND lpsp.mode_of_instruction_type_id IS NOT NULL 
                        AND lpsp.`date` IS NOT NULL 
                        AND lpsp.lecture_hour_id IS NOT NULL
                        $lpDateQuery
                        $groupByClausePp "; // group by only clusterid in case dualaccess
            $ldData = $this->executeQueryForList($sql);
            $query = "SELECT vt.cluster_id , vt.staff_id,
                        COUNT(vt.id) as timetableCount,
                        COUNT(CASE WHEN is_open_to_all = '1' THEN 1 END) AS openToAllCount,
                        COUNT(case WHEN vtsh.id IS NOT NULL THEN 1 END) AS openToSpecificCount,
                        COUNT(CASE WHEN vt.already_marked = 1 OR vamu.id IS NOT NULL THEN 1 END) AS markedCount,
                        COUNT(CASE WHEN vamu.staff_id = vt.staff_id OR is_open_to_all = '1' THEN 1 END) as recivedHour,
                        COUNT(case WHEN (vt.suspended = 1 AND vt.is_holiday = 0) THEN 1 END) as suspendedHour
                        FROM v4_timetable vt
                        LEFT JOIN v4_timetable_swap_hour vtsh ON vtsh.v4_timetable_id = vt.id
                        LEFT JOIN v4_attendance_marked_user vamu ON vamu.cluster_id = vt.cluster_id AND vamu.attendance_date = vt.`date` AND vamu.marked_hour = vt.`hour` AND vamu.staff_id = vt.staff_id
                        WHERE vt.cluster_id  IN ('" . implode("','", $clusterIds) . "') $tDateQuery
                        $groupByClauseVt"; // group by clause for handling dual access
            $timetableData =  $this->executeQueryForList($query);
            $holidayQuery = " SELECT
                    vt.cluster_id,
                    vt.staff_id,
                    COUNT(CASE WHEN vt.`hour` IS NOT NULL AND vt.is_holiday > 0 THEN 1 END) AS holidaycount
                FROM
                    v4_timetable vt
                WHERE vt.cluster_id  IN ('" . implode("','", $clusterIds) . "') $tDateQuery
                $groupByClauseVt"; // group by clause for handling dual access
                $holidayCount = $this->executeQueryForList($holidayQuery);
                // handle the below for each iteration for dual access and normal case
                foreach ($clusterDetails as $program) {
                    foreach($program->batchDetails as $batch){
                        foreach ($batch->clusterDetails as $clusterKey => $cluster){
                                    $lpProposedCount = 0;
                                    $suspendedHour = 0;
                                    $holidaycount = 0;
                                    $timetableCount = 0;
                                    $cluster->uploadStatus = "NO";
                                    foreach ($ldData as $keyLp => $lp) {
                                        if($lp->cluster_id === $cluster->clusterId ){
                                            $lpProposedCount =  $lp->lpCount;
                                            $lpProposedCount > 0 ? $cluster->uploadStatus = "YES" : $cluster->uploadStatus = "NO";
                                            break;
                                        }
                                    }
                                    foreach ($timetableData as $keyTt => $timetable) {
                                        if($timetable->cluster_id === $cluster->clusterId ){
                                            $timetableCount =  $timetable->timetableCount;
                                            $suspendedHour =  $timetable->suspendedHour;
                                            break;
                                        }
                                    }
                                    foreach ($holidayCount as $keyH => $holiday) {
                                        if($holiday->cluster_id === $cluster->clusterId ){
                                            $holidaycount =  $holiday->holidaycount;
                                            break;
                                        }
                                    }
                                    // Calculate plan variance percentage
                                    $totalReceived = isset($timetableCount) ? (int)$timetableCount : 0;
                                    $totalLost = (isset($holidaycount) ? (int)$holidaycount : 0) + (isset($suspendedHour) ? (int)$suspendedHour : 0);
                                    $asPerTimeTable = max($totalReceived - $totalLost, 0);
                                    $unplannedSession = $asPerTimeTable - (isset($lpProposedCount) ? (int)$lpProposedCount : 0);
                                    $planVariance = $asPerTimeTable !== 0 ? round(($unplannedSession / $asPerTimeTable) * 100,2) : 0;
                                    $cluster->planVariancePercentage = $planVariance;
                                    
    
                        }
                        $batch->clusterDetails = array_values($batch->clusterDetails);
                    }
                }
            return $clusterDetails;
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    
    // External API - CALLED FROM LIN-API PROJECT
    public function syallabusCoverageReport(){
        $whereQuery = "";
        $lpDateQuery = "";
        $tDateQuery = "";
        $apDateQuery = "";
        $scDateQuery = "";
        $groupByClausePp = " GROUP BY lpsp.cluster_id ";
        $groupByClauseAp = " GROUP BY lasp4.cluster_id ";
        $groupByClauseVt = " GROUP BY vt.cluster_id";
        $groupByClauseSc = " GROUP BY lasp.cluster_id";
        try {
            $whereQuery .= " AND g.academic_term_id = sg.academic_term_id";
            $sql = "SELECT DISTINCT c.id as clusterId , at.name AS academicTerm, s.staffID as staffId,vas.name as courseName,vas.code as courseCode,
                    caps.properties->>'$.credit' as credit,
                    caps.properties->>'$.hourSplitup' as hourSplitup,
                    s.staffName , c.name, p.id as programId, p.name as programName, g.id as groupId, g.name as section,
                    d.deptName as studentDepartment, d2.deptName as staffDepartment,d2.deptID as staffDeptId from cluster c
                    INNER JOIN cluster_members cm ON cm.cluster_id = c.id AND c.trashed IS NULL
                    INNER JOIN staffaccounts s ON s.staffID = cm.staff_id
                    INNER JOIN cluster_groups_relations cgr ON cgr.cluster_id = c.id
                    INNER JOIN `groups` sg ON sg.id = cgr.groups_id
                    INNER JOIN groups_relations gr ON gr.child_groups_id = sg.id
                    INNER JOIN group_members gm ON gm.groups_id = cgr.groups_id AND gm.academic_status = 'ACTIVE'
                    INNER JOIN `groups` g ON g.id = gr.parent_groups_id
                    INNER JOIN program p ON p.id = g.program_id
                    INNER JOIN program_department_relation pdr ON pdr.program_id = p.id
                    INNER JOIN department d ON d.deptID = pdr.department_id
                    INNER JOIN cm_academic_paper_subjects caps ON caps.id = sg.paperSubjectId
                    INNER JOIN v4_ams_subject vas ON vas.id = caps.ams_subject_id
                    INNER JOIN v4_ams_staff_department_relations vasdr ON vasdr.staff_id = s.staffID
                    INNER JOIN department d2 ON d2.deptID = vasdr.department_id
                    INNER JOIN academic_term at ON at.id = sg.academic_term_id
                    WHERE 1=1 ". $whereQuery  ;
            $clusterDetails = $this->executeQueryForList($sql,  $this->mapper[StaffServiceMapper::GET_CLUSTER_DETAILS]);
            foreach ($clusterDetails as $program) {
                $program->programName = html_entity_decode($program->programName);
                foreach($program->batchDetails as $batch){
                    foreach($batch->clusterDetails as $cluster){
                        $clusterIds[] = $cluster->clusterId;
                    }
                }
            }
            $sql = "SELECT lpsp.cluster_id , 
                        lpsp.created_by as staffId,
                        COUNT(id) as lpCount from lp_proposed_subject_plans lpsp
                    WHERE lpsp.cluster_id  IN ('" . implode("','", $clusterIds) . "') 
                        AND lpsp.name IS NOT NULL
                        AND lpsp.module_id IS NOT NULL
                        AND lpsp.mode_of_instruction_type_id IS NOT NULL 
                        AND lpsp.`date` IS NOT NULL 
                        AND lpsp.lecture_hour_id IS NOT NULL
                        $lpDateQuery
                        $groupByClausePp "; // group by only clusterid in case dualaccess
            $ldData = $this->executeQueryForList($sql);
            
            $sql = "SELECT
                lasp4.cluster_id,
                lasp4.created_by as staffId,
                COUNT(lasp4.is_covered) as apCount
                FROM
                    (
                    SELECT
                        lasp.cluster_id ,
                        lasp.created_by ,
                        lasp3.is_covered
                        --     COUNT(lasp3.is_covered) as apCount
                    FROM
                        lp_actual_subject_plans lasp
                    INNER JOIN (
                        SELECT
                            proposed_plan_id,
                            MAX(updated_date) as latest_date
                        FROM
                            lp_actual_subject_plans lasp2
                        GROUP BY
                            proposed_plan_id) AS lasp2 ON
                        lasp.proposed_plan_id = lasp2.proposed_plan_id
                        AND lasp.updated_date = lasp2.latest_date
                    INNER JOIN (
                        select
                            proposed_plan_id ,
                            updated_date,
                            is_covered
                        from
                            lp_actual_subject_plans lasp3 ) AS lasp3 ON
                        lasp3.proposed_plan_id = lasp2.proposed_plan_id
                        AND lasp3.updated_date = lasp2.latest_date
                    WHERE
                        lasp3.is_covered = '2'
                        $apDateQuery
                        AND cluster_id  IN ('" . implode("','", $clusterIds) . "')
                    GROUP BY
                        lasp.proposed_plan_id) lasp4
                $groupByClauseAp";  // handle group by clause for dual access for collecting fully covered actual plans
            $apData = $this->executeQueryForList($sql);
            
            $sql = "SELECT
                        lasp.cluster_id ,
                        count(distinct lasp.proposed_plan_id) AS sessionCount,
                        lasp.created_by as staffId
                FROM
                    lp_actual_subject_plans lasp
                WHERE
                    cluster_id IN ('" . implode("','", $clusterIds) . "')
                    $scDateQuery
                $groupByClauseSc";
            $sessionCount = $this->executeQueryForList($sql); /*** CLASSIRIFICATION REGARDING THIS QUERY */
            $query = "SELECT vt.cluster_id , vt.staff_id,
                        COUNT(vt.id) as timetableCount,
                        COUNT(CASE WHEN is_open_to_all = '1' THEN 1 END) AS openToAllCount,
                        COUNT(case WHEN vtsh.id IS NOT NULL THEN 1 END) AS openToSpecificCount,
                        COUNT(CASE WHEN vt.already_marked = 1 OR vamu.id IS NOT NULL THEN 1 END) AS markedCount,
                        COUNT(CASE WHEN vamu.staff_id = vt.staff_id OR is_open_to_all = '1' THEN 1 END) as recivedHour,
                        COUNT(case WHEN (vt.suspended = 1 AND vt.is_holiday = 0) THEN 1 END) as suspendedHour
                        FROM v4_timetable vt
                        LEFT JOIN v4_timetable_swap_hour vtsh ON vtsh.v4_timetable_id = vt.id
                        LEFT JOIN v4_attendance_marked_user vamu ON vamu.cluster_id = vt.cluster_id AND vamu.attendance_date = vt.`date` AND vamu.marked_hour = vt.`hour` AND vamu.staff_id = vt.staff_id
                        WHERE vt.cluster_id  IN ('" . implode("','", $clusterIds) . "') $tDateQuery
                        $groupByClauseVt"; // group by clause for handling dual access
            $timetableData =  $this->executeQueryForList($query);
            $holidayQuery = " SELECT
                    vt.cluster_id,
                    vt.staff_id,
                    COUNT(CASE WHEN vt.`hour` IS NOT NULL AND vt.is_holiday > 0 THEN 1 END) AS holidaycount
                FROM
                    v4_timetable vt
                WHERE vt.cluster_id  IN ('" . implode("','", $clusterIds) . "') $tDateQuery
                $groupByClauseVt"; // group by clause for handling dual access
                $holidayCount = $this->executeQueryForList($holidayQuery);
                // handle the below for each iteration for dual access and normal case
                foreach ($clusterDetails as $program) {
                    foreach($program->batchDetails as $batch){
                        foreach ($batch->clusterDetails as $clusterKey => $cluster){
                                    // $lpProposedCount = 0;
                                    // $suspendedHour = 0;
                                    // $holidaycount = 0;
                                    // $timetableCount = 0;
                                    // $apProposedCount = 0;
                                    $cluster->uploadStatus = "NO";
                                    foreach ($ldData as $keyLp => $lp) {
                                        if($lp->cluster_id === $cluster->clusterId ){
                                            $lpProposedCount =  $lp->lpCount;
                                            $lpProposedCount > 0 ? $cluster->uploadStatus = "YES" : $cluster->uploadStatus = "NO";
                                            break;
                                        }
                                    }
                                    foreach ($apData as $keyAp => $lp) {
                                        if($lp->cluster_id === $cluster->clusterId ){
                                            $apProposedCount =  $lp->apCount;
                                            // unset($apData[$keyAp]);
                                            break;
                                        }
                                    }
                                    foreach ($sessionCount as $keyAp => $lp) {
                                        if($lp->cluster_id === $cluster->clusterId ){
                                            $cluster->sessionCount =  $lp->sessionCount;
                                            // unset($apData[$keyAp]);
                                            break;
                                        }
                                    }
                                    foreach ($timetableData as $keyTt => $timetable) {
                                        if($timetable->cluster_id === $cluster->clusterId ){
                                            $timetableCount =  $timetable->timetableCount;
                                            $suspendedHour =  $timetable->suspendedHour;
                                            break;
                                        }
                                    }
                                    foreach ($holidayCount as $keyH => $holiday) {
                                        if($holiday->cluster_id === $cluster->clusterId ){
                                            $holidaycount =  $holiday->holidaycount;
                                            break;
                                        }
                                    }
                                    $sessionCountValue = isset($cluster->sessionCount) ? (int)$cluster->sessionCount : 0;
                                            
                                    // in case of N/A coverage variance is taken as 0
                                    if($sessionCountValue === 0){
                                        $coverageVariance = 0;
                                    }
                                    else{
                                        $coverageVariance = round((($sessionCountValue - (isset($apProposedCount) ? (int)$apProposedCount : 0)) / $sessionCountValue) * 100,2);
                                    }
                                    $cluster->coverageVariance = $coverageVariance;
                                    
                                    // Calculate completion status
                                    $cluster->completionStatusPercentage = 0;
                                    if( isset($apProposedCount) && isset($lpProposedCount) && $lpProposedCount > 0){
                                        $cluster->completionStatusPercentage = round(($apProposedCount / $lpProposedCount) * 100,2);
                                    }
                        }
                        $batch->clusterDetails = array_values($batch->clusterDetails);
                    }
                }
            return $clusterDetails;
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    
    // External API - CALLED FROM LIN-API PROJECT
    public function unmarkedAttendanceDetails()
    {
        $whereCondition = " AND bg.academic_term_id = sg.academic_term_id AND vamu.attendance_date BETWEEN DATE_SUB(CURDATE(), INTERVAL 30 DAY) AND CURDATE() ";
        
        $query1="SELECT
            bg.id as batchId,
            c.id as clusterId,
            c.name as clusterName,
            GROUP_CONCAT(DISTINCT bg.name ORDER BY bg.name SEPARATOR ',') AS batch,             
            vas.id,
            vas.name as subject,
            vas.code as subjectCode,
            s.staffName,
            s.staffID,
            caps.properties->>'$.credit' as credit,
            vamu.marked_hour,
            at.name as academicTerm,
            COUNT(DISTINCT CASE WHEN vamu.id IS NOT NULL THEN CONCAT(vamu.id, vamu.attendance_date, vamu.marked_hour, vamu.cluster_id) END)  as markedHours,
            COUNT(DISTINCT CASE WHEN assignedvt.id IS NOT NULL AND assignedSwappedvt.id IS NULL AND assignedvt.suspended != 1 AND (assignedvt.is_holiday = 0 OR assignedvt.is_holiday IS NULL) THEN CONCAT (assignedvt.`date`, assignedvt.hour ) END) + (COUNT(DISTINCT gainedMarkedAttendance.id)) as assignedttcount,
            COUNT(DISTINCT CASE WHEN ((assignedvt.id IS NOT NULL AND assignedvt.already_marked IS NULL AND markedVamu.id IS NULL AND assignedSwappedvt.id IS NULL AND assignedvt.suspended != 1  AND (assignedvt.is_holiday = 0 OR assignedvt.is_holiday IS NULL)) OR (gainedSwapHour.id IS NOT NULL AND gainedMarkedAttendance.id IS NULL)) THEN CONCAT(assignedvt.`date`, assignedvt.hour) END) 
            + COUNT(DISTINCT CASE WHEN (gainedSwapHour.id IS NOT NULL AND gainedMarkedAttendance.id IS NULL) THEN gainedSwapHour.id END) AS unmarkedHours
            from
                cluster c
            inner join cluster_members cm on
                c.id = cm.cluster_id
            inner join staffaccounts s on
                s.staffID = cm.staff_id
                AND s.isResigned <> 1
            inner join cluster_groups_relations cgr on
                cgr.cluster_id = c.id
            inner join `groups` sg on
                sg.id = cgr.groups_id
            inner join `academic_term` at on
                at.id = sg.academic_term_id
            inner join groups_relations gr on
                gr.child_groups_id = sg.id
            inner join `groups` bg on
                bg.id = gr.parent_groups_id
            inner join program p on
                p.id = bg.program_id 
            inner join program_department_relation pdr on
                pdr.program_id = p.id 
            inner join department d on
                d.deptID = pdr.department_id 
            inner join cm_academic_paper_subjects caps on
                caps.id = sg.paperSubjectId
            inner join v4_ams_subject vas on
                vas.id = caps.ams_subject_id
            left join v4_attendance_marked_user vamu on
                vamu.cluster_id = c.id
                AND vamu.staff_id = s.staffID
            left JOIN v4_timetable assignedvt ON
                assignedvt.cluster_id = c.id
                AND assignedvt.staff_id = s.staffID 
                AND assignedvt.`date` <= CURDATE() 
            left join v4_timetable_swap_hour assignedSwappedvt on
                assignedSwappedvt.v4_timetable_id = assignedvt.id
            LEFT JOIN v4_timetable_swap_hour gainedSwapHour ON
                gainedSwapHour.staff_id = s.staffID
            LEFT JOIN v4_attendance_marked_user gainedMarkedAttendance ON
                gainedMarkedAttendance.time_table_id = gainedSwapHour.v4_timetable_id 
            LEFT JOIN v4_attendance_marked_user markedVamu ON 
                assignedvt.cluster_id = markedVamu.cluster_id 
                AND assignedvt.`hour` = markedVamu.marked_hour 
                AND assignedvt.`date` = markedVamu.attendance_date 
                AND assignedvt.staff_id = s.staffID 
            WHERE
                1=1 
                $whereCondition 
            GROUP BY
                c.id,s.staffName
            ORDER BY
                s.staffName ASC";     
        try{
            $result =$this->executeQueryForList($query1,$this->mapper[StaffServiceMapper::UNMARKED_ATTENDANCE_DETAILS]);
            return $result;
        }catch(\Exception $e){
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    
    // External API - CALLED FROM LIN-API PROJECT
    public function clusterWiseStudentAttendance($offset = 0, $clusterCount = 150)
    {
        try{
            $clustersToFetch = $this->executeQueryForList("SELECT
                                                           c.id as clusterId
                                                           FROM cluster c
                                                           INNER JOIN cluster_members cm ON
                                                               cm.cluster_id = c.id
                                                           INNER JOIN staffaccounts staff ON
                                                               staff.staffID = cm.staff_id
                                                           INNER JOIN cluster_groups_relations cgr ON
                                                               cgr.cluster_id = c.id
                                                           INNER JOIN `groups` sg ON
                                                               sg.id = cgr.groups_id
                                                           INNER JOIN groups_relations gr ON
                                                               gr.child_groups_id = sg.id
                                                           INNER JOIN `groups` g ON
                                                               g.id = gr.parent_groups_id
                                                           INNER JOIN academic_term at ON
                                                               at.id = g.academic_term_id
                                                           INNER JOIN group_members gm ON 
                                                               gm.groups_id = sg.id
                                                           INNER JOIN student_program_account spa ON
                                                               spa.id = gm.student_id 
                                                           INNER JOIN studentaccount s ON
                                                               s.studentID = spa.student_id
                                                           INNER JOIN v4_attendance va ON
                                                               va.cluster_id = c.id AND va.student_id = s.studentID
                                                           WHERE gm.academic_status IN ('ACTIVE', 'COMPLETED') 
                                                               AND c.trashed IS NULL 
                                                               AND sg.academic_term_id = g.academic_term_id
                                                           GROUP BY c.id
                                                           ORDER BY c.id ASC 
                                                           LIMIT $offset$clusterCount");
                                                            
            $clusterIds = array_column($clustersToFetch, 'clusterId');
            
            $totalRecords = $this->executeQueryForObject("SELECT
                                                        COUNT(c.id) AS count
                                                        FROM cluster c
                                                        INNER JOIN cluster_members cm ON
                                                            cm.cluster_id = c.id
                                                        INNER JOIN staffaccounts staff ON
                                                            staff.staffID = cm.staff_id
                                                        INNER JOIN cluster_groups_relations cgr ON
                                                            cgr.cluster_id = c.id
                                                        INNER JOIN `groups` sg ON
                                                            sg.id = cgr.groups_id
                                                        INNER JOIN groups_relations gr ON
                                                            gr.child_groups_id = sg.id
                                                        INNER JOIN `groups` g ON
                                                            g.id = gr.parent_groups_id
                                                        INNER JOIN academic_term at ON
                                                            at.id = g.academic_term_id
                                                        INNER JOIN group_members gm ON 
                                                            gm.groups_id = sg.id
                                                        INNER JOIN student_program_account spa ON
                                                            spa.id = gm.student_id 
                                                        INNER JOIN studentaccount s ON
                                                            s.studentID = spa.student_id
                                                        INNER JOIN v4_attendance va ON
                                                            va.cluster_id = c.id AND va.student_id = s.studentID
                                                        WHERE gm.academic_status IN ('ACTIVE', 'COMPLETED') 
                                                            AND c.trashed IS NULL 
                                                            AND sg.academic_term_id = g.academic_term_id
                                                        GROUP BY c.id");
            
            $query = "SELECT
                        c.id as clusterId,
                        c.name as clusterName, 
                        GROUP_CONCAT(DISTINCT staff.staffName) AS staffName,
                        GROUP_CONCAT(DISTINCT g.name) AS batchName,
                        at.name as semester,
                        s.studentID,
                        s.studentName,
                        -- PRESENT HOURS
                        COUNT(DISTINCT CASE WHEN 
                            va.is_absent = 0 OR va.grant_leave IS NOT NULL
                            THEN CONCAT(va.student_id, va.attendance_date, va.start_time, va.end_time)
                            END) 
                        AS presentHours,
                        -- TOTAL HOURS
                        COUNT(DISTINCT CONCAT(va.student_id, va.attendance_date, va.start_time, va.end_time)) 
                        AS totalHours,
                        -- ATTENDANCE PERCENTAGE
                            ROUND(
                            (COUNT(DISTINCT CASE 
                                WHEN va.is_absent = 0 OR va.grant_leave IS NOT NULL
                                THEN CONCAT(va.student_id, va.attendance_date, va.start_time, va.end_time)
                                END) 
                            / COUNT(DISTINCT CONCAT(va.student_id, va.attendance_date, va.start_time, va.end_time))) * 100, 
                            2
                        ) AS attendancePercentage,
                        -- TOTAL CLUSTER STUDENTS
                        (SELECT COUNT(DISTINCT studentaccount.studentID)
                            FROM studentaccount 
                        INNER JOIN student_program_account spa2 ON spa2.student_id = studentaccount.studentID
                        INNER JOIN group_members gm2 ON gm2.student_id = spa2.id
                        WHERE gm2.academic_status IN ('ACTIVE', 'COMPLETED')
                        AND gm2.groups_id IN (
                            SELECT sg2.id
                            FROM cluster_groups_relations cgr2
                            INNER JOIN `groups` sg2 ON sg2.id = cgr2.groups_id
                            WHERE cgr2.cluster_id = c.id
                        )
                        ) AS totalStudentCount
                    FROM cluster c
                    INNER JOIN cluster_members cm ON
                        cm.cluster_id = c.id
                    INNER JOIN staffaccounts staff ON
                        staff.staffID = cm.staff_id
                    INNER JOIN cluster_groups_relations cgr ON
                        cgr.cluster_id = c.id
                    INNER JOIN `groups` sg ON
                        sg.id = cgr.groups_id
                    INNER JOIN groups_relations gr ON
                        gr.child_groups_id = sg.id
                    INNER JOIN `groups` g ON
                        g.id = gr.parent_groups_id
                    INNER JOIN academic_term at ON
                        at.id = g.academic_term_id
                    INNER JOIN group_members gm ON 
                        gm.groups_id = sg.id
                    INNER JOIN student_program_account spa ON
                        spa.id = gm.student_id 
                    INNER JOIN studentaccount s ON
                        s.studentID = spa.student_id
                    INNER JOIN v4_attendance va ON
                        va.cluster_id = c.id AND va.student_id = s.studentID
                    WHERE gm.academic_status IN ('ACTIVE', 'COMPLETED') 
                          AND c.trashed IS NULL 
                          AND sg.academic_term_id = g.academic_term_id
                          AND c.id IN ('" . implode("','", $clusterIds) . "')
                    GROUP BY c.id, s.studentID";
        
            $result = $this->executeQueryForList($query);
            
            $clusterWiseData = [];
            foreach ($result as $row) {
                $clusterId = $row->clusterId;
                if (!isset($clusterWiseData[$clusterId])) {
                    // Storing first record of each cluster
                    $clusterWiseData[$clusterId] = [
                        'clusterName' => $row->clusterName,
                        'staffName' => $row->staffName,
                        'batchName' => $row->batchName,
                        'semester' => $row->semester,
                        'totalStudents' => $row->totalStudentCount,
                        'studentsBelow75' => 0
                    ];
                } else if (strpos($clusterWiseData[$clusterId]['batchName'], $row->batchName) === false) {
                    // Concating unique batch names against each cluster with comma separator
                    $clusterWiseData[$clusterId]['batchName'] .= ', ' . $row->batchName;
                }
                // Once cluster is stored in $clusterWiseData, count students with attendance percentage less than 75 for that cluster
                if (isset($row->attendancePercentage) && is_numeric($row->attendancePercentage) && floatval($row->attendancePercentage) < 75) {
                    $clusterWiseData[$clusterId]['studentsBelow75']++;
                }
            }
            
            $response = new stdClass();
            $response->totalRecords = $totalRecords->count;
            $response->data = array_values($clusterWiseData);
            return $response;
            
        }catch(\Exception $e){
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function getBackgroundImage($userType, $isMobile){
        $image = null;
        if($userType === 'STAFF'){
            $image = $GLOBALS["COLLEGE_FACULTY_LOGIN_BACKGROUND"];
        }
        if($userType === 'STUDENT'){
            $image = $GLOBALS["COLLEGE_STUDENT_LOGIN_BACKGROUND"];
        }
        if($userType === 'PARENT'){
            $image = $GLOBALS["COLLEGE_PARENT_LOGIN_BACKGROUND"];
        }
        $baseUrl = CommonUtil::getBaseUrl();
        // $bgImage = empty($GLOBALS["COLLEGE_HOME_PAGE_BACKGROUND"]) ? $GLOBALS["DEFAULT_HOME_PAGE_BACKGROUND_IMAGE"] : $GLOBALS["COLLEGE_HOME_PAGE_BACKGROUND"];
        $bgImage = $image;
        if(!empty($bgImage)){
            $Image = $baseUrl.$bgImage ;
        }
     
        try{
            return $Image;
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    
    /**
     * get staff student fro digital val    *
     * @param int $request
     * @return object|NULL|$objectList[]
     * @throws ProfessionalException
     */
    public function getStaffStudentsForDigitalValuation($request){
        $request = $this->realEscapeObject($request);
        $condition = "";
        $groupBy ="";
        if($request->examRegId){
            $condition .= " AND esas.examRegId IN ($request->examRegId" ;
        }
        if($request->subjectId){
            $condition .= " AND esas.subjectId IN ($request->subjectId" ;
        }
        if($request->examType){
            $condition .= " AND esas.examType = '$request->examType" ;
        }
        if($request->valuationCount){
            $condition .= " AND esas.valuationCount IN ($request->valuationCount)" ;
        }
        if($request->staffId){
            $condition .= " AND esas.staffId IN ($request->staffId)" ;
        }
        if($request->groupByStaff){
            $groupBy = " GROUP BY esas.staffId";
        }
        $sql = "SELECT  esas.staffId,sa.staffName,esas.studentId  FROM examValuationStaffAssignedStudents  esas
                INNER JOIN staffaccounts sa ON sa.staffID = esas.staffId
                WHERE 1=1 $condition $groupBy";
        try {
            $staffDetails = $this->executeQueryForList($sql);
            return $staffDetails;
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    
    public function getStaffDetailsByStaffCode($staffCode)
    {
        try{
            $staffCode = $this->realEscapeString($staffCode);
            $sql = " SELECT s.staffID ,s.designationID,s.sectionID  FROM staffaccounts s  WHERE s.staffCode = '$staffCode' and isResigned =0";
            return $this->executeQueryForObject($sql);
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function getAllNonResignedStaff()
    {
        $sql = "SELECT staffID,staffAccount,staffName,staffCode,staffEmail FROM staffaccounts  WHERE isResigned =0";
        try{
            return $this->executeQueryForList($sql);
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function getAllEscalationLeaveStaffs()
    {
        try{
            $sql = "SELECT le.id,
                           le.staffID,
                           sa.staffName,
                           le.time_of_escalation_in_minutes,
                           le.created_date ,
                           hd.designationName,
                           le.designations
                           FROM leaveEscalation le
                           INNER JOIN staffaccounts sa on sa.StaffID = le.staffID
                           LEFT JOIN hr_designations hd on hd.designationID = sa.designationID";
            return $this->executeQueryForList($sql);
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function addEscalationLeaveStaffs($assignedStaffs, $hours, $minutes, $designations)
    {
        try{
            $assignedStaffs = $this->realEscapeArray($assignedStaffs);
            $time_setter = "";
            $staffID = $_SESSION['adminID'];
            $designations = json_encode($designations);
    
            if($hours)
            {
                if($minutes)
                {
                    $formatted_minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT);
                }
                
                $minutes = $minutes ? $formatted_minutes : "00";
    
                $formatted_hours = str_pad($hours, 2, '0', STR_PAD_LEFT);
                $time = $formatted_hours . ":$minutes:00";
                $time_setter .=  $time;
            }
            else{
                if($minutes)
                {
                    $formatted_minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT);
                    $time = "00:$formatted_minutes:00";
                    $time_setter .=  $time;
                }   
    
            }
    
            $sql = "INSERT
                        IGNORE
                        INTO
                        leaveEscalation (staffID,
                        time_of_escalation_in_minutes,
                        created_by,
                        updated_by,
                        created_date,
                        updated_date,
                        designations)
                    VALUES ";
            $entries = [];
            foreach ($assignedStaffs as $staffID) {
                    $entries[] = "($staffID,'$time_setter',$staffID,$staffID,NOW(),NOW(),'$designations' )";
            }
            $sqlEntries = implode(",",$entries);
            $sql .= $sqlEntries;
            $this->executeQuery($sql);
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
       
        return true;
    }
    public function uniassignFacultyFromEscalation($id)
    {
        try{
            $id = $this->realEscapeString($id);
            $sql = "DELETE FROM leaveEscalation WHERE id = $id";
            $this->executeQuery($sql);
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return true;
    }
    public function updateTimeOfLeaveEscalation($id, $hours, $minutes , $designationsToUpdate)
    {
        try{
            $id = $this->realEscapeString($id);
            $hour = $this->realEscapeString($hour);
            $minute = $this->realEscapeString($minute);
            $designationsToUpdate = $this->realEscapeArray($designationsToUpdate);
            $designation = json_encode($designationsToUpdate);
            // $minute = $minute == "-" ? "00":$minute;
            // $hour = $hour == "-" ? "00":$hour;
            $time_setter = "0000-00-00 ";
            $staffID = $_SESSION['adminID'];
    
            if($hours)
            {
                if($minutes)
                {
                    $formatted_minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT);
                }
                
                $minutes = $minutes ? $formatted_minutes : "00";
    
                $formatted_hours = str_pad($hours, 2, '0', STR_PAD_LEFT);
                $time = $formatted_hours . ":$minutes:00";
                $time_setter .=  $time;
            }
            else{
                if($minutes)
                {
                    $formatted_minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT);
                    $time = "00:$formatted_minutes:00";
                    $time_setter .=  $time;
                }   
    
            }
            $sql = "UPDATE leaveEscalation SET time_of_escalation_in_minutes = '$time_setter', updated_by = $staffID, designations = '$designation' WHERE id = '$id'";
            $this->executeQuery($sql);
            
            
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return true;
    }
    public function getStaffDetailsByStaffAccount($staffaccount)
    {
        try{
            $staffaccount = $this->realEscapeString($staffaccount);
            $sql = " SELECT s.staffID,s.designationID,s.sectionID  FROM staffaccounts s  WHERE s.staffAccount = '$staffaccount' and isResigned =0";
            $result =  $this->executeQueryForObject($sql);
            return $result;
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return true;
    }
    public function CheckForEscalationMenu($staffID)
    {
        $staffID = $this->realEscapeString($staffID);
        try{
            
            $sql = "SELECT count(id) as hasExists FROM leaveEscalation WHERE staffID = $staffID";
            $res = $this->executeQueryForObject($sql)->hasExists > 0 ? true : false;
            return $res;
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function getHodPrivilegesDepartmentsByStaff($staffID)
    {
        $staffID = $this->realEscapeString($staffID);
        $departments = [];
        try{   
            $sql = "SELECT batchIDs from hodPrivileges WHERE staffID = $staffID";
            $results = $this->executeQueryForList($sql);
            $batchIds = [];
            foreach($results as $res){
                if($res->batchIDs){
                    $batchIds = array_merge($batchIds,explode(',',$res->batchIDs));
                }
                
            }
            if(!empty($batchIds)){
                $batchIds = implode(',',$batchIds);
                $departments = DepartmentService::getInstance()->getDepartmentByMultiBatchId($batchIds);
            }
            return $departments;
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function getBatchesByStaffId($staffID)
    {
        try{
            $staffID = $this->realEscapeString($staffID);
            $sql = "SELECT
                        DISTINCT b.batchID as id,b.batchName as name ,b.batchDesc 
                    from
                        batches b 
                        inner join sbs_relation sr on sr.batchID = b.batchID and sr.semID = b.semID
                        and sr.staffID in ($staffID
                        and b.isPassOut !=1 
                        ORDER BY b.batchID DESC";
            return $this->executeQueryForList($sql);
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * get staff profile pic by staffId
     * @return Object
     * @throws ProfessionalException
     */
    public function getStaffProfilePic($staffId){
        $sql = " SELECT lr.storage_object as storageObj,lr.path,backend_type,lr.id as resourceId
                FROM staffaccounts sa inner join lin_resource lr on lr.id = sa.lin_resource_id
                WHERE sa.staffID = $staffId";
        try {
            $imageDetails = $this->executeQueryForObject($sql);
            if (empty($imageDetails->storageObj)) {
                return false;
            }
            $fileObj = json_decode(preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $imageDetails->storageObj));
            $imageDetails->docpath=S3Utils::getPreSignedURL($fileObj->bucket, $fileObj->key);
            
            return $imageDetails;
        }
        catch(\Exception $e) {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    /**
     * Remove staff profile pic by staffId
     * @return Object
     * @throws ProfessionalException
     */
    public function removeStaffProfilePic($staffId){
        // $sql = " SELECT sa.lin_resource_id as resourceId
        //         FROM staffaccounts sa 
        //         WHERE sa.staffID = $staffId";
        try {
            // $imageDetails = $this->executeQueryForObject($sql);
            if (!empty($staffId)) {
                // $removeRequest = new RemoveResourceRequest();
                // $removeRequest->resourceId = $imageDetails->resourceId;
                // $removeRequest->accessKey = getenv('AWS_ACCESS_KEY');
                // $removeRequest->secretKey = getenv('AWS_CLIENT_SECRET_KEY');
                // $response = ResourceService::getInstance()->removeResource($removeRequest);
                $sql = "UPDATE staffaccounts set lin_resource_id = NULL where staffID = '$staffId'";
                $imageDetails = $this->executeQuery($sql);
                
            }
            
            return true;
        }
        catch(\Exception $e) {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    // manually added (choose incoming while conflicts occurs)
     /**
     * get punching details
     *
     * getting punching data of a date
     *
     * @param Object $request Object Consists of all parameters
     * @return Array
     * @throws ProfessionalException
     * @author Ajay-the-dev 
     **/
    public function getstaffAttendance($request)
    {
        try{
            $request = $this->realEscapeObject($request);
            $whereCondition = "";
            if (count($request->departmentIds) > 0) {
                $whereCondition .= " AND s.deptID in (".implode(",",$request->departmentIds).")";
            }
            if (count($request->staffIds) > 0) {
                $whereCondition .= " AND s.staffID in (".implode(",",$request->staffIds).")";
            }
            if ($request->date) {
                $whereCondition .= " AND sa.punchDate = '$request->date";
            }
            $sql = "SELECT s.staffID ,
                            s.staffAccount ,
                            s.staffName ,
                            sa.punchDate,
                            sa.actualpunchIn ,
                            sa.punchIn ,
                            sa.actualpunchOut ,
                            sa.punchOut,
                            s.deptID 
                            from staff_attendance sa 
                            inner join staffaccounts s on s.staffAccount = sa.staffAccount 
                            WHERE 1=1 $whereCondition";
            return $this->executeQueryForList($sql);
        }catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    // manually added (choose incoming while conflicts occurs)
    /**
     * update staff attendance by admin
     *
     * update staff attendance by admin
     *
     * @param Object $request 
     * @return Array
     * @throws ProfessionalException
     **/
    public function updatestaffAttendanceByAdmin($request)
    {
        try{
            $request = $this->realEscapeObject($request);
            $author = $_SESSION['adminID'];
            $sql = "UPDATE staff_attendance 
                        SET punchIn = '$request->punchIn',
                             punchOut= '$request->punchOut',
                             updated_by = $author ,
                             updated_date = NOW() ,
                             actualpunchIn = '$request->actualPunchIn',
                             actualpunchOut = '$request->actualPunchOut'
                        WHERE punchDate = '$request->punchDate
                            AND 
                            staffAccount = '$request->staffAccount'";
            $this->executeQuery($sql);
            return true;
        }
        catch (\Exception $e) {
            return false;
        }
    }
    // copied from v3
     /**
     * get all hr designations
     *
     * getting all designations for hr escalaion designation assigning
     *
     * @param Null 
     * @return Array
     * @throws ProfessionalException
     **/
    public function getAllDesignations()
    {
        # code...
        try{
            $sql = "SELECT designationID ,designationName ,designationDesc  from hr_designations  order by designationName";
            return $this->executeQueryForList($sql);
        }catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
    }
    public function getDesignationByDesignationID($designationIDs)
    {
        try{
            $result = [];
            $designationIDs = $this->realEscapeArray($designationIDs);
            
            $designationID = implode(",",$designationIDs);
            $allDesignations = $this->getAllDesignations();
            $sql = "SELECT designationID   from hr_designations hd WHERE designationID IN ($designationID";
            if($designationID)
            {
                $designations =  $this->executeQueryForList($sql);
            }
            else{
                $designations = [];
            }
            $hrDesignations = [];
            foreach ($designations as $designation) {
                $hrDesignations[] = $designation->designationID;
            }
            foreach ($allDesignations as $verifier) {
                if(in_array($verifier->designationID, $hrDesignations))
                {
                    $verifier->checked = true;
                }
                else{
                    $verifier->checked = false;
                }
                $result[] = $verifier;
            }
        }catch (\Exception $e) {
            throw new ProfessionalException ($e->getCode(), $e->getMessage());
        }
        return $result;
    }
    
}