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 / 32
CRAP
0.00% covered (danger)
0.00%
0 / 1746
InternalMarkService
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 32
95790.00
0.00% covered (danger)
0.00%
0 / 1746
 __construct
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 3
 getInternalMarkStudentSubjectList
0.00% covered (danger)
0.00%
0 / 1
702.00
0.00% covered (danger)
0.00%
0 / 109
 getAssignedSubjectStudentsDetailsForInternalMarkEntry
0.00% covered (danger)
0.00%
0 / 1
506.00
0.00% covered (danger)
0.00%
0 / 120
 getInternalSessionalDatesForBatch
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 34
 getAssignedBatchesDetailsWithInternalSessionalDates
0.00% covered (danger)
0.00%
0 / 1
72.00
0.00% covered (danger)
0.00%
0 / 51
 saveInternalSessionalDateSettings
0.00% covered (danger)
0.00%
0 / 1
132.00
0.00% covered (danger)
0.00%
0 / 69
 getCurrentInternalSessionalDateSettings
0.00% covered (danger)
0.00%
0 / 1
110.00
0.00% covered (danger)
0.00%
0 / 34
 insertInternalSessioanlDateSettings
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 updateInternalSessioanlDateSettings
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 21
 searchInternalSessioanlDateSettings
0.00% covered (danger)
0.00%
0 / 1
110.00
0.00% covered (danger)
0.00%
0 / 54
 saveSingleInternalMarkEntry
0.00% covered (danger)
0.00%
0 / 1
132.00
0.00% covered (danger)
0.00%
0 / 70
 insertStudentInternalMarks
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 19
 saveInternalMarksForSingleSubject
0.00% covered (danger)
0.00%
0 / 1
342.00
0.00% covered (danger)
0.00%
0 / 93
 insertStudentMarksEditLog
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 13
 getInternalSessionalDates
0.00% covered (danger)
0.00%
0 / 1
210.00
0.00% covered (danger)
0.00%
0 / 73
 changeInternalMarkSubjectSubmittedStatus
0.00% covered (danger)
0.00%
0 / 1
90.00
0.00% covered (danger)
0.00%
0 / 37
 insertInternalSubjectSubmittedTable
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 deleteInternalSubjectSubmittedTable
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 18
 getMarkLogReport
0.00% covered (danger)
0.00%
0 / 1
90.00
0.00% covered (danger)
0.00%
0 / 70
 getInternalMarkLogReport
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 72
 saveImportedInternalMarks
0.00% covered (danger)
0.00%
0 / 1
506.00
0.00% covered (danger)
0.00%
0 / 98
 getPaperSubjectDetailsForInternalMarks
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 23
 getAssignedSubjectStudentsDetailsForRemoveConfirmState
0.00% covered (danger)
0.00%
0 / 1
72.00
0.00% covered (danger)
0.00%
0 / 89
 getInternalMarkConfirmedStudentList
0.00% covered (danger)
0.00%
0 / 1
72.00
0.00% covered (danger)
0.00%
0 / 42
 saveInternalMarkConfirmState
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 33
 getPrintDataForInternalMarkConsolidated
0.00% covered (danger)
0.00%
0 / 1
240.00
0.00% covered (danger)
0.00%
0 / 84
 getStudentSupplySubjectList
0.00% covered (danger)
0.00%
0 / 1
132.00
0.00% covered (danger)
0.00%
0 / 49
 getStudentSupplyAssignedSubjectList
0.00% covered (danger)
0.00%
0 / 1
90.00
0.00% covered (danger)
0.00%
0 / 80
 saveStudentSupplyInternalMarks
0.00% covered (danger)
0.00%
0 / 1
132.00
0.00% covered (danger)
0.00%
0 / 39
 saveUploadedInternalMark
0.00% covered (danger)
0.00%
0 / 1
210.00
0.00% covered (danger)
0.00%
0 / 85
 getCaMarkImprovementStudentApplications
0.00% covered (danger)
0.00%
0 / 1
552.00
0.00% covered (danger)
0.00%
0 / 102
 getCaMarkImprovementStudentReport
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 40
<?php
namespace com\linways\ec\core\service;
use com\linways\base\util\TwigRenderer;
use com\linways\ec\core\logging\Events;
use com\linways\base\util\SecurityUtils;
use com\linways\base\util\MakeSingletonTrait;
use com\linways\ec\core\logging\entities\Staff;
use com\linways\ec\core\constant\StatusConstants;
use com\linways\ec\core\service\CommonExamService;
use com\linways\core\ams\professional\util\PdfUtil;
use com\linways\core\ams\professional\logging\AMSLogger;
use com\linways\ec\core\mapper\InternalMarkServiceMapper;
use com\linways\ec\core\exception\ExamControllerException;
use com\linways\core\ams\professional\service\StaffService;
use com\linways\core\ams\professional\dto\SettingsConstents;
use com\linways\core\ams\professional\service\CommonService;
use com\linways\ec\core\service\StudentsOverAllMarkReportService;
use com\linways\core\ams\professional\request\api\GetAllFacultiesRequest;
use com\linways\am\core\service\InternalAssessmentReport\AssessmentReportInternalMarkService;
use com\linways\am\core\request\InternalAssessmentReport\SearchAssessmentReportInternalMarkRequest;
use com\linways\oe\core\service\ExamUserMarkService;
use com\linways\ec\core\request\SearchRuleRequest;
use com\linways\ec\core\service\RuleService;
class InternalMarkService extends BaseService
{
    use MakeSingletonTrait;
    private function __construct() {
        $this->mapper = InternalMarkServiceMapper::getInstance()->getMapper();
        $this->logger = AMSLogger::getLogger('exam-controller-log');
    }
     /**
     * get Internal Mark Subject List
     * @param $searchRequest 
     * @return $response 
     */
    public function getInternalMarkStudentSubjectList($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $response = new \stdClass;
            $request = new \stdClass;
            $request->courseTypeId = $searchRequest->courseTypeId;
            $request->departmentId = $searchRequest->departmentId;
            $request->groupId = $searchRequest->groupId;
            $request->academicTermId = $searchRequest->academicTermId;
            $request->isConsolidatedView = $searchRequest->isConsolidatedView;
            $error = false;
            $errorMsg = null;  
            // $checkValuationDateForInternalMarkEntry = CommonService::getInstance()->getSettings(SettingsConstents::INTERNAL_MARK_SETTINGS, SettingsConstents::CHECK_VALUATION_DATE_FOR_INTERNAL_MARK_ENTRY);
            // if($checkValuationDateForInternalMarkEntry){
            //     $staffDetails = $this->getStaffAssignedForInternalMarkEntry($request);
            //     $date = date('Y-m-d');
            //     $details = $staffDetails[0];
            //     if($details->startDate > $date){
            //         $errorMsg = 'Mark entry starts on ' . date('d-m-Y', strtotime($details->startDate));
            //         $error = true;
            //     }
            //     elseif($details->endDate < $date){
            //         $errorMsg = 'Mark entry date exceeded';  
            //         $error = true;
            //     }
            // }
            if(!$error){
                if($request->isConsolidatedView == "true" ){
                    $batchDetails = new \stdClass;
                    $request->mapping = "STUDENT-WISE";
                    $assignedSubjects = CommonExamService::getInstance()->getAssignedSubjectsInBatch($request);
                    $batchSubjects = [];
                    foreach($assignedSubjects as $key => $subject){
                        if($subject->internalMaxMark && $subject->isInternal) {
                            $batchSubjects[] = $subject;
                        }
                    }
                    $studentList =  $this->getAssignedSubjectStudentsDetailsForInternalMarkEntry($request);
                    if(empty($studentList)){
                        throw new ExamControllerException(ExamControllerException::NO_DETAILS_FOUND,"No Students Found In This Batch");
                    }
                    else{
                        $batchDetails->groupId = reset($studentList)->groupId;
                        $batchDetails->groupName = reset($studentList)->groupName;
                        $batchDetails->academicTermId = reset($studentList)->academicTermId;
                        $batchDetails->academicTermName = reset($studentList)->academicTermName;
                        foreach($studentList as $student){
                            foreach($student->subjects as $subject){
                                $subject->internalMark = $subject->internalMark ? number_format((float)$subject->internalMark, 2, '.', '') : null;
                                if($subject->attendanceStatus == "ABSENT"){
                                    $subject->internalMark = "AB";
                                }
                                if($subject->attendanceStatus == "INCOMPLETE"){
                                    $subject->internalMark = "I";
                                }
                            }
                            foreach($assignedSubjects as $subject){
                                foreach($student->subjects as $studentSubject){
                                    $studentSubject->isAssigned = false;
                                    if($studentSubject->academicPaperSubjectId ==  $subject->academicPaperSubjectId){
                                        $studentSubject->isAssigned = true;
                                    }
                                }
                            }
                        }
                        $response->batchAssignedStudents = $studentList;
                        $response->batchSubjects = $batchSubjects;
                        $response->batchDetails = $batchDetails;
                    }
                }
                else{
                    $request->mapping = "SUBJECT-WISE";
                    $subjectList =  $this->getAssignedSubjectStudentsDetailsForInternalMarkEntry($request);
                    foreach($subjectList as $subject){
                        if(!$subject->isInternal){
                            $subject->errorMsg ="External Only Subject";
                            $subject->isError = true;
                        }
                        elseif(!$subject->internalMaxMark && $subject->isInternal){
                            $subject->errorMsg ="Internal max mark not configured";
                            $subject->isError = true;
                        }
                        $subject->markEnteredStudentCount = 0;
                        if($subject->isInternalSubmitted){
                            $subject->isSubmitted=1;
                        }
                        else{
                            $subject->isSubmitted=0;
                        }
                        array_walk($subject->students,function($student,$key) use($subject){
                            // $student->internalMark = $student->internalMark ? (float)$student->internalMark : null;
                            $student->internalMark = $student->internalMark ? number_format((float)$student->internalMark, 2, '.', '') : null;
                            if($student->attendanceStatus == "ABSENT"){
                                $student->internalMark = "AB";
                            }
                            if($student->attendanceStatus == "INCOMPLETE"){
                                $student->internalMark = "I";
                            }
                            $student->oldInternalMarks = $student->internalMark;
                            if($student->internalMarkLog){
                                $log = $student->internalMarkLog;
                                usort($log, function ($a, $b) {
                                    return strtotime($a->actionTakenTime) < strtotime($b->actionTakenTime);
                                });
                                $student->remarks = current($log)->remarks;
                                $student->oldRemarks = current($log)->remarks;
                            }
                            if($student->isInternalEntered){
                                $subject->markEnteredStudentCount ++;
                            }
                            $student->oldRemark = $student->remarks;
                        });
                        $subject->totalStudentCount = count($subject->students);
                    }
                    $response->subjectList = $subjectList;
                }
            }
            else{
                $response->subjectList = [];
                $response->errorMsg = $errorMsg;
            }
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $response;
    }
    /**
     * get Assigned Subject Students Details For Internal Mark Entry
     * @param $searchRequest 
     * @return $subjectWiseInternalMarkDetails 
     * @author Krishnajith
     */
    public function getAssignedSubjectStudentsDetailsForInternalMarkEntry($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        $searchRequest->academicPaperSubjectIds = stripslashes($searchRequest->academicPaperSubjectIds);
        try{
            $orderBy = " ORDER BY sub.name ASC , spa.properties->>'$.registerNumber' ASC";
            if($searchRequest->getOrderByRegisterNo){
                $orderBy = " ORDER BY spa.properties->>'$.registerNumber' ASC";
            }
            $whereQuery = "";
            if(!empty($searchRequest->groupId)) {
                $groupIdString = is_array($searchRequest->groupId) ? "'" . implode("','",$searchRequest->groupId) . "'" : "'".$searchRequest->groupId."'";
                $whereQuery .= " AND g.id IN ( $groupIdString )";
            }
            if(!empty($searchRequest->programId)) {
                $programIdString = is_array($searchRequest->programId) ? "'" . implode("','",$searchRequest->programId) . "'" : "'".$searchRequest->programId."'";
                $whereQuery .= " AND p.id IN ( $programIdString )";
            }
            if(!empty($searchRequest->academicTermId)) {
                $academicTermIdString = is_array($searchRequest->academicTermId) ? "'" . implode("','",$searchRequest->academicTermId) . "'" : "'".$searchRequest->academicTermId."'";
                $whereQuery .= " AND act.id IN ( $academicTermIdString )";
            }
            if(!empty($searchRequest->studentRegisterNo)) {
                $studentRegisterNoString = is_array($searchRequest->studentRegisterNo) ? "'" . implode("','",$searchRequest->studentRegisterNo) . "'" : "'".$searchRequest->studentRegisterNo."'";
                $whereQuery .= " AND spa.properties->>'$.registerNumber' IN ( $studentRegisterNoString )";
            }
            if(!empty($searchRequest->studentRollNo)) {
                $studentRollNoString = is_array($searchRequest->studentRollNo) ? "'" . implode("','",$searchRequest->studentRollNo) . "'" : "'".$searchRequest->studentRollNo."'";
                $whereQuery .= " AND spa.properties->>'$.rollNumber' IN ( $studentRollNoString )";
            }
            if(!empty($searchRequest->studentId)) {
                $studentIdString = is_array($searchRequest->studentId) ? "'" . implode("','",$searchRequest->studentId) . "'" : "'".$searchRequest->studentId."'";
                $whereQuery .= " AND s.studentID IN ( $studentIdString )";
            }
            if(!empty($searchRequest->academicPaperSubjectIds)) {
                $academicPaperSubjectIdsString = is_array($searchRequest->academicPaperSubjectIds) ? "'" . implode("','",$searchRequest->academicPaperSubjectIds) . "'" : $searchRequest->academicPaperSubjectIds;
                $whereQuery .= " AND aps.id IN ( $academicPaperSubjectIdsString )";
            }
            if(!empty($searchRequest->classType)) {
                $classTypeString = is_array($searchRequest->classType) ? "'" . implode("','",$searchRequest->classType) . "'" : "'".$searchRequest->classType."'";
                $whereQuery .= " AND aps.properties->>'$.classType' IN ( $classTypeString )";
            }
            switch ($searchRequest->mapping) {
                case 'SUBJECT-WISE':
                    $mapperConst = InternalMarkServiceMapper::INTERNAL_MARK_SUBJECT_STUDENT_DETAILS;
                    break;
                case 'STUDENT-WISE':
                    $mapperConst = InternalMarkServiceMapper::INTERNAL_MARK_STUDENT_SUBJECT_DETAILS;
                    break;
                case 'STUDENT-SUJECT-CONSOLIDATED-WISE':
                    $mapperConst = InternalMarkServiceMapper::INTERNAL_MARK_STUDENT_SUBJECT_CONSOLIDATED_DETAILS;
                    break;
                default:
                    $mapperConst = InternalMarkServiceMapper::INTERNAL_MARK_SUBJECT_STUDENT_DETAILS;
                    break;
            }
            $query = "SELECT DISTINCT
                            g.id AS groupId,
                            g.name AS groupName,
                            g.properties ->>'$.programId'  AS programId,
                            aps.id AS academicPaperSubjectId,
                            sub.id AS subjectId,
                            sub.name AS subjectCode,
                            sub.code AS subjectName,
                            act.name as academicTermName,
                            act.id as academicTermId,
                            p.name as programName,
                            aps.properties ->> '$.isInternal' as isInternal,
                            aps.properties ->> '$.isExternal' as isExternal,
                            aps.properties ->> '$.internalMaxMark' as internalMaxMark,
                            IF(ims.id,1,0) AS isInternalSubmitted,
                            spa.student_id AS studentId,
                            spa.properties->>'$.rollNumber' AS studentRollNo,
                            spa.properties->>'$.registerNumber' AS studentRegisterNo,
                            std.studentName AS studentName,
                            IF(im.id,1,0) AS isInternalEntered,
                            im.internal_mark AS internalMark,
                            im.attendance_status AS attendanceStatus,
                            imlog.log AS internalMarkLog
                        FROM 
                            studentaccount s 
                        INNER JOIN student_program_account spa
                            ON spa.student_id = s.studentID
                        INNER JOIN student_program_batch_log spbl 
                            ON spbl.program_student_id = spa.id AND spbl.properties->>'$.academicStatus' IN ('ACTIVE','COMPLETED')
                        INNER JOIN `program` p 
                            ON p.id = spbl.program_id
                        INNER JOIN `groups` g 
                            ON g.id = spbl.batch_group_id
                        INNER JOIN groups_relations gr ON 
                            gr.parent_groups_id = g.id
                        INNER JOIN `groups` sg ON 
                            sg.id = gr.child_groups_id AND sg.type = 'SUBJECT'
                        INNER JOIN group_members sgm ON
                            sgm.groups_id = sg.id AND 
                            sgm.members->>'$.studentId' = spa.id AND sgm.academic_status IN ('ACTIVE')
                        INNER JOIN cm_academic_paper_subjects aps ON 
                            aps.id = sg.paperSubjectId
                        INNER JOIN cm_academic_paper ap ON 
                            aps.cm_academic_paper_id = ap.id
                        INNER JOIN cm_syllabus_academic_term_settings csats ON 
                            csats.id = ap.cm_syllabus_academic_term_settings_id 
                        INNER JOIN academic_term act ON
                            act.id = sg.academic_term_id AND act.id = spbl.term_id
                        INNER JOIN v4_ams_subject sub ON 
                            sub.id = aps.ams_subject_id
                        INNER JOIN studentaccount std ON 
                            std.studentID = spa.student_id
                        LEFT JOIN ec_internal_marks_submitted ims ON 
                            ims.groups_id = g.id AND ims.academic_paper_subjects_id = aps.id AND ims.academic_term_id = act.id
                        LEFT JOIN ec_internal_marks im ON 
                            im.groups_id  = g.id AND im.academic_paper_subjects_id = aps.id AND im.academic_term_id = act.id AND im.student_id = spa.student_id
                        LEFT JOIN im_student_mark_edit_log imlog ON 
                            imlog.groups_id = g.id AND imlog.academic_paper_subjects_id = aps.id AND imlog.academic_term_id = act.id AND imlog.student_id = std.studentID 
                        WHERE 1=1 AND sg.academic_term_id = csats.academic_term_id";
            $subjectWiseInternalMarkDetails = $this->executeQueryForList($query.$whereQuery.$orderBy, $this->mapper[$mapperConst]);
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $subjectWiseInternalMarkDetails;
    }
    /**
     * get Internal Mark Subject List
     * @param $searchRequest 
     * @return $response 
     */
    public function getInternalSessionalDatesForBatch($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try
        {
            $response = new \stdClass;
            $request = new \stdClass;
            $request->courseTypeId = $searchRequest->courseTypeId;
            $request->startYear = $searchRequest->admissionYear;
            $request->academicTermId = $searchRequest->academicTermId;
            $request->isInternalOrSessional = $searchRequest->isInternalOrSessional;
            $request->sessionalExamTypeId = $searchRequest->sessionalExamTypeId;
            $batchesList =  $this->getAssignedBatchesDetailsWithInternalSessionalDates($request);
            foreach($batchesList as $batch){
                if(($batch->isInternalOrSessional == $request->isInternalOrSessional) && ($batch->sessionalExamTypeId == $request->sessionalExamTypeId)){
                    if($batch->fromDate){
                        $batch->fromDate = date("d-m-Y",strtotime($batch->fromDate));
                    }
                    if($batch->toDate){
                        $batch->toDate = date("d-m-Y",strtotime($batch->toDate));
                    }
                }
                else{
                    $batch->toDate = null;
                    $batch->fromDate = null;
                }
                $batch->isSelected = false;
               
            }
            $response->batchesList = $batchesList;
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $response;
    }
     /**
     * getAssignedBatchesDetailsWithInternalSessionalDates
     * @param $searchRequest 
     * @return $batchWiseInternalDates 
     * @author Krishnajith
     */
    public function getAssignedBatchesDetailsWithInternalSessionalDates($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try
        {
            $orderBy = " ORDER BY g.name ASC";
            $whereQuery = "";
            if(!empty($searchRequest->courseTypeId)) {
                $courseTypeIdString = is_array($searchRequest->courseTypeId) ? "'" . implode("','",$searchRequest->courseTypeId) . "'" : "'".$searchRequest->courseTypeId."'";
                $whereQuery .= " AND g.properties ->> '$.courseTypeId' IN ( $courseTypeIdString )";
            }
            if(!empty($searchRequest->startYear)) {
                $startYearStrng = is_array($searchRequest->startYear) ? "'" . implode("','",$searchRequest->startYear) . "'" : "'".$searchRequest->startYear."'";
                $whereQuery .= " AND g.properties ->> '$.startYear' IN ( $startYearStrng )";
            }
            // if(!empty($searchRequest->isInternalOrSessional)) {
            //     $whereQuery .= " AND esims.type = '$searchRequest->isInternalOrSessional'";
            // }
            // if(!empty($searchRequest->sessionalExamTypeId)) {
            //     $whereQuery .= " AND esims.sessional_exam_type_id = $searchRequest->sessionalExamTypeId";
            // }
            if(!empty($searchRequest->academicTermId)) {
                $academicTermIdString = is_array($searchRequest->academicTermId) ? "'" . implode("','",$searchRequest->academicTermId) . "'" : "'".$searchRequest->academicTermId."'";
                $whereQuery .= " AND str.academic_term_id IN ( $academicTermIdString )";
            }
            $query = "SELECT DISTINCT
                            g.id AS groupId,
                            g.name AS groupName,
                            esims.type AS isInternalOrSessional,
                            esims.sessional_exam_type_id AS sessionalExamTypeId,
                            esims.from_date AS fromDate,
                            esims.to_date AS toDate
                        FROM cluster c 
                        INNER JOIN cluster_members cm ON 
                            cm.cluster_id = c.id
                        INNER JOIN cluster_groups_relations cg ON 
                            cg.cluster_id = c.id
                        INNER JOIN `groups` sg ON 
                            sg.id = cg.groups_id AND sg.type = 'SUBJECT'
                        INNER JOIN groups_relations gr ON 
                            gr.child_groups_id = cg.groups_id
                        INNER JOIN `groups` g ON 
                            gr.parent_groups_id = g.id AND g.type = 'BATCH'
                        INNER JOIN cm_academic_paper_subjects aps ON 
                            aps.id = sg.paperSubjectId
                        INNER JOIN cm_academic_paper ap ON 
                            aps.cm_academic_paper_id = ap.id
                        INNER JOIN cm_syllabus_academic_term_settings str ON 
                            str.id = ap.cm_syllabus_academic_term_settings_id 
                        LEFT JOIN ec_sessional_internal_marks_settings esims ON 
                            esims.groups_id = g.id AND esims.academic_paper_subjects_id = aps.id AND esims.academic_term_id = str.academic_term_id
                        WHERE 1=1 ";
            $batchWiseInternalDates = $this->executeQueryForList($query.$whereQuery.$orderBy);
            
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $batchWiseInternalDates;
    }
     /**
     * save Internal Sessional Date Settings
     * @param $searchRequest 
     * @return $response 
     */
    public function saveInternalSessionalDateSettings($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $insertionDateSettingTableArray=[];
            $updationDateSettingTableArray=[];
            $currentStaffId = $GLOBALS['userId'];
            $response = new \stdClass;
            $request = new \stdClass;
            $selectedBatches = (array)$searchRequest->selectedBatches;
            $request->courseTypeId = $searchRequest->courseTypeId;
            $request->startYear = $searchRequest->admissionYear;
            $request->academicTermId = $searchRequest->academicTermId;
            $request->isInternalOrSessional = $searchRequest->isInternalOrSessional;
            $request->sesionalExamTypeId = $searchRequest->sesionalExamTypeId;
            if(empty($selectedBatches) || empty($request->academicTermId)){
                throw new ExamControllerException(ExamControllerException::EMPTY_PARAMETERS,"Invailed Request For Save Date Settings");
            }
            foreach($selectedBatches as $batch){
                $subjects = [];
                $requestForGetSubjects = new \stdClass;
                $requestForGetSubjects->courseTypeId = $request->courseTypeId;
                $requestForGetSubjects->startYear = $request->admissionYear;
                $requestForGetSubjects->academicTermId = $request->academicTermId;
                $batch['fromDate'] = date("Y-m-d",strtotime($batch['fromDate']));
                $batch['toDate'] = date("Y-m-d",strtotime($batch['toDate']));
                $requestForGetSubjects->groupId = $batch['groupId'];
                $subjects = CommonExamService::getInstance()->getAssignedSubjectsInBatch($requestForGetSubjects);
                
                foreach($subjects as $subject){
                    if($request->isInternalOrSessional == "INTERNAL"){
                        $requestForDateSettings = new \stdClass;
                        $requestForDateSettings->type = "INTERNAL";
                        $requestForDateSettings->groupId = $subject->groupId;
                        $requestForDateSettings->academicTermId = $subject->academicTermId;
                        $requestForDateSettings->academicPaperSubjectId = $subject->academicPaperSubjectId;
                        $dateSettings = $this->getCurrentInternalSessionalDateSettings($requestForDateSettings);
                        if(empty($dateSettings)){
                            $insertionDateSettingTableArray[] = " ('INTERNAL', null, '".$subject->groupId."','".$subject->academicTermId."','".$subject->academicPaperSubjectId."','".$batch['fromDate']."','".$batch['toDate']."',null,'".$currentStaffId."', utc_timestamp(), '".$currentStaffId."', utc_timestamp() ) ";
                        }
                        else{
                            $updationDateSettingTableEntry = new \stdClass;
                            $updationDateSettingTableEntry->id = $dateSettings->id;
                            $updationDateSettingTableEntry->academicPaperSubjectId = $dateSettings->academicPaperSubjectId;
                            $updationDateSettingTableEntry->academicTermId = $dateSettings->academicTermId;
                            $updationDateSettingTableEntry->groupId = $dateSettings->groupId;
                            $updationDateSettingTableEntry->type = "INTERNAL";
                            $updationDateSettingTableEntry->fromDate = $batch['fromDate'];
                            $updationDateSettingTableEntry->toDate = $batch['toDate'];
                            $updationDateSettingTableEntry->sessionalExamTypeId = null;
                            $updationDateSettingTableEntry->updatedBy = $currentStaffId ;
                            $updationDateSettingTableArray[] = $updationDateSettingTableEntry;
                        }
                        
                    }
                    elseif($request->isInternalOrSessional == "SESSIONAL"){
                        $insertionDateSettingTableArray[] = " ('SESSIONAL','".$request->sesionalExamTypeId."', '".$subject->groupId."','".$subject->academicTermId."','".$subject->academicPaperSubjectId."','".$batch['fromDate']."','".$batch['toDate']."',null,'".$currentStaffId."', utc_timestamp(), '".$currentStaffId."', utc_timestamp() ) ";
                    }
                }
            }
            if(! empty($insertionDateSettingTableArray)){
                $this->insertInternalSessioanlDateSettings($insertionDateSettingTableArray);
            }
            if(! empty($updationDateSettingTableArray)){
                $this->updateInternalSessioanlDateSettings($updationDateSettingTableArray);
            }
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $response;
    }
     /**
     * get Current Internal Sessional Date Settings
     * @param $searchRequest 
     * @return $internalSessionalDateSetting 
     * @author Krishnajith
     */
    public function getCurrentInternalSessionalDateSettings($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $whereQuery = "";
            if(!empty($searchRequest->academicPaperSubjectId)) {
                $academicPaperSubjectIdString = is_array($searchRequest->academicPaperSubjectId) ? "'" . implode("','",$searchRequest->academicPaperSubjectId) . "'" : "'".$searchRequest->academicPaperSubjectId."'";
                $whereQuery .= " AND esims.academic_paper_subjects_id IN ( $academicPaperSubjectIdString )";
            }
            if(!empty($searchRequest->groupId)) {
                $groupIdString = is_array($searchRequest->groupId) ? "'" . implode("','",$searchRequest->groupId) . "'" : "'".$searchRequest->groupId."'";
                $whereQuery .= " AND esims.groups_id IN ( $groupIdString )";
            }
            if(!empty($searchRequest->academicTermId)) {
                $academicTermIdString = is_array($searchRequest->academicTermId) ? "'" . implode("','",$searchRequest->academicTermId) . "'" : "'".$searchRequest->academicTermId."'";
                $whereQuery .= " AND esims.academic_term_id IN ( $academicTermIdString )";
            }
            if(!empty($searchRequest->type)) {
                $typeString = is_array($searchRequest->type) ? "'" . implode("','",$searchRequest->type) . "'" : "'".$searchRequest->type."'";
                $whereQuery .= " AND esims.type IN ( $typeString )";
            }
            $query = "SELECT DISTINCT
                            esims.id AS id,
                            esims.academic_paper_subjects_id AS academicPaperSubjectId,
                            esims.academic_term_id as academicTermId,
                            esims.groups_id AS groupId,
                            esims.type AS type
                        FROM ec_sessional_internal_marks_settings esims
                        WHERE 1=1 ";
            $internalSessionalDateSetting = $this->executeQueryForObject($query.$whereQuery);
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $internalSessionalDateSetting;
    }
    /**
     * insert Internal Sessioanl Date Settings
     * @param  $insertionValues
     */
    public function insertInternalSessioanlDateSettings($insertionValues){
        try {
            $insert_query = "INSERT INTO ec_sessional_internal_marks_settings
                                (type,sessional_exam_type_id,groups_id,academic_term_id,academic_paper_subjects_id,from_date,to_date,properties,created_by,created_date,updated_by,updated_date)
                                VALUES " . implode ( ",", $insertionValues ) . " ON DUPLICATE KEY UPDATE from_date = VALUES(from_date) , to_date = VALUES(to_date) " ;
            $this->executeQuery($insert_query);
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
     /**
     * updateInternalSessioanlDateSettings
     * @param  $updationDateSettingTableArray
     */
    public function updateInternalSessioanlDateSettings($updationDateSettingTableArray)
    {
        $updationDateSettingTableArray = $this->realEscapeArray($updationDateSettingTableArray);
        try {
            foreach($updationDateSettingTableArray as $updatedValue){
                $update_query = "UPDATE
                            ec_sessional_internal_marks_settings
                        SET
                            from_date = '$updatedValue->fromDate',
                            to_date = '$updatedValue->toDate',
                            updated_by = '$updatedValue->updatedBy',                               
                            updated_date = 'utc_timestamp()'
                        WHERE
                            id = '$updatedValue->id'";
                $this->executeQuery($update_query);
            }
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
     /**
     * insert Internal Sessioanl Date Settings
     * @param  $insertionValues
     */
    public function searchInternalSessioanlDateSettings($searchRequest){
        try {
            $orderBy = " ORDER BY sub.code ASC";
            $whereQuery = "";
            if(!empty($searchRequest->courseTypeId)) {
                $courseTypeIdString = is_array($searchRequest->courseTypeId) ? "'" . implode("','",$searchRequest->courseTypeId) . "'" : "'".$searchRequest->courseTypeId."'";
                $whereQuery .= " AND g.properties ->> '$.courseTypeId' IN ( $courseTypeIdString )";
            }
            if(!empty($searchRequest->groupId)) {
                $groupIdString = is_array($searchRequest->groupId) ? "'" . implode("','",$searchRequest->groupId) . "'" : "'".$searchRequest->groupId."'";
                $whereQuery .= " AND g.id IN ( $groupIdString )";
            }
            if(!empty($searchRequest->startYear)) {
                $startYearStrng = is_array($searchRequest->startYear) ? "'" . implode("','",$searchRequest->startYear) . "'" : "'".$searchRequest->startYear."'";
                $whereQuery .= " AND g.properties ->> '$.startYear' IN ( $startYearStrng )";
            }
            if(!empty($searchRequest->academicTermId)) {
                $academicTermIdString = is_array($searchRequest->academicTermId) ? "'" . implode("','",$searchRequest->academicTermId) . "'" : "'".$searchRequest->academicTermId."'";
                $whereQuery .= " AND str.academic_term_id IN ( $academicTermIdString )";
            }
            $query = "SELECT DISTINCT
                            aps.id AS academicPaperSubjectId,
                            sub.id AS subjectId,
                            sub.code AS subjectCode,
                            sub.name AS subjectName,
                            str.academic_term_id as academicTermId,
                            g.id AS groupId,
                            g.name AS groupName
                        FROM cluster c 
                        INNER JOIN cluster_members cm ON 
                            cm.cluster_id = c.id
                        INNER JOIN cluster_groups_relations cg ON 
                            cg.cluster_id = c.id
                        INNER JOIN `groups` sg ON 
                            sg.id = cg.groups_id AND sg.type = 'SUBJECT'
                        INNER JOIN groups_relations gr ON 
                            gr.child_groups_id = cg.groups_id
                        INNER JOIN `groups` g ON 
                            gr.parent_groups_id = g.id AND g.type = 'BATCH'
                        INNER JOIN cm_academic_paper_subjects aps ON 
                            aps.id = sg.paperSubjectId
                        INNER JOIN cm_academic_paper ap ON 
                            aps.cm_academic_paper_id = ap.id
                        INNER JOIN cm_syllabus_academic_term_settings str ON 
                            str.id = ap.cm_syllabus_academic_term_settings_id 
                        INNER JOIN v4_ams_subject sub ON 
                            sub.id = aps.ams_subject_id
                        WHERE 1=1 ";
            $subjectDetails = $this->executeQueryForList($query.$whereQuery.$orderBy);
            
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $subjectDetails;
                
    }
     /**
     * save Single Internal Mark Entry
     * @param $searchRequest 
     * @return $response 
     */
    public function saveSingleInternalMarkEntry($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        $response = new \stdClass;
        $currentStaffId = $GLOBALS['userId'];
        $editHistoryLog = [];
        try{
            $internalMark = $searchRequest->internalMark;
            $academicPaperSubjectId = $searchRequest->academicPaperSubjectId;
            $groupId = $searchRequest->groupId;
            $academicTermId = $searchRequest->academicTermId;
            $studentId = $searchRequest->studentId;
            $programId = $searchRequest->programId;
            if(empty($academicPaperSubjectId) || empty($academicTermId) || empty($groupId) || empty($studentId)){
                throw new ExamControllerException(ExamControllerException::EMPTY_PARAMETERS,"Invailed Request For Save Internal Mark");
            }
            else{
                if($internalMark == "AB"){
                    $insertionInternalMarkTableArray[] = " ('".$studentId."','".$groupId."','".$programId."', '".$academicTermId."','".$academicPaperSubjectId."',0,'ABSENT','".$currentStaffId."', utc_timestamp(), '".$currentStaffId."', utc_timestamp() ) ";
                    $request = new \stdClass();
                    $request->groupId = $groupId;
                    $request->studentId = $studentId;
                    $request->isDirty = 1;
                    $request->staffId = $GLOBALS['userId'];
                    $editHistoryLog[] = $request;
                }
                else if($internalMark == "I"){
                    $insertionInternalMarkTableArray[] = " ('".$studentId."','".$groupId."','".$programId."', '".$academicTermId."','".$academicPaperSubjectId."',0,'INCOMPLETE','".$currentStaffId."', utc_timestamp(), '".$currentStaffId."', utc_timestamp() ) ";
                    $request = new \stdClass();
                    $request->groupId = $groupId;
                    $request->studentId = $studentId;
                    $request->isDirty = 1;
                    $request->staffId = $GLOBALS['userId'];
                    $editHistoryLog[] = $request;
                }
                elseif(is_numeric($internalMark)){
                    $insertionInternalMarkTableArray[] = " ('".$studentId."','".$groupId."','".$programId."', '".$academicTermId."','".$academicPaperSubjectId."','".$internalMark."','PRESENT','".$currentStaffId."', utc_timestamp(), '".$currentStaffId."', utc_timestamp() ) ";
                    $request = new \stdClass();
                    $request->groupId = $groupId;
                    $request->studentId = $studentId;
                    $request->isDirty = 1;
                    $request->staffId = $GLOBALS['userId'];
                    $editHistoryLog[] = $request;
                }
                else{
                    throw new ExamControllerException(ExamControllerException::INVAILED_INTERNAL_MARK,"Invailed Internal Mark");
                }
            }
            if(! empty($insertionInternalMarkTableArray)){
                $this->insertStudentInternalMarks($insertionInternalMarkTableArray);
                AMSLogger::log_info($this->logger,Events::EC_SAVE_INTERNAL_MARK,[
                "staff" => new Staff(["id" => $currentStaffId]),
                    "request" => $searchRequest,
                    "status" => StatusConstants::SUCCESS
                ]);
            }
            if(! empty($editHistoryLog)){
                StudentsOverAllMarkReportService::getInstance()->insertStudentEditStatus($editHistoryLog);
            }
        }
        catch (\Exception $e){
            AMSLogger::log_error($this->logger,Events::EC_SAVE_INTERNAL_MARK,[
            "staff" => new Staff(["id" => $currentStaffId]),
                "request" => $searchRequest,
                "errorCode" => $e->getCode(),
                "errorMessage" => $e->getMessage(),
                "status" => StatusConstants::FAILED
            ]);
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $response;
    }
    /**
     * insert Internal Sessioanl Date Settings
     * @param  $insertionValues
     */
    private function insertStudentInternalMarks($insertionValues, $isInsertFormativeSummative = false){
        try {
            if($isInsertFormativeSummative){
                $insert_query = "INSERT INTO ec_internal_marks
                (student_id,groups_id,program_id,academic_term_id,academic_paper_subjects_id,internal_mark,attendance_status,created_by,created_date,updated_by,updated_date,formative_mark,summative_mark)
                VALUES " . implode ( ",", $insertionValues ) . " ON DUPLICATE KEY UPDATE internal_mark = VALUES(internal_mark) , attendance_status = VALUES(attendance_status), formative_mark = VALUES(formative_mark), summative_mark = VALUES(summative_mark) " ;
                $this->executeQuery($insert_query);
            }
            else{
                $insert_query = "INSERT INTO ec_internal_marks
                                    (student_id,groups_id,program_id,academic_term_id,academic_paper_subjects_id,internal_mark,attendance_status,created_by,created_date,updated_by,updated_date)
                                    VALUES " . implode ( ",", $insertionValues ) . " ON DUPLICATE KEY UPDATE internal_mark = VALUES(internal_mark) , attendance_status = VALUES(attendance_status) " ;
                $this->executeQuery($insert_query);
            }
                
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
     /**
     * save Internal Marks For Single Subject
     * @param $searchRequest 
     * @return $response 
     */
    public function saveInternalMarksForSingleSubject($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        $response = new \stdClass;
        $currentStaffId = $GLOBALS['userId'];
        $insertionInternalMarkLogTableArray = [];
        $insertionInternalMarkTableArray = [];
        $editHistoryLog = [];
        $t=time(); 
        try{
            $academicPaperSubjectId = $searchRequest->academicPaperSubjectId;
            $groupId = $searchRequest->groupId;
            $academicTermId = $searchRequest->academicTermId;
            $studentsMarkDetails = $searchRequest->studentsMarkDetails;
            $programId = $searchRequest->programId;
            if(empty($academicPaperSubjectId) || empty($academicTermId) || empty($groupId) || empty($programId)){
                throw new ExamControllerException(ExamControllerException::EMPTY_PARAMETERS,"Invailed Request For Save Internal Mark");
            }
            else{
                foreach($studentsMarkDetails as $student){
                    if(($student['oldInternalMarks'] != $student['internalMark']) || ($student['remarks'] != $student['oldRemark'])){
                        if(!empty($student['internalMark']) || $student['internalMark'] == 0 ){
                            if($student['internalMark'] == "AB"){
                                $insertionInternalMarkTableArray[] = " ('".$student['studentId']."','".$groupId."','".$programId."', '".$academicTermId."','".$academicPaperSubjectId."',0,'ABSENT','".$currentStaffId."', utc_timestamp(), '".$currentStaffId."', utc_timestamp() ) ";
                            }
                            else if($student['internalMark'] == "I"){
                                $insertionInternalMarkTableArray[] = " ('".$student['studentId']."','".$groupId."','".$programId."', '".$academicTermId."','".$academicPaperSubjectId."',0,'INCOMPLETE','".$currentStaffId."', utc_timestamp(), '".$currentStaffId."', utc_timestamp() ) ";
                            }
                            elseif(is_numeric($student['internalMark'])){
                                if($student['internalMark'] > $student['internalMaxMark']){
                                    $errorMessage = "Internal Mark Exceeded To Maximum Mark For ".$student['registerNo'];
                                    throw new ExamControllerException(ExamControllerException::EXCEEDED_TO_MAXIMUM_MARK,$errorMessage );
                                }
                                else{
                                    $insertionInternalMarkTableArray[] = " ('".$student['studentId']."','".$groupId."','".$programId."', '".$academicTermId."','".$academicPaperSubjectId."','".$student['internalMark']."','PRESENT','".$currentStaffId."', utc_timestamp(), '".$currentStaffId."', utc_timestamp() ) ";
                                }
                            }
                            $log = new \stdClass;
                            $log->oldMark = $student['oldInternalMarks'];
                            $log->newMark = $student['internalMark'];
                            $log->remarks = $student['remarks'];
                            $log->markType = "INTERNAL_MARK";
                            $log->actionTakenTime = date("d-m-Y h:i:s A",$t);
                            $log->updatedStaffId = $currentStaffId;
                            $log->updatedStaffType = "EXAM_CONTROLLER";
                            $log->menuName = "INTERNAL_MARK_NEW_VIEW";
                            $log = json_encode($log);
                            $id = SecurityUtils::getRandomString();
                            $insertionInternalMarkLogEntryObj = new \stdClass();
                            $insertionInternalMarkLogEntryObj->id = $id;
                            $insertionInternalMarkLogEntryObj->studentId = $student['studentId'];
                            $insertionInternalMarkLogEntryObj->groupId = $groupId;
                            $insertionInternalMarkLogEntryObj->academicTermId = $academicTermId;
                            $insertionInternalMarkLogEntryObj->academicPaperSubjectId = $academicPaperSubjectId;
                            $insertionInternalMarkLogEntryObj->log = $log;
                            $insertionInternalMarkLogEntryObj->createdBy = $currentStaffId;
                            $insertionInternalMarkLogEntryObj->updatedBy = $currentStaffId;
                            $insertionInternalMarkLogTableArray[] = $insertionInternalMarkLogEntryObj;
                            $request = new \stdClass();
                            $request->groupId = $student['groupId'];
                            $request->studentId = $student['studentId'];
                            $request->isDirty = 1;
                            $request->staffId = $GLOBALS['userId'];
                            $editHistoryLog[] = $request;
                        }
                    }
                }
            }
            if(! empty($insertionInternalMarkTableArray)){
                $this->insertStudentInternalMarks($insertionInternalMarkTableArray);
                AMSLogger::log_info($this->logger,Events::EC_SAVE_INTERNAL_MARK,[
                    "staff" => new Staff(["id" => $currentStaffId]),
                    "request" => $searchRequest,
                    "status" => StatusConstants::SUCCESS
                ]);
            }
            if(! empty($editHistoryLog)){
                StudentsOverAllMarkReportService::getInstance()->insertStudentEditStatus($editHistoryLog);
            }
            if(! empty($insertionInternalMarkLogTableArray)){
                $this->insertStudentMarksEditLog($insertionInternalMarkLogTableArray);
            }
        }
        catch (\Exception $e){
            AMSLogger::log_error($this->logger,Events::EC_SAVE_INTERNAL_MARK,[
                "staff" => new Staff(["id" => $currentStaffId]),
                "request" => $searchRequest,
                "errorCode" => $e->getCode(),
                "errorMessage" => $e->getMessage(),
                "status" => StatusConstants::FAILED
            ]);
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $response;
    }
     /**
     * insert Internal Mark Edit Log
     * @param  $insertionValues
     */
    private function insertStudentMarksEditLog($insertionValues){
        try {
            foreach($insertionValues as $insertObj){
                $insert_query = "INSERT INTO im_student_mark_edit_log
                (id,student_id,groups_id,academic_term_id,academic_paper_subjects_id,log,created_by,created_date,updated_by,updated_date)
                VALUES ('$insertObj->id','$insertObj->studentId','$insertObj->groupId','$insertObj->academicTermId','$insertObj->academicPaperSubjectId','[$insertObj->log]','$insertObj->createdBy', utc_timestamp(), '$insertObj->updatedBy', utc_timestamp() ) ON DUPLICATE KEY UPDATE log = JSON_MERGE(`log`,'$insertObj->log'), updated_by = VALUES(created_by) " ;
                $this->executeQuery($insert_query);
            }
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
    /**
     * getInternalSessionalDates
     * @param $searchRequest 
     * @return $SubjectWiseInternalDates 
     * @author Krishnajith
     */
    public function getInternalSessionalDates($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try
        {
            $orderBy = " ORDER BY sub.name ASC";
            $whereQuery = "";
            if(!empty($searchRequest->groupId)) {
                $groupIdString = is_array($searchRequest->groupId) ? "'" . implode("','",$searchRequest->groupId) . "'" : "'".$searchRequest->groupId."'";
                $whereQuery .= " AND g.id IN ( $groupIdString )";
            }
            if(!empty($searchRequest->academicPaperSubjectId)) {
                $academicPaperSubjectIdStrng = is_array($searchRequest->academicPaperSubjectId) ? "'" . implode("','",$searchRequest->academicPaperSubjectId) . "'" : "'".$searchRequest->academicPaperSubjectId."'";
                $whereQuery .= " AND aps.id IN ( $academicPaperSubjectIdStrng )";
            }
            if(!empty($searchRequest->academicTermId)) {
                $academicTermIdString = is_array($searchRequest->academicTermId) ? "'" . implode("','",$searchRequest->academicTermId) . "'" : "'".$searchRequest->academicTermId."'";
                $whereQuery .= " AND str.academic_term_id IN ( $academicTermIdString )";
            }
            if(!empty($searchRequest->isInternalOrSessional)) {
                $whereQuery .= " AND esims.type = '$searchRequest->isInternalOrSessional'";
            }
            if(!empty($searchRequest->sessionalExamTypeId)) {
                $whereQuery .= " AND esims.sessional_exam_type_id = $searchRequest->sessionalExamTypeId";
            }
            if(!empty($searchRequest->fromDate)) {
                $fromDateString = is_array($searchRequest->fromDate) ? "'" . implode("','",$searchRequest->fromDate) . "'" : "'".$searchRequest->fromDate."'";
                $whereQuery .= " AND esims.from_date IN ( $fromDateString )";
            }
            if(!empty($searchRequest->toDate)) {
                $toDateString = is_array($searchRequest->toDate) ? "'" . implode("','",$searchRequest->toDate) . "'" : "'".$searchRequest->toDate."'";
                $whereQuery .= " AND esims.to_date IN ( $toDateString )";
            }
            $query = "SELECT DISTINCT
                            aps.id AS academicPaperSubjectId,
                            sub.id AS subjectId,
                            sub.code AS subjectCode,
                            sub.name AS subjectName,
                            esims.from_date AS fromDate,
                            esims.to_date AS toDate,
                            esims.type AS isInternalOrSessional,
                            esims.sessional_exam_type_id AS sessionalExamTypeId,
                            act.name as academicTermName,
                            str.academic_term_id as academicTermId,
                            g.id AS groupId,
                            g.name AS groupName
                        FROM cluster c 
                        INNER JOIN cluster_members cm ON 
                            cm.cluster_id = c.id
                        INNER JOIN cluster_groups_relations cg ON 
                            cg.cluster_id = c.id
                        INNER JOIN `groups` sg ON 
                            sg.id = cg.groups_id AND sg.type = 'SUBJECT'
                        INNER JOIN groups_relations gr ON 
                            gr.child_groups_id = cg.groups_id
                        INNER JOIN `groups` g ON 
                            gr.parent_groups_id = g.id AND g.type = 'BATCH'
                        INNER JOIN cm_academic_paper_subjects aps ON 
                            aps.id = sg.paperSubjectId
                        INNER JOIN cm_academic_paper ap ON 
                            aps.cm_academic_paper_id = ap.id
                        INNER JOIN v4_ams_subject sub ON 
                            sub.id = aps.ams_subject_id
                        INNER JOIN cm_syllabus_academic_term_settings str ON 
                            str.id = ap.cm_syllabus_academic_term_settings_id 
                        INNER JOIN ec_sessional_internal_marks_settings esims ON 
                            esims.groups_id = g.id AND esims.academic_paper_subjects_id = aps.id AND esims.academic_term_id = str.academic_term_id
                        WHERE 1=1 ";
            $subjectInternalDates = $this->executeQueryForList($query.$whereQuery.$orderBy);
            
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $subjectInternalDates;
    }
     /**
     * changeInternalMarkSubjectSubmittedStatus
     * @param $searchRequest 
     * @return $response 
     */
    public function changeInternalMarkSubjectSubmittedStatus($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        $response = new \stdClass;
        $currentStaffId = $GLOBALS['userId'];
        $insertionInternalMarkSubmitedTableArray = [];
        $deletionInternalMarkSubmitedTableArray = [];
        try{
            $academicPaperSubjectId = $searchRequest->academicPaperSubjectId;
            $groupId = $searchRequest->groupId;
            $academicTermId = $searchRequest->academicTermId;
            $internalSubjectSubmittedStatus = $searchRequest->internalSubjectSubmittedStatus;
            if(empty($academicPaperSubjectId) || empty($academicTermId) || empty($groupId)){
                throw new ExamControllerException(ExamControllerException::EMPTY_PARAMETERS,"Invailed Request For Save Internal Mark");
            }
            else{
                if($internalSubjectSubmittedStatus == "ALLOW"){
                    $insertionInternalMarkSubmitedTableArray[] = " ('".$groupId."', '".$academicTermId."','".$academicPaperSubjectId."','".$currentStaffId."','EXAM_CONTROLLER','".$currentStaffId."', utc_timestamp(), '".$currentStaffId."', utc_timestamp() ) ";
                }
                elseif($internalSubjectSubmittedStatus == "BLOCK"){
                    $deletionInternalMarkSubmitedTableObj = new \stdClass;
                    $deletionInternalMarkSubmitedTableObj->groupId = $groupId;
                    $deletionInternalMarkSubmitedTableObj->academicTermId = $academicTermId;
                    $deletionInternalMarkSubmitedTableObj->academicPaperSubjectId = $academicPaperSubjectId;
                    $deletionInternalMarkSubmitedTableArray[] = $deletionInternalMarkSubmitedTableObj;
                }
            }
            if(! empty($insertionInternalMarkSubmitedTableArray)){
                $this->insertInternalSubjectSubmittedTable($insertionInternalMarkSubmitedTableArray);
            }
            if(! empty($deletionInternalMarkSubmitedTableArray)){
                $this->deleteInternalSubjectSubmittedTable($deletionInternalMarkSubmitedTableArray);
            }
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $response;
    }
     /**
     * insertInternalSubjectSubmittedTable
     * @param  $insertionValues
     */
    private function insertInternalSubjectSubmittedTable($insertionValues){
        try {
            $insert_query = "INSERT INTO ec_internal_marks_submitted
                                (groups_id,academic_term_id,academic_paper_subjects_id,staff_id,staff_type,created_by,created_date,updated_by,updated_date)
                                VALUES " . implode ( ",", $insertionValues ) . " ON DUPLICATE KEY UPDATE updated_by = VALUES(created_by) " ;
            $this->executeQuery($insert_query);
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
     /**
     * deleteInternalSubjectSubmittedTable
     * @param  $updationDateSettingTableArray
     */
    public function deleteInternalSubjectSubmittedTable($deletionInternalMarkSubmitedTableArray)
    {
        $deletionInternalMarkSubmitedTableArray = $this->realEscapeArray($deletionInternalMarkSubmitedTableArray);
        try {
            foreach($deletionInternalMarkSubmitedTableArray as $deleteValue){
                $update_query = "DELETE FROM
                            ec_internal_marks_submitted
                        WHERE
                            groups_id = '$deleteValue->groupId' AND
                            academic_term_id = '$deleteValue->academicTermId' AND
                            academic_paper_subjects_id = '$deleteValue->academicPaperSubjectId'";
                $this->executeQuery($update_query);
            }
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
          /**
     * get Mark Log Report
     * @param $searchRequest 
     * @return $response 
     */
    public function getMarkLogReport($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $markLogRequest = new \stdClass;
            $markLogRequest->startDate = $searchRequest->startDate;
            $markLogRequest->endDate = $searchRequest->endDate;
            $markLogs = $this->getInternalMarkLogReport($markLogRequest);
            if(empty($markLogs)){
                throw new ExamControllerException(ExamControllerException::NO_REPORTS_DETAILS_FOUND,"No Mark log found.");
            }
            $markLogsArray = [];
            $getAllFacultiesRequest = new GetAllFacultiesRequest;
            $staffs = StaffService::getInstance()->getAllFacultiesForApi($getAllFacultiesRequest);
            $allStaffs = [];
            foreach($staffs as $staff){
                $allStaffs[$staff->id] = $staff;
            }
            foreach($markLogs as $markLog){
                if($markLog->internalMarkLogs){
                    $logs = $markLog->internalMarkLogs;
                    usort($logs, function ($a, $b) {
                        return strtotime($a->actionTakenTime) < strtotime($b->actionTakenTime);
                    });
                    $markLog->logs = $logs;
                    foreach($logs as $log){
                        $log->actionDate = date("Y-m-d", (strtotime($log->actionTakenTime)));
                        $log->actionTakenDateTime = date("Y-m-d H:i", (strtotime($log->actionTakenTime)));
                        if(($log->actionDate >= $markLogRequest->startDate) && ($log->actionDate <= $markLogRequest->endDate)) {
                            $log->updatedStaffName =  $allStaffs[$log->updatedStaffId]->name;
                            $markLogDetails = new \stdClass;
                            $markLogDetails->studentId = $markLog->studentId;
                            $markLogDetails->studentName = $markLog->studentName;
                            $markLogDetails->studentRegisterNo = $markLog->studentRegisterNo;
                            $markLogDetails->subjectCode = $markLog->subjectCode;
                            $markLogDetails->subjectName = $markLog->subjectName;
                            $markLogDetails->log = $log;
                            $markLogsArray[] = $markLogDetails;
                        }
                    }
                }
            }
            $templateName = "internal_mark_log_report_template_1";
            $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/markLogReport/$templateName.twig"), [ 'markLog'=>$markLogsArray ]);
            $prtContent = NULL;
                $prtContent .= '<html><head>';
                $prtContent .= "";
                $prtContent .= '</head><title>Internal mark log report</title><body>';
                $prtContent .= $responseHtml;
                $prtContent .= '</body></html>';
                $totalWidth = 210;
                $totalHeight = 297;
                $options = array(
                    'page-width'     => $totalHeight."mm",
                    'page-height'    => $totalWidth."mm",
                    'dpi'            => 96,
                    'margin-top' => "9mm",
                    'margin-left' => "1mm",
                    'margin-right' => "1mm",
                    'margin-bottom' => "9mm",
                    // 'binary' => "/usr/local/bin/wkhtmltopdf", // For Mac
                    'user-style-sheet' => realpath(DOCUMENT_ROOT . "/libcommon/bootstrap/css/bootstrap.min.css")
                );
            $programResult = new \stdClass;
            $programResult->dispalyHtmlData = $responseHtml;
            $programResult->studentsData = $markLogs;
            $programResult->printData = PdfUtil::renderPdf($prtContent, $options);
            
            
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return  $programResult;
    }
    /**
     * get Internal Mark Log Report
     * @param $searchRequest  
     * @author Krishnajith
     */
    public function getInternalMarkLogReport($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $orderBy = " ORDER BY imlog.updated_date DESC";
            $whereQuery = "";
            if(!empty($searchRequest->startDate)) {
                $whereQuery .= " AND (DATE_FORMAT(imlog.created_date,'%Y-%m-%d') >= '$searchRequest->startDate' OR DATE_FORMAT(imlog.updated_date,'%Y-%m-%d') >= '$searchRequest->startDate') ";
            }
            if(!empty($searchRequest->endDate)) {
                $whereQuery .= " AND DATE_FORMAT(imlog.updated_date,'%Y-%m-%d') <= '$searchRequest->endDate'";
            }
            $query = "SELECT DISTINCT
                            spa.student_id AS id,
                            g.id AS groupId,
                            g.name AS groupName,
                            g.properties ->>'$.programId'  AS programId,
                            aps.id AS academicPaperSubjectId,
                            sub.id AS subjectId,
                            sub.name AS subjectName,
                            sub.code AS subjectCode,
                            act.name as academicTermName,
                            act.id as academicTermId,
                            aps.properties ->> '$.isInternal' as isInternal,
                            aps.properties ->> '$.isExternal' as isExternal,
                            aps.properties ->> '$.internalMaxMark' as internalMaxMark,
                            spa.student_id AS studentId,
                            spa.properties->>'$.rollNumber' AS studentRollNo,
                            spa.properties->>'$.registerNumber' AS studentRegisterNo,
                            std.studentName AS studentName,
                            IF(im.id,1,0) AS isInternalEntered,
                            im.internal_mark AS internalMark,
                            im.attendance_status AS attendanceStatus,
                            imlog.log AS internalMarkLogs
                        FROM 
                            studentaccount s 
                        INNER JOIN student_program_account spa
                            ON spa.student_id = s.studentID
                        INNER JOIN student_program_batch_log spbl 
                            ON spbl.program_student_id = spa.id  AND spbl.properties->>'$.academicStatus' IN ('ACTIVE','COMPLETED')
                        INNER JOIN `program` p 
                            ON p.id = spbl.program_id
                        INNER JOIN `groups` g 
                            ON g.id = spbl.batch_group_id
                        INNER JOIN groups_relations gr ON 
                            gr.parent_groups_id = g.id
                        INNER JOIN `groups` sg ON 
                            sg.id = gr.child_groups_id AND sg.type = 'SUBJECT'
                        INNER JOIN group_members sgm ON
                            sgm.groups_id = sg.id AND 
                            sgm.members->>'$.studentId' = spa.id AND 
                            sgm.academic_status IN ('ACTIVE')
                        INNER JOIN cm_academic_paper_subjects aps ON 
                            aps.id = sg.paperSubjectId
                        INNER JOIN academic_term act ON
                            act.id = sg.academic_term_id AND act.id = spbl.term_id
                        INNER JOIN v4_ams_subject sub ON 
                            sub.id = aps.ams_subject_id
                        INNER JOIN studentaccount std ON 
                            std.studentID = spa.student_id
                        INNER JOIN ec_internal_marks im ON 
                            im.groups_id  = g.id AND im.academic_paper_subjects_id = aps.id AND im.academic_term_id = act.id AND im.student_id = spa.student_id
                        INNER JOIN im_student_mark_edit_log imlog ON 
                            imlog.groups_id = g.id AND imlog.academic_paper_subjects_id = aps.id AND imlog.academic_term_id = act.id AND imlog.student_id = std.studentID 
                        WHERE 1=1 ";
            $internalMarkLogs = $this->executeQueryForList($query.$whereQuery.$orderBy);
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        array_walk($internalMarkLogs, function($internalMarkLog){
            $internalMarkLog->internalMarkLogs =  json_decode($internalMarkLog->internalMarkLogs);
            
        });
        return $internalMarkLogs;
    }
     /**
     * save Imported Internal Marks
     * @param $searchRequest 
     * @return $response 
     */
    public function saveImportedInternalMarks($clusterId,$studentIds) {
        $clusterId = $this->realEscapeObject($clusterId);
        $studentIds = $this->realEscapeObject($studentIds);
        $currentStaffId = $GLOBALS['userId'];
        $updatedStudentIds = [];
        try{
            $searchAssessmentReportInternalMarkRequest = new SearchAssessmentReportInternalMarkRequest();
            $searchAssessmentReportInternalMarkRequest->clusterId = $clusterId;
            $searchAssessmentReportInternalMarkRequest->studentIds = $studentIds;
            $searchAssessmentReportInternalMarkRequest->confirmed="1";
            $searchAssessmentReportInternalMarkRequest->copiedToExamController = "0";
            $studentList = AssessmentReportInternalMarkService::getInstance()->searchAssessmentReportInternalMark($searchAssessmentReportInternalMarkRequest);
            if(empty($studentIds) || empty($clusterId) || empty($studentList)){
                throw new ExamControllerException(ExamControllerException::EMPTY_PARAMETERS,"Invaild Request For Save Internal Mark");
            }
            else{
                foreach($studentList as $student){
                    $groupId = $student->batchGroupId;
                    $academicTermId = $student->academicTermId;
                    $searchRequest = new \stdClass;
                    $searchRequest->clusterId = $student->clusterId;
                    $searchRequest->batchGroupId = $student->batchGroupId;
                    $searchRequest->studentId = $student->studentId;
                    $paperDetails = $this->getPaperSubjectDetailsForInternalMarks($searchRequest);
                    if(empty($paperDetails)){
                        continue;
                    }
                    $academicPaperSubjectId = $paperDetails->paperSubjectId;
                    $programId = $paperDetails->programId;
                    if(!empty($student->mark) || $student->mark == 0 ){
                        if($student->mark == "AB" || $student->absentStatus == "AB"){
                            $insertionInternalMarkTableArray[] = " ('".$student->studentId."','".$groupId."','".$programId."', '".$academicTermId."','".$academicPaperSubjectId."',NULL,'ABSENT','".$currentStaffId."', utc_timestamp(), '".$currentStaffId."', utc_timestamp(),  ".(isset($student->formativeMark) ? "'".$student->formativeMark."'" : "NULL").", ".(isset($student->summativeMark) ? "'".$student->summativeMark."'" : "NULL")." ) ";
                            $updatedStudentIds [] = $student->studentId;
                        }
                        elseif($student->absentStatus == "I"){
                            $insertionInternalMarkTableArray[] = " ('".$student->studentId."','".$groupId."','".$programId."', '".$academicTermId."','".$academicPaperSubjectId."',NULL,'INCOMPLETED','".$currentStaffId."', utc_timestamp(), '".$currentStaffId."', utc_timestamp(),  ".(isset($student->formativeMark) ? "'".$student->formativeMark."'" : "NULL").", ".(isset($student->summativeMark) ? "'".$student->summativeMark."'" : "NULL")." ) ";
                            $updatedStudentIds [] = $student->studentId;
                        }
                        elseif(is_numeric($student->mark)){
                            $insertionInternalMarkTableArray[] = " ('".$student->studentId."','".$groupId."','".$programId."', '".$academicTermId."','".$academicPaperSubjectId."','".$student->mark."','PRESENT','".$currentStaffId."', utc_timestamp(), '".$currentStaffId."', utc_timestamp(),  ".(isset($student->formativeMark) ? "'".$student->formativeMark."'" : "NULL").", ".(isset($student->summativeMark) ? "'".$student->summativeMark."'" : "NULL")." ) ";
                            $log = new \stdClass;
                            // $log->oldMark = $student['oldInternalMarks'];
                            $log->newMark = $student->mark;
                            $log->remarks = 'Staff side mark import';
                            $log->markType = "INTERNAL_MARK";
                            $log->actionTakenTime = date("d-m-Y h:i A");
                            $log->updatedStaffId = $currentStaffId;
                            $log->updatedStaffType = "ACADEMICS";
                            $log->menuName = "IMPORT_INTERNAL_MARKS";
                            $log = json_encode($log);
                            $id = SecurityUtils::getRandomString();
                            $insertionInternalMarkLogEntryObj = new \stdClass();
                            $insertionInternalMarkLogEntryObj->id = $id;
                            $insertionInternalMarkLogEntryObj->studentId = $student->studentId;
                            $insertionInternalMarkLogEntryObj->groupId = $groupId;
                            $insertionInternalMarkLogEntryObj->academicTermId = $academicTermId;
                            $insertionInternalMarkLogEntryObj->academicPaperSubjectId = $academicPaperSubjectId;
                            $insertionInternalMarkLogEntryObj->log = $log;
                            $insertionInternalMarkLogEntryObj->createdBy = $currentStaffId;
                            $insertionInternalMarkLogEntryObj->updatedBy = $currentStaffId;
                            $insertionInternalMarkLogTableArray[] = $insertionInternalMarkLogEntryObj;
                            $updatedStudentIds [] = $student->studentId;
                        }
                        $request = new \stdClass();
                        $request->groupId = $groupId;
                        $request->studentId = $student->studentId;
                        $request->isDirty = 1;
                        $request->staffId = $GLOBALS['userId'];
                        $editHistoryLog[] = $request;
                    }
                }
            }
            if(! empty($insertionInternalMarkTableArray)){
                $this->insertStudentInternalMarks($insertionInternalMarkTableArray , true);
                AssessmentReportInternalMarkService::getInstance()->updateCopiedToExamController($clusterId,$updatedStudentIds,1);
                $this->logger->info(Events::EC_SAVE_INTERNAL_MARK,[
                    "staff" => new Staff(["id" => $currentStaffId]),
                    "request" => $searchRequest,
                    "status" => StatusConstants::SUCCESS
                ]);
            }
            if(! empty($editHistoryLog)){
                StudentsOverAllMarkReportService::getInstance()->insertStudentEditStatus($editHistoryLog);
            }
            if(! empty($insertionInternalMarkLogTableArray)){
                $this->insertStudentMarksEditLog($insertionInternalMarkLogTableArray);
            }
        }
        catch (\Exception $e){
            AMSLogger::log_error($this->logger,Events::EC_SAVE_INTERNAL_MARK,[
                "staff" => new Staff(["id" => $currentStaffId]),
                "request" => $searchRequest,
                "errorCode" => $e->getCode(),
                "errorMessage" => $e->getMessage(),
                "status" => StatusConstants::FAILED
            ]);
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $response;
    }
    /**
     * get paper details
     * @param $searchRequest  
     */
    public function getPaperSubjectDetailsForInternalMarks($request) {
        $request = $this->realEscapeObject($request);
        try{
            $query = "SELECT
                        spa.current_program_id AS programId, aps.id AS paperSubjectId  from student_program_account spa 
                    INNER JOIN groups_relations gr ON 
                        spa.current_batch_id = gr.parent_groups_id 
                    INNER JOIN cluster_groups_relations cgr ON 
                        cgr.groups_id = gr.child_groups_id 
                    INNER JOIN `groups` g ON 
                        g.id = gr.child_groups_id
                    INNER JOIN cm_academic_paper_subjects aps ON 
                        aps.id=g.paperSubjectId  
                    INNER JOIN group_members gm ON 
                        gm.groups_id = g.id and spa.id = gm.student_id 
                    WHERE 
                        spa.academic_status='ACTIVE' AND gm.academic_status = 'ACTIVE' AND cgr.cluster_id='$request->clusterId' AND current_batch_id ='$request->batchGroupId' AND spa.student_id =$request->studentId";
            $result = $this->executeQueryForObject($query);
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $result;
    }
    /**
     * get Assigned Subject Students Details For Remove Confirmed State
     * @param $searchRequest 
     * @return $subjectWiseInternalMarkDetails 
     * @author Krishnajith
     */
    public function getAssignedSubjectStudentsDetailsForRemoveConfirmState($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $mapperConst = InternalMarkServiceMapper::INTERNAL_MARK_SUBJECT_STUDENT_CONFIRM_STATE;
            $orderBy = " ORDER BY sub.name ASC , spa.properties->>'$.registerNumber' ASC";
            $whereQuery = "";
            if(!empty($searchRequest->groupId)) {
                $groupIdString = is_array($searchRequest->groupId) ? "'" . implode("','",$searchRequest->groupId) . "'" : "'".$searchRequest->groupId."'";
                $whereQuery .= " AND g.id IN ( $groupIdString )";
            }
            if(!empty($searchRequest->programId)) {
                $programIdString = is_array($searchRequest->programId) ? "'" . implode("','",$searchRequest->programId) . "'" : "'".$searchRequest->programId."'";
                $whereQuery .= " AND p.id IN ( $programIdString )";
            }
            if(!empty($searchRequest->academicTermId)) {
                $academicTermIdString = is_array($searchRequest->academicTermId) ? "'" . implode("','",$searchRequest->academicTermId) . "'" : "'".$searchRequest->academicTermId."'";
                $whereQuery .= " AND act.id IN ( $academicTermIdString )";
            }
    
            $query = "SELECT DISTINCT
                            g.id AS groupId,
                            g.name AS groupName,
                            g.properties ->>'$.programId'  AS programId,
                            aps.id AS academicPaperSubjectId,
                            sub.id AS subjectId,
                            sub.name AS subjectName,
                            sub.code AS subjectCode,
                            act.name as academicTermName,
                            act.id as academicTermId,
                            aps.properties ->> '$.isInternal' as isInternal,
                            aps.properties ->> '$.isExternal' as isExternal,
                            aps.properties ->> '$.internalMaxMark' as internalMaxMark,
                            cgr.cluster_id as clusterId,
                            spa.student_id AS studentId,
                            spa.properties->>'$.rollNumber' AS studentRollNo,
                            spa.properties->>'$.registerNumber' AS studentRegisterNo,
                            std.studentName AS studentName,
                            IF(im.id,1,0) AS isInternalEntered,
                            im.internal_mark AS internalMark,
                            im.attendance_status AS attendanceStatus,
                            arim.copied_to_exam_controller as copiedToExamController,
                            arim.confirmed as interalConfirmed,
                            imlog.log AS internalMarkLogs
                        FROM 
                            studentaccount s 
                        INNER JOIN student_program_account spa
                            ON spa.student_id = s.studentID
                        INNER JOIN student_program_batch_log spbl 
                            ON spbl.program_student_id = spa.id AND spbl.properties->>'$.academicStatus' IN ('ACTIVE','COMPLETED')
                        INNER JOIN `program` p 
                            ON p.id = spbl.program_id
                        INNER JOIN `groups` g 
                            ON g.id = spbl.batch_group_id
                        INNER JOIN groups_relations gr ON 
                            gr.parent_groups_id = g.id
                        INNER JOIN cluster_groups_relations cgr ON 
                            cgr.groups_id = gr.child_groups_id 
                        INNER JOIN `groups` sg ON 
                            sg.id = gr.child_groups_id AND sg.type = 'SUBJECT'
                        INNER JOIN group_members sgm ON
                            sgm.groups_id = sg.id AND 
                            sgm.members->>'$.studentId' = spa.id
                            AND sgm.academic_status IN ('ACTIVE')
                        INNER JOIN cm_academic_paper_subjects aps ON 
                            aps.id = sg.paperSubjectId
                        INNER JOIN cm_academic_paper ap ON 
                            aps.cm_academic_paper_id = ap.id
                        INNER JOIN cm_syllabus_academic_term_settings csats ON
                            csats.id = ap.cm_syllabus_academic_term_settings_id 
                        INNER JOIN academic_term act ON
                            act.id = sg.academic_term_id AND act.id = spbl.term_id
                        INNER JOIN v4_ams_subject sub ON 
                            sub.id = aps.ams_subject_id
                        INNER JOIN studentaccount std ON 
                            std.studentID = spa.student_id
                        INNER JOIN am_report_internal_mark arim ON
                            arim.student_id = spa.student_id AND
                            arim.cluster_id = cgr.cluster_id AND
                            arim.batch_group_id = g.id
                        LEFT JOIN ec_internal_marks im ON 
                            im.groups_id  = g.id AND im.academic_paper_subjects_id = aps.id AND im.academic_term_id = act.id AND im.student_id = spa.student_id
                        LEFT JOIN im_student_mark_edit_log imlog ON 
                            imlog.groups_id = g.id AND imlog.academic_paper_subjects_id = aps.id AND imlog.academic_term_id = act.id AND imlog.student_id = spa.student_id
                        WHERE 1=1 AND sg.academic_term_id = csats.academic_term_id";
            $subjectWiseInternalMarkDetails = $this->executeQueryForList($query.$whereQuery.$orderBy, $this->mapper[$mapperConst]);
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $subjectWiseInternalMarkDetails;
    }
     /**
     * get Internal Mark Confirmed Student list
     * @param $searchRequest 
     * @return $response 
     */
     public function getInternalMarkConfirmedStudentList($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $response = new \stdClass;
            $request = new \stdClass;
            $request->courseTypeId = $searchRequest->courseTypeId;
            $request->departmentId = $searchRequest->departmentId;
            $request->groupId = $searchRequest->groupId;
            $request->academicTermId = $searchRequest->academicTermId;  
            $subjectList = $this->getAssignedSubjectStudentsDetailsForRemoveConfirmState($request);
            $getAllFacultiesRequest = new GetAllFacultiesRequest;
            $staffs = StaffService::getInstance()->getAllFacultiesForApi($getAllFacultiesRequest);
            $allStaffs = [];
            foreach($staffs as $staff){
                $allStaffs[$staff->id] = $staff;
            }
            foreach($subjectList as $subject){
                foreach($subject->students as $student){
                    if($student->logs){
                        usort($student->logs, function ($a, $b) {
                            return strtotime($a->actionTakenTime) < strtotime($b->actionTakenTime);
                        });
                        foreach($student->logs as $log){
                            $log->actionDate = date("Y-m-d", (strtotime($log->actionTakenTime)));
                            $log->actionTakenDateTime = date("Y-m-d H:i", (strtotime($log->actionTakenTime)));
                            $log->updatedStaffName =  $allStaffs[$log->updatedStaffId]->name;
                        }
                    }
                    else{
                        $student->logs = [];
                    }
                }
                $subject->totalStudents =  count($subject->students);
                $subject->importedStudents = count(array_filter(array_column($subject->students, 'copiedToExamController')));
                $subject->confirmedStudents = count(array_filter(array_column($subject->students, 'interalConfirmed')));
                $subject->isImportedInternalMark =  $subject->importedStudents > 0 ? 1 : 0;
            }
            $response->subjectList = $subjectList;
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $response;
    }
     /**
     * save Internal Mark Confirmed state 
     * @param $searchRequest 
     * @return $response 
     */
     public function saveInternalMarkConfirmState($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $response = new \stdClass;
            $students =  $searchRequest->students;
            $clusters = [];
            foreach($students as $student){
                if($student->copiedToExamController == '1'){
                    $clusters[$student->clusterId]->requestForUpdateCopiedToExamControllerEnabled->clusterId = $student->clusterId;
                    $clusters[$student->clusterId]->requestForUpdateCopiedToExamControllerEnabled->studentIds[] = $student->id;
                    $clusters[$student->clusterId]->requestForUpdateCopiedToExamControllerEnabled->copiedToExamController = 1;
                }
                else{
                    $clusters[$student->clusterId]->requestForUpdateCopiedToExamControllerDisabled->clusterId = $student->clusterId;
                    $clusters[$student->clusterId]->requestForUpdateCopiedToExamControllerDisabled->studentIds[] = $student->id;
                    $clusters[$student->clusterId]->requestForUpdateCopiedToExamControllerDisabled->copiedToExamController = 0;
                }
            }  
            foreach($clusters as $cluster){
                $requestForUpdateCopiedToExamControllerEnabled = $cluster->requestForUpdateCopiedToExamControllerEnabled;
                $requestForUpdateCopiedToExamControllerDisabled = $cluster->requestForUpdateCopiedToExamControllerDisabled;
                if(!empty($requestForUpdateCopiedToExamControllerEnabled->studentIds)){
                    AssessmentReportInternalMarkService::getInstance()->updateCopiedToExamController($requestForUpdateCopiedToExamControllerEnabled->clusterId,$requestForUpdateCopiedToExamControllerEnabled->studentIds,1);
                }
                if(!empty($requestForUpdateCopiedToExamControllerDisabled->studentIds)){
                    AssessmentReportInternalMarkService::getInstance()->updateCopiedToExamController($requestForUpdateCopiedToExamControllerDisabled->clusterId,$requestForUpdateCopiedToExamControllerDisabled->studentIds,0);
                }       
            }  
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $response;
    }
    
    /**
     * get print data for internal mark consolidated
     * @param $searchRequest 
     * @return $response 
     */
     public function getPrintDataForInternalMarkConsolidated($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $response = new \stdClass;
            $request = new \stdClass;
            $request->groupId = $searchRequest->groupId;
            $request->academicTermId = $searchRequest->academicTermId;
            $batchDetails = new \stdClass;
            $request->mapping = "STUDENT-WISE";
            $assignedSubjects = CommonExamService::getInstance()->getAssignedSubjectsInBatch($request);
            $batchSubjects = [];
            foreach($assignedSubjects as $key => $subject){
                if($subject->internalMaxMark && $subject->isInternal) {
                    $batchSubjects[] = $subject;
                }
            }
            $studentList =  $this->getAssignedSubjectStudentsDetailsForInternalMarkEntry($request);
            if(empty($studentList)){
                throw new ExamControllerException(ExamControllerException::NO_DETAILS_FOUND,"No Students Found In This Batch");
            }
            else{
                $batchDetails->groupId = reset($studentList)->groupId;
                $batchDetails->groupName = reset($studentList)->groupName;
                $batchDetails->academicTermId = reset($studentList)->academicTermId;
                $batchDetails->academicTermName = reset($studentList)->academicTermName;
                foreach($studentList as $student){
                    foreach($student->subjects as $subject){
                        $subject->internalMark = $subject->internalMark ? number_format((float)$subject->internalMark, 2, '.', '') : null;
                        if($subject->attendanceStatus == "ABSENT"){
                            $subject->internalMark = "AB";
                        }
                        if($subject->attendanceStatus == "INCOMPLETE"){
                            $subject->internalMark = "I";
                        }
                    }
                    foreach($assignedSubjects as $subject){
                        foreach($student->subjects as $studentSubject){
                            $studentSubject->isAssigned = false;
                            if($studentSubject->academicPaperSubjectId ==  $subject->academicPaperSubjectId){
                                $studentSubject->isAssigned = true;
                            }
                        }
                    }
                }
            }
            $collegeAndOtherData = CommonExamService::getInstance()->getCollegeDetails($request);
            $additionalInfo = new \stdClass();
            $additionalInfo->groupName = reset($studentList)->groupName;
            $additionalInfo->academicTermName = reset($studentList)->academicTermName;
            $additionalInfo->programName = reset($studentList)->programName;
            $additionalInfo->subjectCount = count($batchSubjects);
            $subjectExcelWidth = [];
            for ($i = 1; $i <= $additionalInfo->subjectCount ; $i++) {
                $subjectExcelWidth[] = 20;
            }
            $additionalInfo->excelSubjectWidth = implode(',' ,$subjectExcelWidth);
            $templateName = "internal_mark_view_consolidated_report";
            $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/internalMarkView/$templateName.twig"), [ 'batchAssignedStudents'=>$studentList , 'batchSubjects' => $batchSubjects, 'collegeAndOtherData' => $collegeAndOtherData, 'additionalInfo' => $additionalInfo]);
            $prtContent = NULL;
            $prtContent .= '<html><head>';
            $prtContent .= "";
            $prtContent .= '</head><title>Internal mark consolidated</title><body>';
            $prtContent .= $responseHtml;
            $prtContent .= '</body></html>';
            $totalWidth = 210;
            $totalHeight = 297;
            $options = array(
                'page-width'     => $totalHeight."mm",
                'page-height'    => $totalWidth."mm",
                'dpi'            => 96,
                'margin-top' => "9mm",
                'margin-left' => "3mm",
                'margin-right' => "3mm",
                'margin-bottom' => "9mm",
                // 'binary' => "/usr/local/bin/wkhtmltopdf", // For Mac
                'user-style-sheet' => realpath(DOCUMENT_ROOT . "/libcommon/bootstrap/css/bootstrap.min.css")
            );
            $programResult = new \stdClass;
            $programResult->printData = PdfUtil::renderPdf($prtContent, $options);
            $programResult->exportExcelData = $responseHtml;
            
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $programResult;
    }
    /**
     * get Srudent supply internal mark details
     * @param $searchRequest 
     * @return $response
     * @author Krishnajith
     */
    public function getStudentSupplySubjectList($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            if(empty($searchRequest->examRegistrationId) || (empty($searchRequest->rollNo) && empty($searchRequest->registerNo))){
                throw new ExamControllerException(ExamControllerException::EMPTY_PARAMETERS,"Invaild Request");
            }
            $searchRuleRequest = new SearchRuleRequest;
            $searchRuleRequest->name = "SUPPLY_INTERNAL_MARK_RULE";
            $ruleObj = reset(RuleService::getInstance()->searchRule($searchRuleRequest))->rule;
            $response = new \stdClass;
            $request = new \stdClass;
            $request->examRegistrationId = $searchRequest->examRegistrationId;
            $request->rollNo = $searchRequest->rollNo;
            $request->registerNo = $searchRequest->registerNo;
            $request->considerInternalSubject = 1;
            $response->showCarriedStatus = $ruleObj->isShowInternalExamCarriedStatus == 1 ? true : false;
            $error = false;
            $errorMsg = null;  
            $studentSubjectList = $this->getStudentSupplyAssignedSubjectList($request);
            AMSLogger::log_info($this->logger,Events::FETCH_SUPPLY_STUDENT_INTERNAL_MARK,[
                "staff" => new Staff(["id" => $GLOBALS['userId']]),
                "request" => $searchRequest,
                "status" => StatusConstants::SUCCESS
            ]);
            if(empty($studentSubjectList)){
                throw new ExamControllerException(ExamControllerException::EMPTY_PARAMETERS,"No Student Found");
            }
            $studentSubjects = reset($studentSubjectList);
            foreach($studentSubjects->subjects as $subject){
                if($subject->regularInternalAttendanceStatus == 'ABSENT'){
                    $subject->regularInternalMark = "AB";
                }
                if($subject->internalAttendanceStatus == 'ABSENT'){
                    $subject->internalMark = "AB";
                }
            }
            if(!$error){
                $response->studentSubjectList = reset($studentSubjectList);
                $response->errorMsg = $errorMsg;
            }
            else{
                $response->studentSubjectList = new \stdClass;
                $response->errorMsg = $errorMsg;
            }
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $response;
    }
    /**
     * get Srudent supply Assigned Subject List
     * @param $searchRequest 
     * @return $studentSubjectList 
     * @author Krishnajith
     */
    public function getStudentSupplyAssignedSubjectList($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $mapperConst = InternalMarkServiceMapper::SUPPLY_INTERNAL_MARK_SUBJECT_LIST;
            $orderBy = " ORDER BY sub.name ASC ";
            $whereQuery = "";
            if(!empty($searchRequest->examRegistrationId)) {
                $examRegistrationIdString = is_array($searchRequest->examRegistrationId) ? "'" . implode("','",$searchRequest->examRegistrationId) . "'" : "'".$searchRequest->examRegistrationId."'";
                $whereQuery .= " AND eer.id IN ( $examRegistrationIdString )";
            }
            if(!empty($searchRequest->registerNo)) {
                $registerNoString = is_array($searchRequest->registerNo) ? "'" . implode("','",$searchRequest->registerNo) . "'" : "'".$searchRequest->registerNo."'";
                $whereQuery .= " AND spa.properties->>'$.registerNumber' IN ( $registerNoString )";
            }
            if(!empty($searchRequest->rollNo)) {
                $rollNoString = is_array($searchRequest->rollNo) ? "'" . implode("','",$searchRequest->rollNo) . "'" : "'".$searchRequest->rollNo."'";
                $whereQuery .= " AND spa.properties->>'$.rollNumber' IN ( $rollNoString )";
            }
            if(!empty($searchRequest->considerInternalSubject)) {
                $whereQuery .= " AND aps.properties->>'$.isInternal' = 1";
            }
            $query = "SELECT DISTINCT 
                            esar.student_id as studentId,
                            sa.studentName as studentName,
                            spa.properties->>'$.registerNumber' AS registerNo,
                            spa.properties->>'$.rollNumber' AS rollNo,
                            eer.name AS examRegistrationName,
                            oe.id AS oeExamId,
                            eers.am_assessment_id AS assessmentId,
                            sub.code AS subjectCode,
                            sub.name AS subjectName,
                            aps.properties ->> '$.internalMaxMark' as internalMaxMark,
                            im.attendance_status AS regularInternalAttendanceStatus,
                            im.internal_mark AS regularInternalMark,
                            ostm.internal_mark AS internalMark,
                            ostm.internal_attendance_status AS internalAttendanceStatus,
                            ostm.internal_carried_status AS isInternalCarriedMark,
                            ostm.mark_obtained AS markObtained,
                            ostm.attendance_status AS attendanceStatus,
                            ostm.properties AS totalMarkProperties
                        FROM ec_exam_registration eer 
                        INNER JOIN ec_exam_registration_batch eerb ON 
                            eerb.ec_exam_registration_id = eer.id 
                        INNER JOIN ec_exam_registration_subject eers ON
                            eers.ec_exam_registration_batch_id = eerb.id 
                        INNER JOIN ec_student_assessment_registration esar ON
                            esar.am_assessment_id = eers.am_assessment_id AND
                            CAST(esar.properties ->> '$.registrationStatus' AS CHAR) = 'REGISTERED'
                        INNER JOIN studentaccount sa ON 
                            sa.studentID = esar.student_id
                        INNER JOIN `groups` g ON
                            g.id = eerb.groups_id
                            AND g.`type` = 'BATCH'
                        INNER JOIN program p ON 
                            p.id = g.properties->>'$.programId'
                        INNER JOIN student_program_account spa ON 
                            spa.student_id  = esar.student_id  AND
                            spa.current_program_id = p.id 
                        INNER JOIN oe_exams oe ON
                            oe.assessment_id = eers.am_assessment_id AND oe.is_deleted = 0
                        INNER JOIN  cm_academic_paper_subjects aps ON 
                            aps.id = eers.cm_academic_paper_subjects_id
                        INNER JOIN v4_ams_subject sub ON 
                            sub.id = aps.ams_subject_id
                        LEFT JOIN ec_internal_marks im ON 
                            im.groups_id = eerb.groups_id AND
                            im.academic_paper_subjects_id = eers.cm_academic_paper_subjects_id AND 
                            im.student_id = esar.student_id 
                        LEFT JOIN oe_student_total_mark ostm ON 
                            ostm.student_id = esar.student_id AND 
                            ostm.am_assessment_id = esar.am_assessment_id AND 
                            ostm.valuation_count = 'FINALIZED' AND 
                            (ostm.valuation_type IS NULL OR ostm.valuation_type = '')
                        WHERE 1=1 ";
            $studentSubjectList = $this->executeQueryForList($query.$whereQuery.$orderBy, $this->mapper[$mapperConst]);
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $studentSubjectList;
    }
    
    /**
     * Save Srudent supply internal mark
     * @param $searchRequest 
     * @author Krishnajith
     */
    public function saveStudentSupplyInternalMarks($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $subject = $searchRequest->subject;
            if(empty($subject->studentId) && empty($subject->assessmentId) && empty($subject->oeExamId) && empty($subject->internalMark)){
                throw new ExamControllerException(ExamControllerException::EMPTY_PARAMETERS,"Invaild Request");
            }
            $markEntryObj = new \stdClass();
            $markEntryObj->studentId = $subject->studentId;
            $markEntryObj->assessmentId = $subject->assessmentId;
            $markEntryObj->oeExamsId = $subject->oeExamId;
            $markEntryObj->markObtained = $subject->markObtained;
            $markEntryObj->attendanceStatus = $subject->attendanceStatus ?? 'NULL';
            $markEntryObj->valuationCount = 'FINALIZED';
            $markproperties = "";
            if($subject->totalMarkProperties){
                $markproperties = (object)$subject->totalMarkProperties;
            }
            $markEntryObj->properties  = $markproperties;
            $markEntryObj->valuationType = null;
            $markEntryObj->internalMark = $subject->internalMark == 'AB' ? '0' : $subject->internalMark;
            $markEntryObj->internalAttendanceStatus = $subject->internalMark == 'AB' ? 'ABSENT' : 'PRESENT';
            $markEntryObj->isInternalCarriedFlag = 1;
            $markEntryObj->isInternalCarriedStatus = $subject->isInternalCarriedMark ? 1 : NULL;
            $markEntryObj->valuationType = null;
            $markEntryObj->createdBy = $GLOBALS['userId'];
            $insertionValues[] = $markEntryObj;
            AMSLogger::log_info($this->logger,Events::SAVE_SUPPLY_STUDENT_INTERNAL_MARK,[
                "staff" => new Staff(["id" => $GLOBALS['userId']]),
                "request" => $markEntryObj,
                "status" => StatusConstants::SUCCESS
            ]);
            if( !empty ( $insertionValues ) ){
                ExamUserMarkService::getInstance()->saveExamUserTotalMark($insertionValues);
            }
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
    
      /**
     * Save upload internal mark
     * @param $studentsMarkDetails 
     * @author Krishnajith
     */
    public function saveUploadedInternalMark($studentsMarkDetails) {
        try{
            $currentStaffId = $GLOBALS['userId'];
            foreach($studentsMarkDetails as $student){
                if(!empty($student->finalMark)){
                    if(!empty($student->studentId) && !empty($student->groupId)  && !empty($student->programId) && !empty($student->academicTermId) && !empty($student->academicPaperSubjectId) ){
                        if($student->finalMark == 'AB' ){
                            $insertionInternalMarkTableArray[] = " ('".$student->studentId."','".$student->groupId."','".$student->programId."', '".$student->academicTermId."','".$student->academicPaperSubjectId."',0,'ABSENT','".$currentStaffId."', utc_timestamp(), '".$currentStaffId."', utc_timestamp() ) ";
                            $request = new \stdClass();
                            $request->groupId = $student->groupId;
                            $request->studentId = $student->studentId;
                            $request->isDirty = 1;
                            $request->staffId = $GLOBALS['userId'];
                            $editHistoryLog[] = $request;
                            $log = new \stdClass;
                            // $log->oldMark = $student['oldInternalMarks'];
                            $log->newMark = $student->finalMark;
                            $log->remarks = 'upload internal mark';
                            $log->markType = "INTERNAL_MARK";
                            $log->actionTakenTime = date("d-m-Y h:i A");
                            $log->updatedStaffId = $currentStaffId;
                            $log->updatedStaffType = "EXAM_CONTROLLER";
                            $log->menuName = "UPLOAD_INTERNAL_MARKS";
                            $log = json_encode($log);
                            $id = SecurityUtils::getRandomString();
                            $insertionInternalMarkLogEntryObj = new \stdClass();
                            $insertionInternalMarkLogEntryObj->id = $id;
                            $insertionInternalMarkLogEntryObj->studentId = $student->studentId;
                            $insertionInternalMarkLogEntryObj->groupId = $student->groupId;
                            $insertionInternalMarkLogEntryObj->academicTermId = $student->academicTermId;
                            $insertionInternalMarkLogEntryObj->academicPaperSubjectId = $student->academicPaperSubjectId;
                            $insertionInternalMarkLogEntryObj->log = $log;
                            $insertionInternalMarkLogEntryObj->createdBy = $currentStaffId;
                            $insertionInternalMarkLogEntryObj->updatedBy = $currentStaffId;
                            $insertionInternalMarkLogTableArray[] = $insertionInternalMarkLogEntryObj;
                        }
                        
                        else if(is_numeric($student->finalMark)){
                            $insertionInternalMarkTableArray[] = " ('".$student->studentId."','".$student->groupId."','".$student->programId."', '".$student->academicTermId."','".$student->academicPaperSubjectId."','".$student->finalMark."','PRESENT','".$currentStaffId."', utc_timestamp(), '".$currentStaffId."', utc_timestamp() ) ";
                            $request = new \stdClass();
                            $request->groupId = $student->groupId;
                            $request->studentId = $student->studentId;
                            $request->isDirty = 1;
                            $request->staffId = $GLOBALS['userId'];
                            $editHistoryLog[] = $request;
                            $log = new \stdClass;
                            // $log->oldMark = $student['oldInternalMarks'];
                            $log->newMark = $student->finalMark;
                            $log->remarks = 'upload internal mark';
                            $log->markType = "INTERNAL_MARK";
                            $log->actionTakenTime = date("d-m-Y h:i A");
                            $log->updatedStaffId = $currentStaffId;
                            $log->updatedStaffType = "EXAM_CONTROLLER";
                            $log->menuName = "UPLOAD_INTERNAL_MARKS";
                            $log = json_encode($log);
                            $id = SecurityUtils::getRandomString();
                            $insertionInternalMarkLogEntryObj = new \stdClass();
                            $insertionInternalMarkLogEntryObj->id = $id;
                            $insertionInternalMarkLogEntryObj->studentId = $student->studentId;
                            $insertionInternalMarkLogEntryObj->groupId = $student->groupId;
                            $insertionInternalMarkLogEntryObj->academicTermId = $student->academicTermId;
                            $insertionInternalMarkLogEntryObj->academicPaperSubjectId = $student->academicPaperSubjectId;
                            $insertionInternalMarkLogEntryObj->log = $log;
                            $insertionInternalMarkLogEntryObj->createdBy = $currentStaffId;
                            $insertionInternalMarkLogEntryObj->updatedBy = $currentStaffId;
                            $insertionInternalMarkLogTableArray[] = $insertionInternalMarkLogEntryObj;
                        }
                    }
                }
            }
            if(! empty($insertionInternalMarkTableArray)){
                $this->insertStudentInternalMarks($insertionInternalMarkTableArray);
                $this->logger->info(Events::EC_SAVE_INTERNAL_MARK,[
                    "staff" => new Staff(["id" => $currentStaffId]),
                    "request" => $searchRequest,
                    "status" => StatusConstants::SUCCESS
                ]);
            }
            if(! empty($editHistoryLog)){
                StudentsOverAllMarkReportService::getInstance()->insertStudentEditStatus($editHistoryLog);
            }
            if(! empty($insertionInternalMarkLogTableArray)){
                $this->insertStudentMarksEditLog($insertionInternalMarkLogTableArray);
            }
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
     /**
     * get All Student Application for CA Improvement Make up test
     * @param $searchRequest 
     * @return $studentDetails 
     * @author Krishnajith
     */
    public function getCaMarkImprovementStudentApplications($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try
        {
            $studentDetails = [];
            $orderBy = " ORDER BY g.name ASC";
            $whereQuery = "";
            // this case not consider term checking after that db modification will update the term condition
            if(!empty($searchRequest->applicationId)) {
                $applicationIdString = is_array($searchRequest->applicationId) ? "'" . implode("','",$searchRequest->applicationId) . "'" : "'".$searchRequest->applicationId."'";
                $whereQuery .= " AND ecasd.properties->>'$.applicationId' IN ( $applicationIdString )";
            }
            if(!empty($searchRequest->courseTypeId)) {
                $courseTypeIdString = is_array($searchRequest->courseTypeId) ? "'" . implode("','",$searchRequest->courseTypeId) . "'" : "'".$searchRequest->courseTypeId."'";
                $whereQuery .= " AND p.course_type_id IN ( $courseTypeIdString )";
            }
            if(!empty($searchRequest->startYear)) {
                $startYearStrng = is_array($searchRequest->startYear) ? "'" . implode("','",$searchRequest->startYear) . "'" : "'".$searchRequest->startYear."'";
                $whereQuery .= " AND g.properties ->> '$.startYear' IN ( $startYearStrng )";
            }
            $query = " SELECT DISTINCT ecasd.studentID as studentId,
                            ecasd.amount,
                            ecasd.paid,
                            ecasd.properties,
                            spa.properties->>'$.registerNumber' as regNo,
                            sa.studentName,
                            g.id,
                            g.name as batchName
                    FROM ec_certificate_applied_student_details ecasd
                    INNER JOIN studentaccount sa ON sa.studentID = ecasd.studentID
                    INNER JOIN student_program_account spa ON spa.student_id = sa.studentID
                    INNER JOIN program p ON p.id = spa.current_program_id                 
                    INNER JOIN  `groups` g ON g.id = spa.current_batch_id
                    INNER JOIN group_members gm ON gm.groups_id = g.id AND  gm.members->>'$.studentId' = spa.id
                    WHERE 1=1 AND ecasd.paid = 1 ";
            $studentApplications = $this->executeQueryForList($query.$whereQuery.$orderBy);
            if(!empty($studentApplications)){
                if(!empty($searchRequest->subjectIds)) {
                    $subjectIdsString = is_array($searchRequest->subjectIds) ? "'" . implode("','",$searchRequest->subjectIds) . "'" : "'".$searchRequest->subjectIds."'";
                    $whereSubjectQuery .= " AND sub.id IN ( $subjectIdsString )";
                }
                $subjectQuery = " SELECT DISTINCT 
                            sub.id,
                            sub.code as code,
                            sub.name as name
                    FROM v4_ams_subject sub
                    WHERE 1=1 ";
                $subjects = $this->executeQueryForList($subjectQuery.$whereSubjectQuery);
                $selectedSubjects = [];
                foreach($subjects as $subject){
                    $selectedSubjects[$subject->id] = $subject;
                }
                if($searchRequest->applicationType == 'CA_MARKS'){
                    $searchRequest->caMark = true;
                    $searchRequest->makeUpTest = false;
                }
                else if($searchRequest->applicationType == 'MAKEUP_TEST'){
                    $searchRequest->caMark = false;
                    $searchRequest->makeUpTest = true;
                }
                else{
                    $searchRequest->caMark = true;
                    $searchRequest->makeUpTest = true;
                }
                foreach($studentApplications as $application){
                    $application->properties = json_decode($application->properties);
                    if($searchRequest->caMark){ 
                        if(!empty($application->properties->caMarkImpSubjects)){
                            foreach($application->properties->caMarkImpSubjects as $caMarkImpSubject){
                                if(in_array($caMarkImpSubject,$searchRequest->subjectIds)){
                                    $studentSubjectApplication =  new \stdClass;
                                    $studentSubjectApplication->regNo = $application->regNo;
                                    $studentSubjectApplication->studentName = $application->studentName;
                                    $studentSubjectApplication->batchName = $application->batchName;
                                    $studentSubjectApplication->subjectName =$selectedSubjects[$caMarkImpSubject]->code;
                                    $studentSubjectApplication->isMakeUp = false;
                                    $studentDetails[] = $studentSubjectApplication;
                                }
                            }
                        }
                    }
                    if($searchRequest->makeUpTest){
                        if(!empty($application->properties->caMakeUpTestSubjects)){
                            foreach($application->properties->caMakeUpTestSubjects as $caMakeUpTestSubjects){
                                if(in_array($caMakeUpTestSubjects,$searchRequest->subjectIds)){
                                    $studentSubjectApplication =  new \stdClass;
                                    $studentSubjectApplication->regNo = $application->regNo;
                                    $studentSubjectApplication->studentName = $application->studentName;
                                    $studentSubjectApplication->batchName = $application->batchName;
                                    $studentSubjectApplication->subjectName =$selectedSubjects[$caMakeUpTestSubjects]->code;
                                    $studentSubjectApplication->isMakeUp = true;
                                    $studentDetails[] = $studentSubjectApplication;
                                }
                            }
                        }
                    }
                }
            }
            
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $studentDetails;
    }
    
    /**
     * get print data for CA Improvement Make up test student report
     * @param $searchRequest 
     * @return $response 
     */
     public function getCaMarkImprovementStudentReport($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $request = new \stdClass;
            $request->courseTypeId = $searchRequest->courseTypeId;
            $request->startYear = $searchRequest->startYear;
            $request->academicTermId = $searchRequest->academicTermId;
            $request->subjectIds = $searchRequest->subjectIds;
            $request->applicationId = $searchRequest->applicationId;
            $request->applicationType = $searchRequest->applicationType;
            $studentList =  $this->getCaMarkImprovementStudentApplications($request);
            if(empty($studentList)){
                throw new ExamControllerException(ExamControllerException::NO_DETAILS_FOUND,"No Student Application(s)");
            }
            $templateName = "camark_makeup_test_students_report";
            $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/caMarkMakeUpTestReport/$templateName.twig"), [ 'students' => $studentList]);
            $prtContent = NULL;
            $prtContent .= '<html><head>';
            $prtContent .= "";
            $prtContent .= '</head><title>CA Mark Improvement / Make Up Test Students Report</title><body>';
            $prtContent .= $responseHtml;
            $prtContent .= '</body></html>';
            $options = array(
                'page-width'     => "297mm",
                'page-height'    => "210mm",
                'dpi'            => 96,
                'margin-top' => "10mm",
                'margin-left' => "10mm",
                'margin-right' => "10mm",
                'margin-bottom' => "10mm",
                // 'binary' => "/usr/local/bin/wkhtmltopdf", // For Mac
                'user-style-sheet' => realpath(DOCUMENT_ROOT . "/libcommon/bootstrap/css/bootstrap.min.css")
            );
            $programResult = new \stdClass;
            $programResult->printData = PdfUtil::renderPdf($prtContent, $options);
            $programResult->displayHtmlData = $responseHtml;
            
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $programResult;
    }
    
    
    
    
 
    
    
}