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 / 41
CRAP
0.00% covered (danger)
0.00%
0 / 2917
FinalConsolidatedReportService
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 41
198470.00
0.00% covered (danger)
0.00%
0 / 2917
 __construct
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 2
 getPassPercentageReport
0.00% covered (danger)
0.00%
0 / 1
272.00
0.00% covered (danger)
0.00%
0 / 99
 getAllStudentSemesterWiseMarkDetails
0.00% covered (danger)
0.00%
0 / 1
110.00
0.00% covered (danger)
0.00%
0 / 110
 getAllAcademicTerms
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 24
 getBatchesByAcademicTerm
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 48
 getStudentRankListForSelectedBatch
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 54
 getAllPasedStudentFinalRankListDetails
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 31
 getAllGroupDetailsByGroupIds
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 21
 getStudentCgpaReportByBatch
0.00% covered (danger)
0.00%
0 / 1
462.00
0.00% covered (danger)
0.00%
0 / 108
 getAllStudentSemesterAndOverallMarkDetails
0.00% covered (danger)
0.00%
0 / 1
90.00
0.00% covered (danger)
0.00%
0 / 96
 getOverallCgpaReportByBatch
0.00% covered (danger)
0.00%
0 / 1
506.00
0.00% covered (danger)
0.00%
0 / 119
 getAllStudentsOverallMarkDetails
0.00% covered (danger)
0.00%
0 / 1
90.00
0.00% covered (danger)
0.00%
0 / 71
 getYearWiseResultComparisonReport
0.00% covered (danger)
0.00%
0 / 1
156.00
0.00% covered (danger)
0.00%
0 / 82
 getSemesterWiseResultComparisonReport
0.00% covered (danger)
0.00%
0 / 1
156.00
0.00% covered (danger)
0.00%
0 / 83
 getAllStudentSubjectMarkDetails
0.00% covered (danger)
0.00%
0 / 1
1056.00
0.00% covered (danger)
0.00%
0 / 142
 getConsolidatedResultAnalysisReport
0.00% covered (danger)
0.00%
0 / 1
420.00
0.00% covered (danger)
0.00%
0 / 122
 getStudentPendingSubjectListReport
0.00% covered (danger)
0.00%
0 / 1
110.00
0.00% covered (danger)
0.00%
0 / 94
 getBatchesWithExamMonthYear
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 37
 getAllBatchesWithExamRegistrations
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 47
 getSupplimentaryStudentsResultNotificationDetails
0.00% covered (danger)
0.00%
0 / 1
1122.00
0.00% covered (danger)
0.00%
0 / 155
 getRegularStudentsResultNotificationDetails
0.00% covered (danger)
0.00%
0 / 1
702.00
0.00% covered (danger)
0.00%
0 / 131
 getFailedStudentsInRegularExamRegistrations
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 19
 getPassedStudentsInSupplyExamRegistrations
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 21
 getAllGradeScemesByCurriculum
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 46
 getFinalGradeSchemesByCurriculum
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 40
 getReportData
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 29
 saveReportData
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 34
 getCGPAGradeScemesByCurriculum
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 40
 getAllStudentConsolidatedSemesterAndOverallMarkDetails
0.00% covered (danger)
0.00%
0 / 1
72.00
0.00% covered (danger)
0.00%
0 / 86
 getFailedStudentList
0.00% covered (danger)
0.00%
0 / 1
210.00
0.00% covered (danger)
0.00%
0 / 133
 getProgramResultReport
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 17
 getGraduationBatchReport
0.00% covered (danger)
0.00%
0 / 1
2862.00
0.00% covered (danger)
0.00%
0 / 232
 getTranscriptMarksCard
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 7
 getSupplyExamMonthAndYearSemesterWise
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 41
 getStudentStatusReport
0.00% covered (danger)
0.00%
0 / 1
72.00
0.00% covered (danger)
0.00%
0 / 104
 getStudentCgpaReport
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 63
 getAllStudentSemesterWiseConsolidatedMarkDetails
0.00% covered (danger)
0.00%
0 / 1
72.00
0.00% covered (danger)
0.00%
0 / 103
 getStudentForRankCertificate
0.00% covered (danger)
0.00%
0 / 1
342.00
0.00% covered (danger)
0.00%
0 / 75
 generateStudentRankCertificate
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 49
 getRanksCalculated
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 37
 getStudentOverallMarkReport
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 65
<?php
namespace com\linways\ec\core\service;
use com\linways\ec\core\request\SearchRuleRequest;
use com\linways\ec\core\service\RuleService;
use com\linways\base\util\MakeSingletonTrait;
use com\linways\ec\core\exception\ExamControllerException;
use com\linways\core\ams\professional\service\ReligionService;
use com\linways\core\ams\professional\service\AdmissionService;
use com\linways\core\ams\professional\service\CampusTypeService;
use com\linways\base\util\TwigRenderer;
use com\linways\core\ams\professional\util\PdfUtil;
use com\linways\core\ams\professional\service\CommonService;
use com\linways\ec\core\service\ExamRegistrationService;
use com\linways\ec\core\request\SearchExamRegistrationRequest;
use com\linways\ec\core\service\ExamRegistrationSubjectService;
use com\linways\core\ams\professional\service\CourseTypeService;
use com\linways\core\ams\professional\util\CommonUtil;
use com\linways\core\ams\professional\constant\ExamType; 
use com\linways\core\ams\professional\dto\SettingsConstents;
use com\linways\base\util\SecurityUtils;
use com\linways\ec\core\service\GradeSchemeService;
use com\linways\ec\core\request\SearchExamRegistrationBatchRequest;
use com\linways\ec\core\constant\ExamRegistrationTypeConstants;
use com\linways\ec\core\dto\StudentMarkDetails;
use com\linways\ec\core\dto\exam\StudentDetails;
use com\linways\ec\core\dto\exam\AcademicTermMark;
use com\linways\ec\core\dto\exam\RegularExam;
use com\linways\ec\core\dto\exam\ExamSubject;
use com\linways\ec\core\mapper\FinalConsolidatedReportServiceMapper;
use com\linways\ec\core\service\ProgramResultGenerator\ProgramResultGenerator;
use com\linways\ec\core\service\CommonExamService;
use com\linways\ec\core\service\TranscriptMarkCardGenerator\TranscriptMarkCardGenerator;
use com\linways\core\ams\professional\service\AmsCustomFieldsService;
use com\linways\core\ams\professional\constant\AmsCustomFieldsEntities;
use com\linways\core\ams\professional\request\academic\SearchGroupRequest;
use com\linways\ec\core\service\GroupService as ECGroupService;
use com\linways\ec\core\service\StudentMarkListService;
use com\linways\ec\core\service\MarksCardService;
class FinalConsolidatedReportService extends BaseService
{
    use MakeSingletonTrait;
    private function __construct() {
        $this->mapper = FinalConsolidatedReportServiceMapper::getInstance()->getMapper();
    }
     /**
     * get Pass Percentage Report
     * @param $searchRequest 
     * @return $programResult 
     */
    public function getPassPercentageReport($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $request = new \stdClass;
            $additionalDetails = new \stdClass;
            $additionalDetails->collageName = $GLOBALS['COLLEGE_NAME'];
            $additionalDetails->batchName = "BATCH".$searchRequest->admissionYear;
            $request->courseTypeId = $searchRequest->courseTypeId;
            $request->academicTermId = $searchRequest->academicTermId;
            $request->admissionYear = $searchRequest->admissionYear;
            $additionalDetails->batchStartYear = $searchRequest->admissionYear;
            $courseType = CourseTypeService::getInstance()->getCourseTypesById ($searchRequest->courseTypeId);
            if($courseType->courseTypeMethod == "PG"){
                $additionalDetails->semesters = $this->getAllAcademicTerms(true);
            }
            else{
                $additionalDetails->semesters = $this->getAllAcademicTerms(false);
            }
            $batchDetails = [];
            $batchDetailsArray = [];
            $studentsDetails = $this->getAllStudentSemesterWiseMarkDetails($request);
            if(empty($studentsDetails)){
                throw new ExamControllerException(ExamControllerException::NO_STUDENTS_IN_THIS_EXAM_REGISTRATION,"No Student(s) Found");
            }
            else{
                $alreadyEnteredStudents = [];
                foreach($studentsDetails as $student){
                    $batchDetails[$student->groupId]->groupId = $student->groupId;
                    $batchDetails[$student->groupId]->groupName = $student->groupName;
                    $batchDetails[$student->groupId]->deptName = $student->deptName;
                    $batchDetails[$student->groupId]->departmentDescription = $student->departmentDescription;
                    foreach($student->academicTerms as $academicTerm){
                        $batchDetails[$student->groupId]->semesters[$academicTerm->id]->academicTermId = $academicTerm->id;
                        $batchDetails[$student->groupId]->semesters[$academicTerm->id]->academicTerm = $academicTerm->name;
                        $batchDetails[$student->groupId]->semesters[$academicTerm->id]->appeared++;
                        if($academicTerm->failedStatus == "PASSED"){
                            $batchDetails[$student->groupId]->semesters[$academicTerm->id]->passed++;
                        }
                        elseif($academicTerm->failedStatus == "FAILED"){
                            $batchDetails[$student->groupId]->semesters[$academicTerm->id]->failed++;
                        }
                    }
                    if($student->failedStatus == 'PASSED'){
                        $batchDetails[$student->groupId]->passed++;
                        $batchDetails[$student->groupId]->appeared++;
                    }
                    elseif($student->failedStatus == 'FAILED'){
                        $batchDetails[$student->groupId]->failed++;
                        $batchDetails[$student->groupId]->appeared++;
                    }
                }
                $batchDetailsArray = array_values($batchDetails);
                foreach($batchDetailsArray as $batch){
                    $batch->semesters = array_values($batch->semesters);
                }
                foreach($batchDetails as $batch){
                    $batch->aggregatePercentage =  round ( 100 * ($batch->appeared ? $batch->passed / $batch->appeared : 0 ), 2);
                    foreach($batch->semesters as $semester){
                        $semester->passPercetage =  round ( 100 * ($semester->appeared ? $semester->passed / $semester->appeared : 0 ), 2);
                    }
                }
                
            }
            if(empty($batchDetailsArray)){
                throw new ExamControllerException(ExamControllerException::NO_STUDENTS_IN_THIS_EXAM_REGISTRATION,"No Students Found");
            }
            else{
                $templateName = "ConsolidatedPassPercentageReport";
                $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/ConsolidatedReports/$templateName.twig"), [ 'batches'=>$batchDetailsArray ,'additionalDetails'=>$additionalDetails]);
                $prtContent = NULL;
                $prtContent .= '<html><head>';
                $prtContent .= "<style>
                    h6 {font-size: 26px;} .text-center { text-align: center;} .align-middle {vertical-align: middle;}; tr.noBorder td {border: 0;  border-collapse:collapse;}
                    table, th, td {border: 1px solid black;border-collapse: collapse;}
                    </style>";
                $prtContent .= '</head><title>Pass Percentage Report</title><body>';
                $prtContent .= $responseHtml;
                $prtContent .= '</body></html>';
                $totalWidth = 210;
                $totalHeight = 297;
                $options = array(
                    'page-width'     => $totalWidth."mm",
                    'page-height'    => $totalHeight."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->printData = PdfUtil::renderPdf($prtContent, $options);
            return  $programResult;
            }
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
     /**
     * get All Students (Semester Wise)Details
     * @param $searchRequest 
     * @return $studentDetails 
     */
    public function getAllStudentSemesterWiseMarkDetails($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try
        {
            $orderBy = " ORDER BY d.departmentDesc ASC, spa.properties->>'$.registerNumber' ASC";
            $whereQuery = "";
            if(!empty($searchRequest->courseTypeId)) {
                $whereQuery .= " AND p.course_type_id = '$searchRequest->courseTypeId'";
            }
            if(!empty($searchRequest->admissionYear)) {
                $whereQuery .= " AND g.properties ->> '$.startYear' = '$searchRequest->admissionYear'";
            }
            if(!empty($searchRequest->groupsId)) {
                $whereQuery .= " AND g.id = '$searchRequest->groupsId'";
            }
            // this groupIdList to check student current batch details 
            if(!empty($searchRequest->groupIdList)) {
                $groupIdString =  is_array($searchRequest->groupIdList) ? "'" . implode("','",$searchRequest->groupIdList) . "'" : "'".$searchRequest->groupIdList."'";
                $whereQuery .= " AND spa.current_batch_id IN($groupIdString)";
            }
            if(!empty($searchRequest->passedStudentsOnly)) {
                if($searchRequest->passedStudentsOnly == true){
                    $whereQuery .= " AND esmd.failed_status = 'PASSED'";
                }
            }
            if(!empty($searchRequest->examRegistrationIds)) {
                $examRegistrationIdString= "'" . implode("', '", $searchRequest->examRegistrationIds) . "'" ;
                $whereQuery .= " AND eer.id IN ($examRegistrationIdString)";
            }
            $query = "SELECT DISTINCT
                            sa.studentID as studentId,
                            sa.studentName,
                            spa.properties->>'$.registerNumber' as regNo,
                            g.id as groupId,
                            g.name as groupName,
                            g.properties ->> '$.startYear' as admissionYear,
                            g.properties ->> '$.finalTermId' as finalSem,
                            g.properties ->> '$.startYear' as startYear,
                            g.properties ->> '$.endYear' as endYear,
                            act.id as academicTermId,
                            act.name as academicTerm,
                            act.properties ->> '$.orderNo' as termOrderNo,
                            p.name as programName,
                            d.deptName,
                            d.departmentDesc as departmentDescription,
                            d.deptID,
                            esmd.sgpa as semesterSgpa,
                            esmd.credit as semesterCredit,
                            esmd.percentage as semesterPercentage, 
                            esmd.grade as semesterGrade,
                            esmd.failed_status as semesterFailedStatus,
                            ecmdcourse.failed_status as courseFailedStatus,
                            ecmdcourse.cgpa,
                            ecmdcourse.percentage as coursePercentage,
                            ecmdcourse.grade as courseGrade,
                            ecmdcourse.mark_details->>'$.latestExamMonth' as latestExamMonth,
                            ecmdcourse.mark_details->>'$.latestExamYear' as latestExamYear,
                            ecmdcourse.mark_details AS courseMarkDetails,
                            eers.cm_academic_paper_subjects_id as academicPaperSubjectId,
                            esmdsubcon.mark_details ->>'$.credit' AS subjectCredit,
                            esmdsubcon.failed_status AS subjectFailedStatus,
                            ct.course_Type as courseType,
                            esmd.mark_history as semesterMarkHistory,
                            esmdsubcon.mark_history as subjectMarkHistory,
                            eer.id as examRegId,
                            eerb.properties as examBatchProperties,
                            eserd.properties->>'$.isResultWithHeld' AS isResultWithHeld,
                            eer.type as examType,
                            spa.academic_status AS academicStatus
                        FROM
                            `groups` g
                        INNER JOIN program p 
                            ON p.id  = g.properties->>'$.programId'
                        INNER JOIN ec_exam_registration_batch eerb ON
                            eerb.groups_id = g.id
                        INNER JOIN ec_exam_registration_subject eers ON
                            eers.ec_exam_registration_batch_id = eerb.id
                        INNER JOIN ec_exam_registration eer ON
                            eer.id = eerb.ec_exam_registration_id
                        INNER JOIN ec_student_assessment_registration esar ON
                            esar.am_assessment_id = eers.am_assessment_id AND 
                            esar.ec_exam_registration_type = eer.type AND
                            ((CAST(esar.properties ->> '$.registrationStatus' AS CHAR) = 'REGISTERED' AND 
                            CAST(esar.properties ->> '$.feeStatus' AS CHAR) = 'PAID' ) OR 
                            CAST(esar.properties->>'$.studentAttendanceStatus' AS CHAR) = 'FE' AND
                            CAST(esar.properties->>'$.registrationStatus' AS CHAR) ='NOT_REGISTERED')
                        INNER JOIN studentaccount sa ON 
                            sa.studentID = esar.student_id
                        INNER JOIN ec_student_exam_registration_details eserd ON eserd.student_id = sa.studentID AND eserd.ec_exam_registration_id = eer.id 
                        INNER JOIN student_program_account spa ON 
                            spa.student_id  = esar.student_id  AND
                            spa.current_program_id = p.id 
                        INNER JOIN department d ON
                            d.deptID = g.properties ->> '$.departmentId'
                        INNER JOIN course_type ct ON
                            ct.courseTypeID = p.course_type_id
                        INNER JOIN  academic_term act ON 
                            act.id = CAST(eerb.properties ->> '$.academicTermId'AS CHAR)
                        INNER JOIN ec_semester_mark_details esmd ON
                            esmd.groups_id = eerb.groups_id AND esmd.academic_term_id = act.id AND esmd.student_id = sa.studentID 
                        LEFT JOIN  ec_course_mark_details ecmdcourse ON
                            ecmdcourse.groups_id = eerb.groups_id AND ecmdcourse.student_id = sa.studentID 
                        INNER JOIN ec_consolidated_subject_mark_details esmdsubcon ON
                            esmdsubcon.groups_id = eerb.groups_id AND esmdsubcon.cm_academic_paper_subjects_id = eers.cm_academic_paper_subjects_id AND esmdsubcon.student_id = sa.studentID 
                        WHERE 1=1 AND ( (eer.properties ->> '$.isHonorCourse' IS NULL OR eer.properties ->> '$.isHonorCourse' != '1') AND (eer.properties ->> '$.isMinorCourse' IS NULL OR eer.properties ->> '$.isMinorCourse' != '1'))";
             $studentDetails = $this->executeQueryForList($query.$whereQuery.$orderBy, $this->mapper[FinalConsolidatedReportServiceMapper::SEMESTER_WISE_MARK_DETAILS]);
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $studentDetails;
    }
     /**
     * get All Academic terms
     * @param $isPG 
     * @return $academisTerms 
     */
    private function getAllAcademicTerms($isPG = false) {
        try
        {
            $orderBy = "ORDER BY act.name";
            $whereQuery = "";
            if($isPG) {
                $whereQuery .= " AND act.name in ('s1','s2','s3','s4')";
            }
            else{
                $whereQuery .= " AND act.name in ('s1','s2','s3','s4','s5','s6')";
            }
            $query = "SELECT DISTINCT
                            act.id as academicTermId,
                            act.name as academicTerm
                        FROM
                            academic_term act
                        WHERE 1=1 ";
            $academisTerms = $this->executeQueryForList($query.$whereQuery.$orderBy);
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $academisTerms;
    }
     /**
     * get All Batches By Academic terms
     * @param $searchRequest 
     * @return $groups 
     */
    public function getBatchesByAcademicTerm($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $orderBy = "ORDER BY g.created_date DESC";
            $whereQuery = "";
            if(!empty($searchRequest->admissionYear)) {
                $whereQuery .= " AND g.properties ->> '$.startYear' = '$searchRequest->admissionYear'";
            }
            if(!empty($searchRequest->groupId)) {
                $groupIdString =  is_array($searchRequest->groupId) ? "'" . implode("','",$searchRequest->groupId) . "'" : "'".$searchRequest->groupId."'";
                $whereQuery .= " AND g.id IN($groupIdString)";
            }
            if(!empty($searchRequest->courseTypeId)) {
                $whereQuery .= " AND p.course_type_id = '$searchRequest->courseTypeId'";
            }
            $query = "SELECT DISTINCT
                            g.id,
                            g.name as groupName,
                            g.properties ->> '$.startYear' as batchStartYear,
                            g.properties ->> '$.endYear' as batchEndYear,
                            p.name as programName,
                            d.deptName,
                            d.departmentDesc as departmentDescription,
                            d.deptID,
                            deg.name as degreeName,
                            ct.typeName as courseTypeName,
                            ct.courseTypeID as courseTypeId
                        FROM
                            `groups` g
                        INNER JOIN department d ON
                            d.deptID = g.properties ->> '$.departmentId' 
                        INNER JOIN program p ON
                            p.id = CAST(g.properties ->> '$.programId' AS CHAR) 
                        INNER JOIN degree deg ON
                            deg.id = p.degree_id
                        INNER JOIN course_type ct ON
                            ct.courseTypeID = p.course_type_id
                        WHERE 1=1 AND g.`type` = 'BATCH' ";
            $groups = $this->executeQueryForList($query.$whereQuery.$orderBy);
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        foreach($groups as $group){
            $group->isSelected = false;
        }
        return $groups;
    }
      /**
     * get Student Rank List For Selected Batches
     * @param $searchRequest 
     * @return $programResult 
     */
    public function getStudentRankListForSelectedBatch($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $request = new \stdClass;
            $additionalDetails = new \stdClass;
            $additionalDetails->collageName = $GLOBALS['COLLEGE_NAME'];
            $courseType = CourseTypeService::getInstance()->getCourseTypesById ($searchRequest->courseTypeId);
            $additionalDetails->courseProgramName = $courseType->courseTypeMethod." - Program - ".$searchRequest->admissionYear;
            $request->considerFirstChanceStudentsOnly = $searchRequest->considerFirstChanceStudentsOnly;
            $additionalDetails->considerFirstChanceStudentsOnly = $searchRequest->considerFirstChanceStudentsOnly;
            $request->groupsIds = $searchRequest->groupsIds;
            $batchDetails =  $this->getAllGroupDetailsByGroupIds($request);
            foreach($batchDetails as $batch){
                $batchNames[] =  $batch->groupName;
            }
            $additionalDetails->batchName = implode(" , ",$batchNames);
            $studentsDetails = $this->getAllPasedStudentFinalRankListDetails($request);
            if(empty($studentsDetails)){
                throw new ExamControllerException(ExamControllerException::NO_STUDENTS_IN_THIS_EXAM_REGISTRATION,"No Student(s) Found");
            }
            else{
                $templateName = "ConsolidatedStudentRankListReport";
                $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/ConsolidatedReports/$templateName.twig"), [ 'students'=>$studentsDetails ,'additionalDetails'=>$additionalDetails]);
                $prtContent = NULL;
                $prtContent .= '<html><head>';
                $prtContent .= "<style>
                    h6 {font-size: 26px;} .text-center { text-align: center;} .align-middle {vertical-align: middle;}; tr.noBorder td {border: 0;  border-collapse:collapse;}
                    table, th, td {border: 1px solid black;border-collapse: collapse;}
                    </style>";
                $prtContent .= '</head><title>Student Rank List</title><body>';
                $prtContent .= $responseHtml;
                $prtContent .= '</body></html>';
                $totalWidth = 210;
                $totalHeight = 297;
                $options = array(
                    'page-width'     => $totalWidth."mm",
                    'page-height'    => $totalHeight."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->printData = PdfUtil::renderPdf($prtContent, $options);
            return  $programResult;
            }
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
    /**
     * get All Student Final Mark List Details
     * @param $searchRequest 
     * @return $groups 
     */
    private function getAllPasedStudentFinalRankListDetails($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $orderBy = " ORDER BY ecmd.mark_details->'$.cgpaWithoutGracemark' DESC";
            $whereQuery = "";
            if(!empty($searchRequest->groupsIds)) {
                $groupsIdsString= "'" . implode("', '", $searchRequest->groupsIds) . "'" ;
                $whereQuery .= " AND ecmd.groups_id IN ($groupsIdsString)";
            }
            if($searchRequest->considerFirstChanceStudentsOnly == 'true') {
                $whereQuery .= " AND ecmd.total_supply_attempt_count = 0";
            }
            $query = "SELECT DISTINCT
                            ecmd.student_id,
                            sa.studentName,
                            sa.regNo,
                            ecmd.cgpa,
                            ecmd.mark_details->>'$.cgpaWithoutGracemark' AS cgpaWithoutGracemark, 
                            ecmd.grade
                        FROM
                            ec_course_mark_details ecmd
                        INNER JOIN studentaccount sa ON 
                            sa.studentID = ecmd.student_id
                        
                        WHERE 1=1 AND ecmd.failed_status = 'PASSED'";
            $students = $this->executeQueryForList($query.$whereQuery.$orderBy);
        }
        
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $students;
    }
    /**
     * get All Group Details By Group Ids
     * @param $searchRequest 
     * @return $groups 
     */
    public function getAllGroupDetailsByGroupIds($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $whereQuery = "";
            if(!empty($searchRequest->groupsIds)) {
                $groupsIdsString= "'" . implode("', '", $searchRequest->groupsIds) . "'" ;
                $whereQuery .= " AND g.id IN ($groupsIdsString)";
            }
            $query = "SELECT DISTINCT
                            g.id,
                            g.name as groupName
                        FROM
                            `groups` g
                        WHERE 1=1 ";
            $groups = $this->executeQueryForList($query.$whereQuery);
        }
        
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $groups;
    }
     /**
     * get Student CGPA Report By Batch
     * @param $searchRequest 
     * @return $programResult 
     */
    public function getStudentCgpaReportByBatch($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $isShowSgpaInGetCgpaReports = CommonService::getInstance()->getSettings(SettingsConstents::EXAM_CONTROLLER, SettingsConstents::IS_SHOW_CGPA_REPORT_WITH_SGPA);
            $request = new \stdClass;
            $additionalDetails = new \stdClass;
            $additionalDetails->collageName = $GLOBALS['COLLEGE_NAME'];
            $request->courseTypeId = $searchRequest->courseTypeId;
            $request->admissionYear = $searchRequest->admissionYear;
            $request->groupId = $searchRequest->groupId;
            $request->isShowSgpa = $searchRequest->isShowSgpa;
            $additionalDetails->isShowSgpa = $searchRequest->isShowSgpa;
            $studentsDetails = $this->getAllStudentConsolidatedSemesterAndOverallMarkDetails($request);
            if(empty($studentsDetails)){
                throw new ExamControllerException(ExamControllerException::NO_STUDENTS_IN_THIS_EXAM_REGISTRATION,"No Student(s) Found");
            }
            else{
                $batchDetails =  $this->getBatchesByAcademicTerm($request);
                if($isShowSgpaInGetCgpaReports == "1" || $isShowSgpaInGetCgpaReports == true){
                    if($batchDetails[0]->degreeName == "BPED" || $batchDetails[0]->degreeName == "BLISC"){
                        $templateName = "StudentCgpaReportForBPEDAndPGBLISC"; 
                    }
                    else{
                        $templateName = "StudentCgpaReportByBatch";
                    }
                }
                else{
                    if($batchDetails[0]->courseTypeName == "PG"){
                        $templateName = "StudentCgpaReportByBatchTemplate_pg";
                    }
                    else{
                        $templateName = "StudentCgpaReportByBatchTemplate_ug";
                    }
                }
                $additionalDetails->batchName = reset($studentsDetails)->groupName;
                $additionalDetails->courseTypeId = reset($studentsDetails)->courseTypeId;
                foreach($studentsDetails as $student){
                    $student->roundOff = $student->admissionYear < 2019 ?  2 : 3;
                    $student->cgpa = $student->admissionYear < 2019 ?  round($student->cgpa,2) : round($student->cgpa,3);
                    if (0.5 < $student->cgpa && $student->cgpa <= 5.5) {
                        $student->cgpaPercentage = 40 + ($student->cgpa - 0.5) * 10;
                    }
                    else if ($student->cgpa > 5.5) {
                        $student->cgpaPercentage = 90 + ($student->cgpa - 5.5) * 20;
                    }
                    if ($batchDetails[0]->courseTypeName == "PG") {
                        if($batchDetails[0]->startYear >= 2019)
                        {
                            $student->cgpaPercentage = $student->cgpa * 20;
                        }
                        else
                        {
                            $student->cgpaPercentage = $student->cgpa * 25;
                        }
                    }
                    $student->overallPercentage = round($student->overallPercentage,2);
                    foreach($student->academicTerms as $academicTerm){
                        $academicTerm->sgpa = $student->admissionYear < 2019 ?  round($academicTerm->sgpa,2) : round($academicTerm->sgpa,3);
                        $academicTerm->percentage = round($academicTerm->percentage,2);
                        $academicTerm->examDateAndMonth =  $academicTerm->latestExamYear."-".$academicTerm->latestExamMonth;
                    }
                }
                
                if($additionalDetails->courseTypeId){
                    $courseType = CourseTypeService::getInstance()->getCourseTypesById ($additionalDetails->courseTypeId);
                    if($courseType->courseTypeMethod == "PG"){
                        $additionalDetails->semesters = $this->getAllAcademicTerms(true);
                    }
                    else{
                        $additionalDetails->semesters = $this->getAllAcademicTerms(false);
                    }
                }
            }
            if(empty($studentsDetails)){
                throw new ExamControllerException(ExamControllerException::NO_STUDENTS_IN_THIS_EXAM_REGISTRATION,"No Students Found");
            }
            else{
                $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/ConsolidatedReports/$templateName.twig"), [ 'students'=>$studentsDetails ,'additionalDetails'=>$additionalDetails]);
                $prtContent = NULL;
                $prtContent .= '<html><head>';
                $prtContent .= "<style>
                    h6 {font-size: 26px;} .text-center { text-align: center;} .align-middle {vertical-align: middle;}; tr.noBorder td {border: 0;  border-collapse:collapse;}
                    table, th, td {border: 1px solid black;border-collapse: collapse;}
                    </style>";
                $prtContent .= '</head><title>Pass Percentage Report</title><body>';
                $prtContent .= $responseHtml;
                $prtContent .= '</body></html>';
                $totalWidth = 210;
                $totalHeight = 297;
                $options = array(
                    'page-width'     => $totalWidth."mm",
                    'page-height'    => $totalHeight."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->printData = PdfUtil::renderPdf($prtContent, $options);
            return  $programResult;
            }
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
    /**
     * get All student semester and overall mark details
     * @param $searchRequest 
     * @return $studentDetails 
     */
    public function getAllStudentSemesterAndOverallMarkDetails($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try
        {
            $whereQuery = "";
            $orderBy = null;
            if(!empty($searchRequest->orderBy)) {
                if($searchRequest->orderBy == 'AdmissionYear'){
                    $orderBy = "ORDER BY g.properties ->> '$.startYear' ASC";
                }
            }
            else{
                $orderBy = "ORDER BY spa.properties->>'$.registerNumber' ASC";
            }
            if(!empty($searchRequest->groupId)) {
                $whereQuery .= " AND g.id = '$searchRequest->groupId'";
            }
            if(!empty($searchRequest->courseTypeId)) {
                $whereQuery .= " AND p.course_type_id = '$searchRequest->courseTypeId'";
            }
            if(!empty($searchRequest->admissionYears)) {
                $admissionYearsString= "'" . implode("', '", $searchRequest->admissionYears) . "'" ;
                $whereQuery .= " AND g.properties ->> '$.startYear' IN ($admissionYearsString)";
            }
            if(!empty($searchRequest->admissionYear)) {
                $whereQuery .= " AND g.properties ->> '$.startYear' = '$searchRequest->admissionYear'";
            }
            if(!empty($searchRequest->departmentId)) {
                $whereQuery .= " AND g.properties ->> '$.departmentId' = '$searchRequest->departmentId'";
            }
            $query = "SELECT DISTINCT
                        sa.studentID as studentId,
                        sa.studentName as studentName,
                        spa.properties->>'$.registerNumber' as regNo,
                        esmd.mark_details ->> '$.latestExamMonth' as examMonth,
                        esmd.mark_details ->> '$.latestExamYear' as examYear,
                        esmd.mark_details ->> '$.latestExamType' as examRegType,
                        g.id as groupId,
                        g.name as groupName,
                        g.properties ->> '$.startYear' as admissionYear,
                        g.properties ->> '$.departmentId' as departmentId,
                        p.course_type_id as courseTypeId,
                        act.id as academicTermId,
                        act.name as academicTerm,
                        act.properties ->> '$.orderNo' as senesterOrderNo,
                        esmd.sgpa as semesterSgpa,
                        esmd.percentage as semesterPercentage,
                        esmd.grade as semesterGrade,
                        esmd.failed_status as semesterFailedStatus,
                        esmd.mark_details->>'$.latestExamYear' as latestExamYear,
                        esmd.mark_details->>'$.latestExamMonth' as latestExamMonth,
                        esmd.mark_details as semesterMarkDetails,
                        ecmd.cgpa as cgpa,
                        ecmd.percentage as overallPercentage,
                        ecmd.grade as overallGrade,
                        ecmd.class as overallClass,
                        ecmd.total_marks as totalMark,
                        ecmd.failed_status as overallFailedStatus,
                        ecmd.mark_details as courseMarkDetails,
                        dept.deptName as departmentName
                    FROM
                        `groups` g
                    INNER JOIN program p ON 
                        p.id = CAST(g.properties ->> '$.programId' AS CHAR)
                    INNER JOIN ec_exam_registration_batch eerb ON
                        eerb.groups_id = g.id
                    INNER JOIN ec_exam_registration_subject eers ON
                        eers.ec_exam_registration_batch_id = eerb.id
                    INNER JOIN ec_exam_registration eer
                        ON eer.id = eerb.ec_exam_registration_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' AND 
                        CAST(esar.properties ->> '$.feeStatus' AS CHAR) = 'PAID' AND 
                        esar.ec_exam_registration_type = eer.type 
                    INNER JOIN studentaccount sa ON 
                        sa.studentID = esar.student_id
                    INNER JOIN student_program_account spa ON 
                        spa.student_id  = esar.student_id  AND
                        spa.current_program_id = p.id 
                    INNER JOIN  academic_term act ON 
                        act.id = CAST(eerb.properties ->> '$.academicTermId'AS CHAR)
                    INNER JOIN  department dept ON 
                        dept.deptID = g.properties ->> '$.departmentId'
                    INNER JOIN ec_semester_mark_details esmd ON
                        esmd.groups_id = eerb.groups_id AND esmd.academic_term_id = act.id AND esmd.student_id = sa.studentID 
                    INNER JOIN  ec_course_mark_details ecmd ON
                        ecmd.groups_id = eerb.groups_id AND ecmd.student_id = sa.studentID 
                    WHERE 1=1 ";
            $studentDetails = $this->executeQueryForList($query.$whereQuery.$orderBy);
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $studentDetails;
    }
     /**
     * get Overall CGPA Report By Batch
     * @param $searchRequest 
     * @return $programResult 
     */
    public function getOverallCgpaReportByBatch($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $request = new \stdClass;
            $request->courseTypeId = $searchRequest->courseTypeId;
            $request->admissionYear = $searchRequest->admissionYear;
            $request->groupId = $searchRequest->groupsId;
            $request->isGenderWiseSplitUp = $searchRequest->isGenderWiseSplitUp;
            $additionalDetails = new \stdClass;
            $additionalDetails->collageName = $GLOBALS['COLLEGE_NAME'];
            $gradeSchemeRequest = new \stdClass;
            $gradeSchemeRequest->groupId = $request->groupId;
            $gradeSchemeRequest->orderBy = "ASC";
            $grades = GradeSchemeService::getInstance()->getAllExamRegistrationGradeSchemes($gradeSchemeRequest);
            // $grades = $this->getFinalGradeSchemesByCurriculum($request);
            array_walk($grades, function($grade){
                $grade->properties = json_decode($grade->properties);
                $grade->class = $grade->properties->class;
            });
            if( $searchRequest->displayType == 'GRADE_WISE'){
                $headerNames = array_unique(array_column(array_filter($grades,function($g){return !$g->properties->failStatus;}),'name'));
            }
            else {
                $headerNames = array_unique(array_column(array_filter($grades,function($g){return !$g->properties->failStatus;}),'class'));
            }
            
            $overallReport = new \Stdclass;
            $overallReportGenderWie = [];
            $displayRows = [];
            $studentsDetailsArray = [];
            $studentsDetails = $this->getAllStudentsOverallMarkDetails($request);
            if(empty($studentsDetails)){
                throw new ExamControllerException(ExamControllerException::NO_STUDENTS_IN_THIS_EXAM_REGISTRATION,"No Student(s) Found");
            }
            else{
                $additionalDetails->batchName = $studentsDetails[0]->groupName;
                foreach($studentsDetails as $student){
                    $overallReportGenderWie[$student->studentGender]->enrolledStudents++;
                    $overallReport->enrolledStudents++;
                    if($student->overallFailedStatus == 'FAILED'){
                        $overallReportGenderWie[$student->studentGender]->failedStudents++;
                        $overallReport->failedStudents++;
                    }
                    else{
                        if( $searchRequest->displayType == 'GRADE_WISE'){
                            $overallReportGenderWie[$student->studentGender]->header[strtoupper($student->grade)]++;
                            $overallReport->header[strtoupper($student->grade)]++;
                        }
                        else {
                            $overallReportGenderWie[$student->studentGender]->header[strtoupper($student->class)]++;
                            $overallReport->header[strtoupper($student->class)]++;
                        }
                    }
                }
                $displayRows[0]->displayName = "No of Students Applied";
                $displayRows[0]->maleCount = $overallReportGenderWie['MALE']->enrolledStudents ? $overallReportGenderWie['MALE']->enrolledStudents : 0;
                $displayRows[0]->femaleCount = $overallReportGenderWie['FEMALE']->enrolledStudents ? $overallReportGenderWie['FEMALE']->enrolledStudents : 0;
                $displayRows[0]->malePercetage = "-";
                $displayRows[0]->femalePercetage = "-";
                $displayRows[0]->count = $overallReport->enrolledStudents ?? 0;
                $displayRows[0]->percetage = "-";
                foreach($headerNames as $header){
                    $displayObj = new \Stdclass;
                    $displayObj->displayName = "No of Students having ".$header;
                    $displayObj->maleCount = $overallReportGenderWie['MALE']->header[strtoupper($header)] ? $overallReportGenderWie['MALE']->header[strtoupper($header)] :0 ;
                    $displayObj->femaleCount = $overallReportGenderWie['FEMALE']->header[strtoupper($header)] ? $overallReportGenderWie['FEMALE']->header[strtoupper($header)] : 0;
                    $displayObj->malePercetage = round ( $overallReportGenderWie['MALE']->enrolledStudents ? 100 * $displayObj->maleCount / $overallReportGenderWie['MALE']->enrolledStudents : 0, 2)." %";
                    $displayObj->femalePercetage = round ( $overallReportGenderWie['FEMALE']->enrolledStudents ? 100 * $displayObj->femaleCount / $overallReportGenderWie['FEMALE']->enrolledStudents : 0, 2)." %";
                    $displayObj->count = $overallReport->header[strtoupper($header)] ?? 0;
                    $displayObj->percetage = round ( $overallReport->enrolledStudents ? 100 * $overallReport->header[strtoupper($header)] /$overallReport->enrolledStudents : 0, 2)." %";
                    $displayRows[] = $displayObj;
                }
                $displayObj = new \Stdclass;
                $displayObj->displayName = "No of Students Failed ";
                $displayObj->maleCount = $overallReportGenderWie['MALE']->failedStudents ? $overallReportGenderWie['MALE']->failedStudents : 0;
                $displayObj->femaleCount = $overallReportGenderWie['FEMALE']->failedStudents ? $overallReportGenderWie['FEMALE']->failedStudents : 0;
                $displayObj->malePercetage = round ( $overallReportGenderWie['MALE']->enrolledStudents ? 100 * $overallReportGenderWie['MALE']->failedStudents / $overallReportGenderWie['MALE']->enrolledStudents : 0, 2)." %";
                $displayObj->femalePercetage = round ( $overallReportGenderWie['FEMALE']->enrolledStudents ? 100 * $overallReportGenderWie['FEMALE']->failedStudents / $overallReportGenderWie['FEMALE']->enrolledStudents : 0, 2)." %";
                $displayObj->count = $overallReport->failedStudents ?? 0;
                $displayObj->percetage = round ( $overallReport->enrolledStudents ? 100 * $displayObj->count / $overallReport->enrolledStudents : 0, 2)." %";
                $displayRows[] = $displayObj;
                if($searchRequest->isGenderWiseSplitUp == 'true'){
                    $templateName = "OverallCgpaReportByBatchGenderWise";
                }
                else {
                    $templateName = "OverallCgpaReportByBatch";
                    
                }
            }
            if(empty($displayRows)){
                throw new ExamControllerException(ExamControllerException::NO_STUDENTS_IN_THIS_EXAM_REGISTRATION,"No Students Found");
            }
            else{
                $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/ConsolidatedReports/$templateName.twig"), [ 'datas'=>$displayRows ,'additionalDetails'=>$additionalDetails]);
                $prtContent = NULL;
                $prtContent .= '<html><head>';
                $prtContent .= "<style>
                    h6 {font-size: 26px;} .text-center { text-align: center;} .align-middle {vertical-align: middle;}; tr.noBorder td {border: 0;  border-collapse:collapse;}
                    table, th, td {border: 1px solid black;border-collapse: collapse;}
                    </style>";
                $prtContent .= '</head><title>Overall CGPA Report</title><body>';
                $prtContent .= $responseHtml;
                $prtContent .= '</body></html>';
                $totalWidth = 210;
                $totalHeight = 297;
                $options = array(
                    'page-width'     => $totalWidth."mm",
                    'page-height'    => $totalHeight."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->printData = PdfUtil::renderPdf($prtContent, $options);
            return  $programResult;
            }
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
    /**
     * get All student overall mark details
     * @param $searchRequest 
     * @return $studentDetails 
     */
    public function getAllStudentsOverallMarkDetails($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try
        {
            $whereQuery = "";
            $monthYearQueryString = [];
            if(!empty($searchRequest->groupId)) {
                $groupIdString = is_array($searchRequest->groupId) ? "'" . implode("','",$searchRequest->groupId) . "'" : "'".$searchRequest->groupId."'";
                $whereQuery .= " AND g.id IN ( $groupIdString )";
            }
            if(!empty($searchRequest->studentIds)) {
                $studentIdString= "'" . implode("', '", $searchRequest->studentIds) . "'" ;
                $whereQuery .= " AND sa.studentID IN ($studentIdString)";
            }
            if(!empty($searchRequest->passedStudentsOnly)) {
                if($searchRequest->passedStudentsOnly == true){
                    $whereQuery .= " AND ecmd.failed_status = 'PASSED'";
                }
            }
            if(!empty($searchRequest->lastExamMonthYears)) {
                $whereQuery .= " AND (";
                foreach($searchRequest->lastExamMonthYears as $examMonthYear){
                    $monthYearQueryString[] = " ( ecmd.mark_details ->> '$.lastExamYear' = '$examMonthYear->year' AND ecmd.mark_details ->> '$.lastExamMonth' = '$examMonthYear->month' )";
                }
                $whereQuery .= implode(" OR", $monthYearQueryString);
                $whereQuery .= " ) ";
            }
            $query = "SELECT DISTINCT
                        sa.studentID as studentId,
                        sa.studentName,
                        sa.regNo,
                        sa.studentGender,
                        ecmd.mark_details ->> '$.latestExamMonth' as examMonth,
                        ecmd.mark_details ->> '$.latestExamYear' as examYear,
                        ecmd.mark_details ->> '$.latestExamType' as examRegType,                        
                        g.name as groupName,
                        ecmd.cgpa as cgpa,
                        ecmd.percentage as overallPercentage,
                        ecmd.grade as grade,
                        ecmd.class as class,
                        ecmd.mark_details as markDetails,
                        ecmd.total_marks as totalMark,
                        ecmd.failed_status as overallFailedStatus
                    FROM
                        `groups` g
                    INNER JOIN ec_exam_registration_batch eerb ON
                        eerb.groups_id = g.id
                    INNER JOIN ec_exam_registration eer
                        ON eer.id = eerb.ec_exam_registration_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 esar.ec_exam_registration_type = eer.type
                        AND CAST(esar.properties ->> '$.registrationStatus' AS CHAR) = 'REGISTERED'
                        AND CAST(esar.properties ->> '$.feeStatus' AS CHAR) = 'PAID'
                    INNER JOIN studentaccount sa ON
                        sa.studentID = esar.student_id
                    INNER JOIN ec_course_mark_details ecmd ON
                        ecmd.groups_id = eerb.groups_id
                        AND ecmd.student_id = sa.studentID
                        AND ecmd.groups_id = g.id 
                    WHERE 1=1 
                    $whereQuery GROUP BY ecmd.id";
            $studentDetails = $this->executeQueryForList($query);
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $studentDetails;
    }
     /**
     * get Year Wise Result Comparison
     * @param $searchRequest 
     * @return $programResult 
     */
    public function getYearWiseResultComparisonReport($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $request = new \stdClass;
            $additionalDetails = new \stdClass;
            $additionalDetails->collageName = $GLOBALS['COLLEGE_NAME'];
            $request->courseTypeId = $searchRequest->courseTypeId;
            $request->admissionYears = $searchRequest->admissionYears;
            $request->departmentId = $searchRequest->departmentId;
            $request->orderBy = "AdmissionYear";
            $courseType = CourseTypeService::getInstance()->getCourseTypesById ($searchRequest->courseTypeId);
            if($courseType->courseTypeMethod == "PG"){
                $additionalDetails->semesters = $this->getAllAcademicTerms(true);
            }
            else{
                $additionalDetails->semesters = $this->getAllAcademicTerms(false);
            }
            $yearWiseComparisonDetails = [];
            $studentsDetails = $this->getAllStudentSemesterAndOverallMarkDetails($request);
            if(empty($studentsDetails)){
                throw new ExamControllerException(ExamControllerException::NO_REPORTS_DETAILS_FOUND,"No Details Found");
            }
            else{
                $templateName = "YearWiseResultComparisonReport";
                foreach($studentsDetails as $student){
                    $yearWiseComparisonDetails[$student->admissionYear]->admissionYear = $student->admissionYear;
                    $yearWiseComparisonDetails[$student->admissionYear]->semesters[$student->academicTermId]->academicTermId = $student->academicTermId;
                    $yearWiseComparisonDetails[$student->admissionYear]->semesters[$student->academicTermId]->academicTerm = $student->academicTerm;
                    $yearWiseComparisonDetails[$student->admissionYear]->semesters[$student->academicTermId]->appeared++;
                    if($student->semesterFailedStatus == 'PASSED'){
                        $yearWiseComparisonDetails[$student->admissionYear]->semesters[$student->academicTermId]->passed++;
                    }
                    elseif($student->semesterFailedStatus == 'FAILED'){
                        $yearWiseComparisonDetails[$student->admissionYear]->semesters[$student->academicTermId]->failed++;
                    }
                }
                $yearWiseComparisonDetails = array_values($yearWiseComparisonDetails);
                foreach($yearWiseComparisonDetails as $yearWiseDetails){
                    $yearWiseDetails->semesters = array_values($yearWiseDetails->semesters);
                }
                foreach($yearWiseComparisonDetails as $yearWiseDetails){
                    foreach($yearWiseDetails->semesters as $semester){
                        $semester->passPercetage =  round ( ( 100 * $semester->passed / ($semester->appeared ? $semester->appeared : 0 )), 2);
                    }
                }
            }
            if(empty($yearWiseComparisonDetails)){
                throw new ExamControllerException(ExamControllerException::NO_REPORTS_DETAILS_FOUND,"No Details Found");
            }
            else{
                $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/ConsolidatedReports/$templateName.twig"), [ 'yearWiseDetails'=>$yearWiseComparisonDetails ,'additionalDetails'=>$additionalDetails]);
                $prtContent = NULL;
                $prtContent .= '<html><head>';
                $prtContent .= "<style>
                    h6 {font-size: 26px;} .text-center { text-align: center;} .align-middle {vertical-align: middle;}; tr.noBorder td {border: 0;  border-collapse:collapse;}
                    table, th, td {border: 1px solid black;border-collapse: collapse;}
                    </style>";
                $prtContent .= '</head><title>Year Wise Result Comparison Report</title><body>';
                $prtContent .= $responseHtml;
                $prtContent .= '</body></html>';
                $totalWidth = 210;
                $totalHeight = 297;
                $options = array(
                    'page-width'     => $totalWidth."mm",
                    'page-height'    => $totalHeight."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->printData = PdfUtil::renderPdf($prtContent, $options);
            return  $programResult;
            }
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
    /**
     * get Semester Wise Result Comparison
     * @param $searchRequest 
     * @return $programResult 
     */
    public function getSemesterWiseResultComparisonReport($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $request = new \stdClass;
            $additionalDetails = new \stdClass;
            $additionalDetails->collageName = $GLOBALS['COLLEGE_NAME'];
            $request->courseTypeId = $searchRequest->courseTypeId;
            $request->admissionYears = $searchRequest->admissionYears;
            $request->departmentId = $searchRequest->departmentId;
            $request->academicTermId = $searchRequest->academicTermId;
            $request->orderBy = "";
            foreach($searchRequest->admissionYears as $admissionYear){
                $admissionYearObj = new \stdClass;
                $admissionYearObj->admissionYear = $admissionYear;
                $additionalDetails->admissionYears[] = $admissionYearObj;
            }
            $subjectWiseComparisonDetails = [];
            $studentsDetails = $this->getAllStudentSubjectMarkDetails($request);
            if(empty($studentsDetails)){
                throw new ExamControllerException(ExamControllerException::NO_REPORTS_DETAILS_FOUND,"No Details Found");
            }
            else{
                $templateName = "SubjectWiseResultComparisonReport";
                foreach($studentsDetails as $student){
                    $additionalDetails->academicTerm = $student->academicTerm;
                    $subjectWiseComparisonDetails[$student->academicPaperSubjectId]->academicPaperSubjectId = $student->academicPaperSubjectId;
                    $subjectWiseComparisonDetails[$student->academicPaperSubjectId]->subjectCode = $student->subjectCode;
                    $subjectWiseComparisonDetails[$student->academicPaperSubjectId]->subjectName = $student->subjectName;
                    $subjectWiseComparisonDetails[$student->academicPaperSubjectId]->admissionYears[$student->admissionYear]->admissionYear = $student->admissionYear;
                    $subjectWiseComparisonDetails[$student->academicPaperSubjectId]->admissionYears[$student->admissionYear]->appeared++;
                    if($student->failedStatus == 'PASSED'){
                        $subjectWiseComparisonDetails[$student->academicPaperSubjectId]->admissionYears[$student->admissionYear]->passed++;
                    }
                    else if($student->failedStatus == 'FAILED'){
                        $subjectWiseComparisonDetails[$student->academicPaperSubjectId]->admissionYears[$student->admissionYear]->failed++;
                    }
                }
                $subjectWiseComparisonDetails = array_values($subjectWiseComparisonDetails);
                foreach($subjectWiseComparisonDetails as $yearWiseDetails){
                    $yearWiseDetails->admissionYears = array_values($yearWiseDetails->admissionYears);
                }
                foreach($subjectWiseComparisonDetails as $yearWiseDetails){
                    foreach($yearWiseDetails->admissionYears as $admissionYear){
                        $admissionYear->passPercetage =  round ( ( 100 * $admissionYear->passed / ($admissionYear->appeared ? $admissionYear->appeared : 0 )), 2);
                    }
                }
            }
            if(empty($subjectWiseComparisonDetails)){
                throw new ExamControllerException(ExamControllerException::NO_REPORTS_DETAILS_FOUND,"No Details Found");
            }
            else{
                $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/ConsolidatedReports/$templateName.twig"), [ 'subjectWiseDetails'=>$subjectWiseComparisonDetails ,'additionalDetails'=>$additionalDetails]);
                $prtContent = NULL;
                $prtContent .= '<html><head>';
                $prtContent .= "<style>
                    h6 {font-size: 26px;} .text-center { text-align: center;} .align-middle {vertical-align: middle;}; tr.noBorder td {border: 0;  border-collapse:collapse;}
                    table, th, td {border: 1px solid black;border-collapse: collapse;}
                    </style>";
                $prtContent .= '</head><title>Semester Wise Result Comparison Report</title><body>';
                $prtContent .= $responseHtml;
                $prtContent .= '</body></html>';
                $totalWidth = 210;
                $totalHeight = 297;
                $options = array(
                    'page-width'     => $totalWidth."mm",
                    'page-height'    => $totalHeight."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->printData = PdfUtil::renderPdf($prtContent, $options);
            return  $programResult;
            }
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
    
     /**
     * get All student Subject mark details
     * @param $searchRequest 
     * @return $studentDetails 
     */
    public function getAllStudentSubjectMarkDetails($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        if(!empty($searchRequest->academicPaperSubjectIdUnique) && !is_array($searchRequest->academicPaperSubjectIdUnique)){
            $searchRequest->academicPaperSubjectIdUnique = stripslashes($searchRequest->academicPaperSubjectIdUnique);
        }
        try{
            $whereQuery = "";
            $monthYearQueryString = [];
            $orderBy = null;
            if(!empty($searchRequest->orderBy)) {
                if($searchRequest->orderBy == 'AdmissionYear'){
                    $orderBy = "ORDER BY g.properties ->> '$.startYear' ASC";
                }
                elseif($searchRequest->orderBy == 'REGISTER_NO'){
                    $orderBy = "ORDER BY spa.properties->>'$.registerNumber' ASC";
                }  
            }
           
            if(!empty($searchRequest->groupId)) {
                $whereQuery .= " AND g.id = '$searchRequest->groupId'";
            }
            if(!empty($searchRequest->examMonthYears)) {
                $whereQuery .= " AND (";
                foreach($searchRequest->examMonthYears as $examMonthYear){
                    $monthYearQueryString[] = " ( eer.properties ->> '$.examYear' = '$examMonthYear->year' AND eer.properties ->> '$.examMonth' = '$examMonthYear->month' )";
                }
                $whereQuery .= implode(" OR", $monthYearQueryString);
                $whereQuery .= " ) ";
            }
            if(!empty($searchRequest->passedStudentsOnly)) {
                if($searchRequest->passedStudentsOnly){
                    $whereQuery .= " AND esmd.failed_status = 'PASSED'";
                }
            }
            if(!empty($searchRequest->failedStudentsOnly)) {
                if($searchRequest->failedStudentsOnly){
                    $whereQuery .= " AND esmd.failed_status = 'FAILED'";
                }
            }
            if(!empty($searchRequest->consolidatedFailedStudentsOnly)) {
                if($searchRequest->consolidatedFailedStudentsOnly){
                    $whereQuery .= " AND ecsmd.failed_status = 'FAILED'";
                }
            }
            if(!empty($searchRequest->courseTypeId)) {
                $whereQuery .= " AND p.course_type_id = '$searchRequest->courseTypeId'";
            }
            if(!empty($searchRequest->admissionYears)) {
                $admissionYearsString= is_array($searchRequest->admissionYears) ? "'" . implode("','",$searchRequest->admissionYears) . "'" : "'".$searchRequest->admissionYears."'";
                $whereQuery .= " AND g.properties ->> '$.startYear' IN ($admissionYearsString)";
            }
            if(!empty($searchRequest->departmentId)) {
                $whereQuery .= " AND g.properties ->> '$.departmentId' = '$searchRequest->departmentId'";
            }
            if(!empty($searchRequest->academicTermId)) {
                $academicTermIdString =  is_array($searchRequest->academicTermId) ? "'" . implode("','",$searchRequest->academicTermId) . "'" : "'".$searchRequest->academicTermId."'";
                $whereQuery .= " AND act.id IN($academicTermIdString)";
            }
            if(!empty($searchRequest->religionId)) {
                $whereQuery .= " AND sa.religionID = '$searchRequest->religionId'";
            }
            if(!empty($searchRequest->reservationId)) {
                $whereQuery .= " AND sa.reservationID = '$searchRequest->reservationId'";
            }
            if(!empty($searchRequest->campusTypeId)) {
                $whereQuery .= " AND sa.campus_type_id = '$searchRequest->campusTypeId'";
            }
            if(!empty($searchRequest->gender)) {
                $whereQuery .= " AND sa.studentGender = '$searchRequest->gender'";
            }
            if(!empty($searchRequest->examRegistrationType)) {
                $whereQuery .= " AND eer.type = '$searchRequest->examRegistrationType'";
            }
            if(!empty($searchRequest->academicPaperSubjectId)) {
                $academicPaperSubjectIdString= is_array($searchRequest->academicPaperSubjectId) ? "'" . implode("','",$searchRequest->academicPaperSubjectId) . "'" : "'".$searchRequest->academicPaperSubjectId."'";
                $whereQuery .= " AND aps.id IN ($academicPaperSubjectIdString)";
            }
            if(!empty($searchRequest->academicPaperSubjectIdUnique)) {
                $whereQuery .= " AND aps.id IN ($searchRequest->academicPaperSubjectIdUnique)";
            }
            if(!empty($searchRequest->groupId)) {
                $groupIdString= is_array($searchRequest->groupId) ? "'" . implode("','",$searchRequest->groupId) . "'" : "'".$searchRequest->groupId."'";
                $whereQuery .= " AND g.id IN ($groupIdString)";
            }
            $query = "SELECT DISTINCT
                        sa.studentID as studentId,
                        sa.studentName,
                        spa.properties->>'$.registerNumber' as regNo,
                        sa.studentEmail,
                        sa.studentPhone,
                        g.id as groupId,
                        g.name as groupName,
                        act.id as academicTermId,
                        act.name as academicTerm,
                        g.properties ->> '$.startYear' as admissionYear,
                        eerb.ec_exam_registration_id as examRegistrationId,
                        eers.cm_academic_paper_subjects_id as academicPaperSubjectId,
                        eerb.properties ->> '$.publishingStartDate' as publishingDate,
                        s.id as subjectId,
                        s.code as subjectCode,
                        s.name as subjectName,
                        esmd.failed_status as failedStatus,
                        esmd.no_of_chances_taken as attemptCount,
                        ecsmd.failed_status as consolidatedFailedStatus
                    FROM
                        `groups` g
                    INNER JOIN ec_exam_registration_batch eerb ON
                        eerb.groups_id = g.id
                    INNER JOIN ec_exam_registration_subject eers ON
                        eers.ec_exam_registration_batch_id = eerb.id
                    INNER JOIN ec_exam_registration eer ON
                        eer.id = eerb.ec_exam_registration_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' AND 
                        CAST(esar.properties ->> '$.feeStatus' AS CHAR) = 'PAID' AND 
                        esar.ec_exam_registration_type = eer.type
                    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 AND 
                        spa.properties->>'$.academicStatus' IN ('ACTIVE','COMPLETED')
                    INNER JOIN studentaccount sa ON 
                        sa.studentID = esar.student_id
                    INNER JOIN  cm_academic_paper_subjects aps ON 
                        eers.cm_academic_paper_subjects_id = aps.id
                    INNER JOIN  v4_ams_subject s ON 
                        aps.ams_subject_id = s.id
                    INNER JOIN  academic_term act ON 
                        act.id = CAST(eerb.properties ->> '$.academicTermId'AS CHAR) 
                    INNER JOIN ec_subject_mark_details esmd ON
                        esmd.ec_exam_registration_id = eerb.ec_exam_registration_id AND esmd.groups_id = eerb.groups_id AND esmd.cm_academic_paper_subjects_id = eers.cm_academic_paper_subjects_id AND esmd.student_id = sa.studentID 
                    INNER JOIN ec_consolidated_subject_mark_details ecsmd ON
                        ecsmd.groups_id = eerb.groups_id AND ecsmd.cm_academic_paper_subjects_id = eers.cm_academic_paper_subjects_id AND ecsmd.student_id = sa.studentID 
                    WHERE 1=1 ";
            $studentDetails = $this->executeQueryForList($query.$whereQuery.$orderBy);
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $studentDetails;
    }
    /**
     * get Consolidated Result Analysis Report
     * @param $searchRequest 
     * @return $programResult 
     */
    public function getConsolidatedResultAnalysisReport($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $request = new \stdClass;
            $additionalDetails = new \stdClass;
            $additionalDetails->collageName = $GLOBALS['COLLEGE_NAME'];
            $additionalDetails->admissionYear = $searchRequest->admissionYear;
            $request->courseTypeId = $searchRequest->courseTypeId;
            $request->admissionYear = $searchRequest->admissionYear;
            $courseType = CourseTypeService::getInstance()->getCourseTypesById ($searchRequest->courseTypeId);
            $additionalDetails->couseType = $courseType->courseTypeMethod;
            $additionalDetails->collegeData = CommonExamService::getInstance()->getCollegeDetails();
            $gradeSchemes = $this->getAllGradeScemesByCurriculum($request);
            foreach($gradeSchemes as $gradeScheme){
                $gradeScheme->properties = json_decode($gradeScheme->properties);
                $gradeScheme->className = $gradeScheme->properties->class;
                if($gradeScheme->className){
                    $gradeScheme->grade = $gradeScheme->name;
                    $classNames[strtoupper($gradeScheme->className)] = strtoupper($gradeScheme->className);
                    $classHeaderNames[strtoupper($gradeScheme->className)] = strtoupper($gradeScheme->grade);
                }
            }
            $uniqueClassNames= array_unique($classNames);
            $classHeaderNames= array_unique($classHeaderNames);
            $additionalDetails->uniqueClassNames = $uniqueClassNames;
            $additionalDetails->classHeaderNames = $classHeaderNames;
            $departmentWiseDetails = [];
            $batchWiseDetails = [];
            $studentsDetails = $this->getAllStudentSemesterAndOverallMarkDetails($request);
            if(empty($studentsDetails)){
                throw new ExamControllerException(ExamControllerException::NO_REPORTS_DETAILS_FOUND,"No Details Found");
            }
            else{
                $searchRuleRequest = new SearchRuleRequest;
                $searchRuleRequest->name = "CONSOLIDATED_RESULT_ANALYSIS_RULE";
                $rule = reset(RuleService::getInstance()->searchRule($searchRuleRequest))->rule;
                $templateNameConst = $rule->templateName;
                $templateName = $templateNameConst ==  'BATCH_WISE' ? "ConsolidatedResultAnalysisReportBatchWise" : "ConsolidatedResultAnalysisReport";
                foreach($studentsDetails as $student){
                    $batchWiseDetails[$student->groupId]->groupId = $student->groupId;
                    $batchWiseDetails[$student->groupId]->name = $student->groupName;
                    $batchWiseDetails[$student->groupId]->totalCount++;
                    $batchWiseDetails[$student->groupId]->appeared++;
                    if($student->overallFailedStatus == 'FAILED'){
                        $batchWiseDetails[$student->groupId]->failed++;
                    }
                    else if($student->overallFailedStatus == 'PASSED'){
                        $batchWiseDetails[$student->groupId]->passed++;
                    }
                    $batchWiseDetails[$student->groupId]->class[$uniqueClassNames[strtoupper($student->overallClass)]]++;
                    $batchWiseDetails[$student->groupId]->className = $student->overallClass;
                }
                $batchWiseDetails = array_values($batchWiseDetails); 
                foreach($batchWiseDetails as $batchWiseDetail){
                    $batchWiseDetail->totalPassPercent =  round ( ( 100 * $batchWiseDetail->passed / ($batchWiseDetail->appeared ? $batchWiseDetail->appeared : 0 )), 2);
                }
                
                foreach($batchWiseDetails as $batch){
                    $totalResult->totalRegistered += $batch->totalCount;
                    $totalResult->totalAppeared += $batch->appeared;
                    $totalResult->totalPassed +=  $batch->passed;
                    foreach($batch->class as $class){
                        $totalResult->class[$uniqueClassNames[strtoupper($batch->className)]] += $class;
                    }
                    
                    $totalResult->totalPassPercent = $totalResult->totalAppeared? round(($totalResult->totalPassed / $totalResult->totalAppeared) * 100,2) : 0;
                    $totalResult->totalPassPercent = sprintf("%.2f", $totalResult->totalPassPercent);
                }
                $batchWiseResultAnaysis->finalResult = $totalResult;
                $batchWiseResultAnaysis->batches = $batchWiseDetails;
                foreach($studentsDetails as $student){
                    $departmentWiseDetails[$student->departmentId]->departmentId = $student->departmentId;
                    $departmentWiseDetails[$student->departmentId]->departmentName = $student->departmentName;
                    $departmentWiseDetails[$student->departmentId]->departmentId = $student->departmentId;
                    $departmentWiseDetails[$student->departmentId]->appeared++;
                    if($student->overallFailedStatus == 'FAILED'){
                        $departmentWiseDetails[$student->departmentId]->failed++;
                    }
                    else if($student->overallFailedStatus == 'PASSED'){
                        $departmentWiseDetails[$student->departmentId]->passed++;
                        $departmentWiseDetails[$student->departmentId]->class[$uniqueClassNames[strtoupper($student->overallClass)]]++;
                    }
                }
                $departmentWiseDetails = array_values($departmentWiseDetails); 
                foreach($departmentWiseDetails as $departmentWiseDetail){
                    $departmentWiseDetail->passPercetage =  round ( ( 100 * $departmentWiseDetail->passed / ($departmentWiseDetail->appeared ? $departmentWiseDetail->appeared : 0 )), 2);
                }
            }
            if(empty($departmentWiseDetails)){
                throw new ExamControllerException(ExamControllerException::NO_REPORTS_DETAILS_FOUND,"No Details Found");
            }
            else{
                $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/ConsolidatedReports/$templateName.twig"), [ 'departmentWiseDetails'=>$departmentWiseDetails ,'additionalDetails'=>$additionalDetails,'batchWiseResultAnaysis'=>$batchWiseResultAnaysis]);
                $prtContent = NULL;
                $prtContent .= '<html><head>';
                $prtContent .= "<style>
                    h6 {font-size: 26px;} .text-center { text-align: center;} .align-middle {vertical-align: middle;}; tr.noBorder td {border: 0;  border-collapse:collapse;}
                    table, th, td {border: 1px solid black;border-collapse: collapse;}
                    </style>";
                $prtContent .= '</head><title>Consilidated Result Analysis</title><body>';
                $prtContent .= $responseHtml;
                $prtContent .= '</body></html>';
                $totalWidth = 210;
                $totalHeight = 297;
                $options = array(
                    'page-width'     => $totalWidth."mm",
                    'page-height'    => $totalHeight."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->printData = PdfUtil::renderPdf($prtContent, $options);
            return  $programResult;
            }
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
     /**
     * get Consolidated Result Analysis Report
     * @param $searchRequest 
     * @return $programResult 
     */
    public function getStudentPendingSubjectListReport($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $request = new \stdClass;
            $additionalDetails = new \stdClass;
            $additionalDetails->collageName = $GLOBALS['COLLEGE_NAME'];
            $request->departmentId = $searchRequest->departmentId;
            $request->groupId = $searchRequest->groupId;
            $request->religionId = $searchRequest->religionId;
            $request->reservationId = $searchRequest->reservationId;
            $request->campusTypeId = $searchRequest->campusTypeId;
            $request->gender = $searchRequest->gender;
            $request->failedStudentsOnly = true;
            $academicTermIdsArray = [];
            $batchDetails =  $this->getBatchesByAcademicTerm($request);
            if(empty($batchDetails)){
                throw new ExamControllerException(ExamControllerException::NO_EXAM_REGISTRATION_BATCH_FOUND,"No Batches Assigned");
            }
            $courseType = CourseTypeService::getInstance()->getCourseTypesById ($batchDetails[0]->courseTypeId);
            if($courseType->courseTypeMethod == "PG"){
                $additionalDetails->semesters = $this->getAllAcademicTerms(true);
            }
            else{
                $additionalDetails->semesters = $this->getAllAcademicTerms(false);
            }
            foreach($additionalDetails->semesters as $semester){
                $academicTermIdsArray[$semester->academicTermId]=$semester->academicTermId;
                $request->academicTermId[]=$semester->academicTermId;
            }
            $studentPendingSubjectList = [];
            $studentsDetails = $this->getAllStudentSubjectMarkDetails($request);
            if(empty($studentsDetails)){
                throw new ExamControllerException(ExamControllerException::NO_REPORTS_DETAILS_FOUND,"No Details Found");
            }
            else{
                $additionalDetails->batchName = $studentsDetails[0]->groupName;
                foreach($studentsDetails as $student){
                    $studentPendingSubjectList[$student->studentId]->studentId = $student->studentId;
                    $studentPendingSubjectList[$student->studentId]->studentName = $student->studentName;
                    $studentPendingSubjectList[$student->studentId]->regNo = $student->regNo;
                    $studentPendingSubjectList[$student->studentId]->semesters[$student->academicTermId]->academicTermId = $student->academicTermId;
                    $studentPendingSubjectList[$student->studentId]->semesters[$student->academicTermId]->academicTerm = $student->academicTerm;
                    $studentPendingSubjectList[$student->studentId]->semesters[$student->academicTermId]->subjects[$student->academicPaperSubjectId]->academicPaperSubjectId = $student->academicPaperSubjectId;
                    $studentPendingSubjectList[$student->studentId]->semesters[$student->academicTermId]->subjects[$student->academicPaperSubjectId]->subjectCode = $student->subjectCode;
                    $studentPendingSubjectList[$student->studentId]->semesters[$student->academicTermId]->subjects[$student->academicPaperSubjectId]->subjectName = $student->subjectName;
                    $studentPendingSubjectList[$student->studentId]->semesters[$student->academicTermId]->subjects[$student->academicPaperSubjectId]->attemptCount = $student->attemptCount;
                }
                $studentPendingSubjectList = array_values($studentPendingSubjectList); 
                foreach($studentPendingSubjectList as $student){
                    $student->semesters = array_values($student->semesters); 
                    foreach($student->semesters as $semester){
                        $semester->failedSubjectCount = count($semester->subjects);
                        $semester->subjects = array_values($semester->subjects);  
                    }
                    $student->maxFailedSubjectCount = max(array_column($student->semesters, "failedSubjectCount"));
                }
            }
            if(empty($studentPendingSubjectList)){
                throw new ExamControllerException(ExamControllerException::NO_REPORTS_DETAILS_FOUND,"No Details Found");
            }
            else{
                $templateName = "StudentPendingSubjectListReport";
                $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/ConsolidatedReports/$templateName.twig"), [ 'studentPendingSubjectList'=>$studentPendingSubjectList ,'additionalDetails'=>$additionalDetails]);
                $prtContent = NULL;
                $prtContent .= '<html><head>';
                $prtContent .= "<style>
                    h6 {font-size: 26px;} .text-center { text-align: center;} .align-middle {vertical-align: middle;}; tr.noBorder td {border: 0;  border-collapse:collapse;}
                    table, {border: 1px solid black;border-collapse: collapse;} .noborder-r-0{ border-right-style: none;} .border-r-0{ border-right:1px solid #dee2e6 !important;}
                    </style>";
                $prtContent .= '</head><title>Student Pending Subject List</title><body>';
                $prtContent .= $responseHtml;
                $prtContent .= '</body></html>';
                $totalWidth = 350;
                $totalHeight = 200;
                $options = array(
                    'page-width'     => $totalWidth."mm",
                    'page-height'    => $totalHeight."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->printData = PdfUtil::renderPdf($prtContent, $options);
            return  $programResult;
            }
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
    /**
     * get All Batches With Exam Registrations
     * @param $searchRequest 
     * @return $groups 
     */
    public function getBatchesWithExamMonthYear($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        $request = new \stdClass;
        $response = new \stdClass;
        $request->courseTypeId = $searchRequest->courseTypeId;
        if($request->courseTypeId){
            $courseType = CourseTypeService::getInstance()->getCourseTypesById ($request->courseTypeId);
            if($courseType->typeName == "MBA"){
                $response->enableSelectBatches = true;
            }
        }
        $request->admissionYear = $searchRequest->admissionYear;
        $request->examType = $searchRequest->examType;
        $groups = [];
        try{
            $batchDetails = $this->getAllBatchesWithExamRegistrations($request);
            foreach($batchDetails as $batch){
                $groups[$batch->groupId]->groupId = $batch->groupId;
                $groups[$batch->groupId]->isSelected = false;
                $groups[$batch->groupId]->id = $batch->groupId;
                $groups[$batch->groupId]->groupName = $batch->groupName;
                $monthYearId =  $batch->examYear."-".$batch->examMonth;
                $groups[$batch->groupId]->examRegistrations[$monthYearId]->id = $monthYearId;
                $monthName = date("M", mktime(0, 0, 0, (int)$batch->examMonth, 10));
                $groups[$batch->groupId]->examRegistrations[$monthYearId]->examMonthAndYear = $batch->examYear."-".$monthName;
            }
            $groups = array_values($groups);
            foreach($groups as $group){
                $group->examRegistrations = array_values($group->examRegistrations);
            }
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        
        $response->batches = $groups;
        return $response;
    }
    public function getAllBatchesWithExamRegistrations($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
      
        try{
            $orderBy = "ORDER BY g.created_date DESC";
            $whereQuery = "";
            if(!empty($searchRequest->admissionYear)) {
                $whereQuery .= " AND g.properties ->> '$.startYear' = '$searchRequest->admissionYear'";
            }
            if(!empty($searchRequest->groupId)) {
                $whereQuery .= " AND g.id = '$searchRequest->groupId'";
            }
            if(!empty($searchRequest->courseTypeId)) {
                $whereQuery .= " AND p.course_type_id = '$searchRequest->courseTypeId'";
            }
            if(!empty($searchRequest->examType)) {
                $whereQuery .= " AND eer.type = '$searchRequest->examType'";
            }
            $query = "SELECT DISTINCT
                            g.id as groupId,
                            g.name as groupName,
                            eer.id as examRegistrationId,
                            eer.name as examRegistrationName,
                            eer.properties ->> '$.examMonth' as examMonth,
                            eer.properties ->> '$.examYear' as examYear,
                            ct.typeName as courseTypeName,
                            ct.courseTypeID as courseTypeId
                        FROM
                            `groups` g
                        INNER JOIN ec_exam_registration_batch eerb ON
                            eerb.groups_id = g.id
                        INNER JOIN ec_exam_registration eer ON
                            eer.id = eerb.ec_exam_registration_id
                        INNER JOIN program p ON
                            p.id = g.properties ->> '$.programId'
                        INNER JOIN `course_type` ct ON
                            ct.courseTypeID = p.course_type_id
                        WHERE 1=1 ";
            $groups = $this->executeQueryForList($query.$whereQuery.$orderBy);
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        foreach($groups as $group){
            $group->isSelected = false;
        }
        return $groups;
    }
     /**
     * get Supplimentary Students Result Notification Details
     * @param $searchRequest 
     * @return $programResult 
     */
    public function getSupplimentaryStudentsResultNotificationDetails($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $request = new \stdClass;
            $additionalDetails = new \stdClass;
            $request->groupId = $searchRequest->groupId;
            foreach($searchRequest->examMonthYears as $monthYear){
                $singleMonthYear = explode("-", $monthYear);
                $monthYearObj = new \stdClass;
                $monthYearObj->year = $singleMonthYear[0];
                $monthYearObj->month = $singleMonthYear[1];
                $request->examMonthYears[] = $monthYearObj;
            }
            if($searchRequest->isPrint == "1"){
                $reportData = new \stdClass;
                $resultNotificationReportData = new \stdClass;
                $reportData->groupId = $searchRequest->groupId;
                $reportData->type = "RESULT_NOTIFICATION";
                $resultNotificationReportData->orderNo = $searchRequest->orderNo;
                $resultNotificationReportData->resultDate = $searchRequest->resultDate;
                $reportData->data = $resultNotificationReportData;
                $reportData->createdBy = $GLOBALS['userId'];
                $reportData = $this->saveReportData($reportData);
            }
            $reportDataRequest = new \stdClass;
            $reportDataRequest->type = "RESULT_NOTIFICATION";
            $reportDataRequest->groupId = $searchRequest->groupId;
            $reportData = new \stdClass;
            $reportData = $this->getReportData($reportDataRequest);
            if (empty($reportData->data)) {
                $additionalDetails->resultDate = "";
                $additionalDetails->orderNo = "";
            } else {
                $additionalDetails->resultDate = $reportData->data->resultDate;
                $additionalDetails->orderNo = $reportData->data->orderNo;
            }
            $batchRequest = new \stdClass;
            $batchRequest->groupId = $groupId;
            $additionalDetails->cgpaName = 'CGPA'; 
            $batchDetails =  reset($this->getBatchesByAcademicTerm($batchRequest));
            if((($batchDetails->courseTypeName == 'UG' || $batchDetails->courseTypeName == 'MSW') && ($batchDetails->batchStartYear > 2014 and $batchDetails->batchStartYear < 2019))|| 
                (($batchDetails->courseTypeName == 'UG') && ($batchDetails->batchStartYear >= 2014 && $batchDetails->batchStartYear <= 2016)) || 
                (($batchDetails->courseTypeName == 'UG') && ($batchDetails->batchStartYear == 2018  && $batchDetails->batchStartYear  == 2019)) || 
                (($batchDetails->courseTypeName == 'MPHIL') && ($batchDetails->batchStartYear == 2018 ))){
                $additionalDetails->cgpaName = 'CCPA'; 
            }
            $additionalDetails->startYear = $batchDetails->batchStartYear; 
            $additionalDetails->endYear = $batchDetails->batchEndYear; 
            $additionalDetails->programName = $batchDetails->programName; 
            $request->passedStudentsOnly = true;
            $additionalDetails->collageName = $GLOBALS['COLLEGE_NAME'];
            $batchDetails = [];
            $passedBySupplyStudentsIds = [];
            $publishDateArray = [];
            $isOverallPassed = true;
            $passedBySupplyStudentsDetails = [];
            $passedBySupplyStudentsDetailsArray = [];
            $regularFailedstudentsDetails = $this->getFailedStudentsInRegularExamRegistrations($request);
            $supplyPassedstudentsDetails = $this->getPassedStudentsInSupplyExamRegistrations($request);
            if(empty($supplyPassedstudentsDetails)){
                throw new ExamControllerException(ExamControllerException::NO_STUDENTS_IN_THIS_EXAM_REGISTRATION,"No Student(s) Found");
            }
            else{
                foreach($supplyPassedstudentsDetails as $passedStudent){
                    $publishDateArray[$passedStudent->studentId]->publishingDate = $passedStudent->publishingDate;
                    if(!empty($regularFailedstudentsDetails[$passedStudent->studentId])){
                        foreach($passedStudent->subjects as $passedStudentSubject){
                            if(!empty($regularFailedstudentsDetails[$passedStudent->studentId]->subjects[$passedStudentSubject->academicPaperSubjectId])){
                                $regularFailedstudentsDetails[$passedStudent->studentId]->subjects[$passedStudentSubject->academicPaperSubjectId]->isFailed = false;
                            }
                        }
                    }
                }
                foreach($regularFailedstudentsDetails as $failedStudent){
                    if(!empty($failedStudent->subjects)){
                        $isOverallPassed = true;
                        foreach($failedStudent->subjects as $failedStudentSubject){
                            if($failedStudentSubject->isFailed){
                                $isOverallPassed = false;
                            }
                        }
                        if($isOverallPassed){
                            $passedBySupplyStudentsIds[] = $failedStudent->studentId;
                        }
                    }
                }
                if(!empty($passedBySupplyStudentsIds)){
                    $request->studentIds = $passedBySupplyStudentsIds;
                    $passedBySupplyStudentsDetails = $this->getAllStudentsOverallMarkDetails($request);
                }
                foreach($passedBySupplyStudentsDetails as $student){
                    $passedBySupplyStudentsDetailsArray[$student->studentId]->studentId = $student->studentId;
                    $passedBySupplyStudentsDetailsArray[$student->studentId]->studentName = $student->studentName;
                    $passedBySupplyStudentsDetailsArray[$student->studentId]->regNo = $student->regNo;
                    $passedBySupplyStudentsDetailsArray[$student->studentId]->totalMark = $student->totalMark;
                    $passedBySupplyStudentsDetailsArray[$student->studentId]->class = $student->class;
                    $passedBySupplyStudentsDetailsArray[$student->studentId]->grade = $student->grade;
                    $passedBySupplyStudentsDetailsArray[$student->studentId]->cgpa = $student->cgpa;
                    if($publishDateArray[$student->studentId]->publishingDate){
                        $student->publishDate = date("d-m-Y", strtotime($publishDateArray[$student->studentId]->publishingDate));
                    }
                    $passedBySupplyStudentsDetailsArray[$student->studentId]->publishDate = $student->publishDate;
                    $markDetailsObj = json_decode($student->markDetails);
                    $passedBySupplyStudentsDetailsArray[$student->studentId]->cgpaWithoutGracemark = $markDetailsObj->cgpaWithoutGracemark;
                    $passedBySupplyStudentsDetailsArray[$student->studentId]->gradeWithoutGracemark = $markDetailsObj->gradeWithoutGracemark;
                    $monthName = date("M", mktime(0, 0, 0, (int)$markDetailsObj->latestExamMonth, 10));
                    $passedBySupplyStudentsDetailsArray[$student->studentId]->monthYearOfPassing = $monthName."-".$markDetailsObj->latestExamYear;
                    $passedBySupplyStudentsDetailsArray[$student->studentId]->isGraceMarkAwarded = $student->cgpa == $markDetailsObj->cgpaWithoutGracemark ? false : true;
                }
                $passedBySupplyStudentsDetailsArray = array_values($passedBySupplyStudentsDetailsArray);
                $batchDetails =  $this->getBatchesByAcademicTerm($request);
                if($batchDetails[0]->degreeName == "MBA"){
                    $templateName = "SupplyResultNotificationReportTemplate2"; 
                }
                else{
                    $templateName = "SupplyResultNotificationReportTemplate1";
                }
            }
            if(empty($passedBySupplyStudentsDetailsArray)){
                throw new ExamControllerException(ExamControllerException::NO_STUDENTS_IN_THIS_EXAM_REGISTRATION,"No Students Found");
            }
            else{
                $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/ConsolidatedReports/$templateName.twig"), [ 'students'=>$passedBySupplyStudentsDetailsArray ,'additionalDetails'=>$additionalDetails]);
                $prtContent = NULL;
                $prtContent .= '<html><head>';
                $prtContent .= "<style>
                    h6 {font-size: 26px;} .text-center { text-align: center;} .align-middle {vertical-align: middle;}; tr.noBorder td {border: 0;  border-collapse:collapse;}
                    table, th, td {border: 1px solid black;border-collapse: collapse;} .displayOnlyDisplayData { display: none; }
                    </style>";
                $prtContent .= '</head><title>Supply Result Notification Report</title><body>';
                $prtContent .= $responseHtml;
                $prtContent .= '</body></html>';
                
                $totalWidth = 210;
                $totalHeight = 297;
                $options = array(
                    'page-width'     => $totalWidth."mm",
                    'page-height'    => $totalHeight."mm",
                    'dpi'            => 96,
                    'margin-top' => "10mm",
                    'margin-left' => "10mm",
                    'margin-right' => "10mm",
                    'margin-bottom' => "30mm",
                    'footer-spacing' => -10,
                    // '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->printData = PdfUtil::renderPdf($prtContent, $options);
            return  $programResult;
            }
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
     /**
     * get Regular Students Result Notification Details
     * @param $searchRequest 
     * @return $programResult 
     */
    public function getRegularStudentsResultNotificationDetails($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $request = new \stdClass;
            $additionalDetails = new \stdClass;
            $request->groupId = $searchRequest->groupIds;
            foreach($searchRequest->examMonthYears as $monthYear){
                $singleMonthYear = explode("-", $monthYear);
                $monthYearObj = new \stdClass;
                $monthYearObj->year = $singleMonthYear[0];
                $monthYearObj->month = $singleMonthYear[1];
                $request->lastExamMonthYears[] = $monthYearObj;
            }
            $request->passedStudentsOnly = true;
            if($searchRequest->isPrint == "1"){
                foreach($searchRequest->groupIds as $groupId){
                    $reportData = new \stdClass;
                    $resultNotificationReportData = new \stdClass;
                    $reportData->groupId = $groupId;
                    $reportData->type = "RESULT_NOTIFICATION";
                    $resultNotificationReportData->orderNo = $searchRequest->orderNo;
                    $resultNotificationReportData->resultDate = $searchRequest->resultDate;
                    $reportData->data = $resultNotificationReportData;
                    $reportData->createdBy = $GLOBALS['userId'];
                    $reportData = $this->saveReportData($reportData);
                }
            }
            foreach($searchRequest->groupIds as $key => $groupId){
                $reportDataRequest = new \stdClass;
                $reportDataRequest->type = "RESULT_NOTIFICATION";
                $reportDataRequest->groupId = $groupId;
                $reportData = new \stdClass;
                $reportData = $this->getReportData($reportDataRequest);
                if (empty($reportData->data)) {
                    $additionalDetails->resultDate = "";
                    $additionalDetails->orderNo = "";
                } else {
                    $additionalDetails->resultDate = $reportData->data->resultDate;
                    $additionalDetails->orderNo = $reportData->data->orderNo;
                }
            }
            $additionalDetails->collageName = $GLOBALS['COLLEGE_NAME'];
            $batchRequest = new \stdClass;
            $batchRequest->groupId = $groupId;
            $additionalDetails->cgpaName = 'CGPA'; 
            $batchDetails =  reset($this->getBatchesByAcademicTerm($batchRequest));
            if((($batchDetails->courseTypeName == 'UG' || $batchDetails->courseTypeName == 'MSW') && ($batchDetails->batchStartYear > 2014 and $batchDetails->batchStartYear < 2019))|| 
                (($batchDetails->courseTypeName == 'UG') && ($batchDetails->batchStartYear >= 2014 && $batchDetails->batchStartYear <= 2016)) || 
                (($batchDetails->courseTypeName == 'UG') && ($batchDetails->batchStartYear == 2018  && $batchDetails->batchStartYear  == 2019)) || 
                (($batchDetails->courseTypeName == 'MPHIL') && ($batchDetails->batchStartYear == 2018 ))){
                $additionalDetails->cgpaName = 'CCPA'; 
            }
            $additionalDetails->startYear = $batchDetails->batchStartYear; 
            $additionalDetails->endYear = $batchDetails->batchEndYear; 
            $additionalDetails->programName = $batchDetails->programName; 
            
            $batchDetails = [];
            $regularPassedstudentsDetails = [];
            $passedStudentsDetailsArray = [];
            $regularPassedstudentsDetails = $this->getAllStudentsOverallMarkDetails($request);
            if(empty($regularPassedstudentsDetails)){
                throw new ExamControllerException(ExamControllerException::NO_STUDENTS_IN_THIS_EXAM_REGISTRATION,"No Student(s) Found");
            }
            else{
                foreach($regularPassedstudentsDetails as $student){
                    $passedStudentsDetailsArray[$student->studentId]->studentId = $student->studentId;
                    $passedStudentsDetailsArray[$student->studentId]->studentName = $student->studentName;
                    $passedStudentsDetailsArray[$student->studentId]->regNo = $student->regNo;
                    $passedStudentsDetailsArray[$student->studentId]->totalMark = $student->totalMark;
                    $passedStudentsDetailsArray[$student->studentId]->class = $student->class;
                    $passedStudentsDetailsArray[$student->studentId]->grade = $student->grade;
                    $passedStudentsDetailsArray[$student->studentId]->cgpa = $student->cgpa;
                    $markDetailsObj = json_decode($student->markDetails);
                    $passedStudentsDetailsArray[$student->studentId]->cgpaWithoutGracemark = $markDetailsObj->cgpaWithoutGracemark ? round($student->cgpa,3) : '' ;
                     $passedStudentsDetailsArray[$student->studentId]->gradeWithoutGracemark = $markDetailsObj->gradeWithoutGracemark;
                    $monthName = date("M", mktime(0, 0, 0, (int)$markDetailsObj->lastExamMonth, 10));
                    $passedStudentsDetailsArray[$student->studentId]->monthYearOfPassing = $monthName."-".$markDetailsObj->latestExamYear;
                    $passedBySupplyStudentsDetailsArray[$student->studentId]->isGraceMarkAwarded = $student->cgpa == $markDetailsObj->cgpaWithoutGracemark ? false : true;
                }
                $passedStudentsDetailsArray = array_values($passedStudentsDetailsArray);
                uasort($passedStudentsDetailsArray, function ($studentA, $studentB) {
                    return $studentA->cgpaWithoutGracemark < $studentB->cgpaWithoutGracemark;
                });
                $rank = 1;
                foreach($passedStudentsDetailsArray as $student){
                    $student->rank = $rank++;
                }
                usort($passedStudentsDetailsArray, function ($studentA, $studentB){
                    return $studentA->regNo > $studentB->regNo;
                });
                $batchDetails =  $this->getBatchesByAcademicTerm($request);
                if($batchDetails[0]->degreeName == "MBA"){
                    $templateName = "RegularResultNotificationReportTemplate2"; 
                }
                else{
                    $templateName = "RegularResultNotificationReportTemplate1";
                }
            }
            if(empty($passedStudentsDetailsArray)){
                throw new ExamControllerException(ExamControllerException::NO_STUDENTS_IN_THIS_EXAM_REGISTRATION,"No Students Found");
            }
            else{
                $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/ConsolidatedReports/$templateName.twig"), [ 'students'=>$passedStudentsDetailsArray ,'additionalDetails'=>$additionalDetails]);
                $prtContent = NULL;
                $prtContent .= '<html><head>';
                $prtContent .= "<style>
                    h6 {font-size: 26px;} .text-center { text-align: center;} .align-middle {vertical-align: middle;}; tr.noBorder td {border: 0;  border-collapse:collapse;}
                    table, th, td {border: 1px solid black;border-collapse: collapse;} .displayOnlyDisplayData { display: none; }
                    </style>";
                $prtContent .= '</head><title>Regular result notification report</title><body>';
                $prtContent .= $responseHtml;
                $prtContent .= '</body></html>';
                
                $totalWidth = 210;
                $totalHeight = 297;
                $options = array(
                    'page-width'     => $totalWidth."mm",
                    'page-height'    => $totalHeight."mm",
                    'dpi'            => 96,
                    'margin-top' => "10mm",
                    'margin-left' => "10mm",
                    'margin-right' => "10mm",
                    'margin-bottom' => "30mm",
                    // '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->printData = PdfUtil::renderPdf($prtContent, $options);
            return  $programResult;
            }
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
    
     /**
     * get Failed Students In Regular Exam Registrations
     * @param $searchRequest 
     * @return $programResult 
     */
    public function getFailedStudentsInRegularExamRegistrations($searchRequest){
        $searchRequest = $this->realEscapeObject($searchRequest);
        $request = new \stdClass;
        $request->groupId = $searchRequest->groupId;
        $request->failedStudentsOnly = true;
        $request->examRegistrationType = ExamRegistrationTypeConstants::REGULAR;
        $studentsDetails = $this->getAllStudentSubjectMarkDetails($request);
        $regularFailedstudentsDetails = [];
        foreach($studentsDetails as $student){
            if($student->failedStatus == "FAILED"){
                $regularFailedstudentsDetails[$student->studentId]->studentId = $student->studentId;
                $regularFailedstudentsDetails[$student->studentId]->studentName = $student->studentName;
                $regularFailedstudentsDetails[$student->studentId]->regNo = $student->regNo;
                $regularFailedstudentsDetails[$student->studentId]->subjects[$student->academicPaperSubjectId]->academicPaperSubjectId = $student->academicPaperSubjectId;
                $regularFailedstudentsDetails[$student->studentId]->subjects[$student->academicPaperSubjectId]->subjectName = $student->subjectName;
                $regularFailedstudentsDetails[$student->studentId]->subjects[$student->academicPaperSubjectId]->isFailed = true;
            }
        }
        return $regularFailedstudentsDetails;
    }
     /**
     * get Passed Students In SUPPLEMENTARY ExamRegistrations
     * @param $searchRequest 
     * @return $programResult 
     */
    public function getPassedStudentsInSupplyExamRegistrations($searchRequest){
        $searchRequest = $this->realEscapeObject($searchRequest);
        $request = new \stdClass;
        $request->groupsId = $searchRequest->groupsId;
        $request->examMonthYears = $searchRequest->examMonthYears;
        $request->passedStudentsOnly = true;
       
        $request->examRegistrationType = ExamRegistrationTypeConstants::SUPPLEMENTARY;
        $studentsDetails = $this->getAllStudentSubjectMarkDetails($request);
        $supplyPassedstudentsDetails = [];
        foreach($studentsDetails as $student){
            if($student->failedStatus == "PASSED"){
                $supplyPassedstudentsDetails[$student->studentId]->studentId = $student->studentId;
                $supplyPassedstudentsDetails[$student->studentId]->studentName = $student->studentName;
                $supplyPassedstudentsDetails[$student->studentId]->publishingDate = $student->publishingDate;
                $supplyPassedstudentsDetails[$student->studentId]->regNo = $student->regNo;
                $supplyPassedstudentsDetails[$student->studentId]->subjects[$student->academicPaperSubjectId]->academicPaperSubjectId = $student->academicPaperSubjectId;
                $supplyPassedstudentsDetails[$student->studentId]->subjects[$student->academicPaperSubjectId]->subjectName = $student->subjectName;
                $supplyPassedstudentsDetails[$student->studentId]->subjects[$student->academicPaperSubjectId]->isFailed = true;
            }
        }
        return $supplyPassedstudentsDetails;
    }
    public function getAllGradeScemesByCurriculum($searchRequest){
        $searchRequest = $this->realEscapeObject($searchRequest);
        
        try{
            $whereQuery = "";
            if(!empty($searchRequest->courseTypeId)) {
                $whereQuery .= " AND p.course_type_id = '$searchRequest->courseTypeId'";
            }
            if(!empty($searchRequest->admissionYear)) {
                $whereQuery .= " AND g.properties ->> '$.startYear' = '$searchRequest->admissionYear'";
            }
            if(!empty($searchRequest->groupId)) {
                $whereQuery .= " AND g.id = '$searchRequest->groupId'";
            }
            $orderBy = " ORDER BY gr.range_to DESC";
            $query = "SELECT DISTINCT 
                gr.id,
                gr.name,
                gr.range_from AS rangeFrom, 
                gr.range_to AS rangeTo,
                gr.properties,
                gs.type
            FROM
                `groups` g
            INNER JOIN program p 
                ON p.id  = g.properties->>'$.programId'
            INNER JOIN cm_curriculum cc ON
                cc.id = CAST(g.properties->>'$.curriculumId' AS CHAR)
            INNER JOIN cm_curriculum_syllabus_relation ccsr ON
                ccsr.cm_curriculum_id = cc.id
            INNER JOIN cm_syllabus_academic_term_settings csats ON
                csats.cm_syllabus_id = ccsr.cm_syllabus_id
            INNER JOIN valuation_method vm ON
                CAST(vm.identifying_context->>'$.syllabusAcademicTermSettingsId' AS CHAR) = csats.id AND 
                vm.type = 'SYLLABUS_ACADEMIC_TERM' AND 
                vm.trashed IS NULL
            INNER JOIN grade_scheme gs ON
                gs.id = CAST(vm.properties->>'$.gradeSchemeId' AS CHAR)
            INNER JOIN grade gr ON
                gr.grade_scheme_id = CAST(csats.properties->>'$.gradeSchemeId' AS CHAR)
                AND gr.grade_scheme_id = gs.id";
            $gradeSchemrs =  $this->executeQueryForList($query.$whereQuery.$orderBy);
           
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $gradeSchemrs;
    }
    public function getFinalGradeSchemesByCurriculum($searchRequest){
        $searchRequest = $this->realEscapeObject($searchRequest);
        
        try{
            $whereQuery = "";
            if(!empty($searchRequest->courseTypeId)) {
                $whereQuery .= " AND p.course_type_id = '$searchRequest->courseTypeId'";
            }
            if(!empty($searchRequest->admissionYear)) {
                $whereQuery .= " AND g.properties ->> '$.startYear' = '$searchRequest->admissionYear'";
            }
            if(!empty($searchRequest->groupId)) {
                $whereQuery .= " AND g.id = '$searchRequest->groupId'";
            }
            $orderBy = " ORDER BY gr.range_to DESC";
            $query = "SELECT DISTINCT 
                gr.id,
                gr.name,
                gr.range_from,
                gr.range_to,
                gr.properties,
                gs.type
            FROM
                `groups` g
            INNER JOIN program p 
                ON p.id  = g.properties->>'$.programId'
            INNER JOIN cm_curriculum cc ON
                cc.id = CAST(g.properties->>'$.curriculumId' AS CHAR)
            INNER JOIN cm_curriculum_syllabus_relation ccsr ON
                ccsr.cm_curriculum_id = cc.id
            INNER JOIN grade_scheme gs ON
                gs.id = CAST(cc.properties->>'$.gradeSchemId' AS CHAR)
            INNER JOIN grade gr ON
                gr.grade_scheme_id = CAST(cc.properties->>'$.gradeSchemId' AS CHAR)
                AND gr.grade_scheme_id = gs.id";
            $gradeSchemrs =  $this->executeQueryForList($query.$whereQuery.$orderBy);
           
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $gradeSchemrs;
    }
    /**
     * get report related data.
     * 
     * @throws ExamControllerException
     * @return reportData
     */
    public function getReportData($request) {
        $request = $this->realEscapeObject($request);
        $sql ="";
        try {
            if (!$request->groupId) {
                throw new ExamControllerException(ExamControllerException::INVALID_REQUEST,"Batch Id is required!");
            }
            if (!$request->type) {
                throw new ExamControllerException(ExamControllerException::INVALID_REQUEST,"Report type is required!");
            }
            $sql = "SELECT
                id,
                `type`,
                group_Id AS groupId,
                `data`
            FROM
                ec_report_data
            WHERE
                group_Id = '$request->groupId'
                AND `type` = '$request->type'";
            $reportData  = $this->executeQueryForObject($sql);
        }
        catch(\Exception $e) {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        if(!empty($reportData)){
            $reportData->data  = json_decode($reportData->data);
        }
        return $reportData;
    }
    /**
     * save report related data.
     * 
     * @throws ExamControllerException
     * @return reportData
     */
    public function saveReportData($reportData) {
        $reportData = $this->realEscapeObject($reportData);
        $sql ="";
        try {
            if (!$reportData->groupId) {
                throw new ExamControllerException(ExamControllerException::INVALID_REQUEST,"Batch Id is required!");
            }
            if (!$reportData->type) {
                throw new ExamControllerException(ExamControllerException::INVALID_REQUEST,"Report type is required!");
            }
            $savedReportData = $this->getReportData($reportData);
            $identifyingContext = '{"groupId":"' . $reportData->groupId . '"}';
            $data = empty($reportData->data) ? "{}" : json_encode($reportData->data);
            if (empty($savedReportData)) {
                $sql = "INSERT INTO ec_report_data(id,`type`,group_Id,identifying_context,`data`,created_by) VALUES
                (LEFT(MD5(RAND()),17),'$reportData->type','$reportData->groupId','$identifyingContext','$data', $reportData->createdBy)";
                $reportData->id  = $this->executeQuery($sql,true);
            }
            else {
                $sql = "UPDATE
                    ec_report_data
                SET
                    `data` = '$data',
                    updated_by = '$reportData->createdBy'
                WHERE
                    id = '$savedReportData->id'";
                $this->executeQuery($sql);
                $reportData->id  = $savedReportData->id;
            }
        }
        catch(\Exception $e) {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $reportData;
    }
     /**
     * get CGPA Grade Scemes By Curriculum
     * @param $searchRequest 
     * @throws ExamControllerException
     * @return gradeSchemrs
     */
    public function getCGPAGradeScemesByCurriculum($searchRequest){
        $searchRequest = $this->realEscapeObject($searchRequest);
        
        try{
            $whereQuery = "";
            if(!empty($searchRequest->courseTypeId)) {
                $whereQuery .= " AND p.course_type_id = '$searchRequest->courseTypeId'";
            }
            if(!empty($searchRequest->admissionYear)) {
                $whereQuery .= " AND g.properties ->> '$.startYear' = '$searchRequest->admissionYear'";
            }
            if(!empty($searchRequest->groupId)) {
                $whereQuery .= " AND g.id = '$searchRequest->groupId'";
            }
            $orderBy = " ORDER BY gr.range_to DESC";
            $query = "SELECT DISTINCT 
                gr.id,
                gr.name,
                gr.range_from AS rangeFrom, 
                gr.range_to AS rangeTo,
                gr.properties,
                gs.type
            FROM
                `groups` g
            INNER JOIN program p 
                ON p.id  = g.properties->>'$.programId'
            INNER JOIN cm_curriculum cc ON
                cc.id = CAST(g.properties->>'$.curriculumId' AS CHAR)
            INNER JOIN valuation_method vm ON 
                CAST(g.identifying_context->>'$.curriculumId' AS CHAR) = cc.id AND vm.type = 'CURRICULUM'
            INNER JOIN grade_scheme gs ON
                gs.id = CAST(vm.properties->>'$.gradeSchemId' AS CHAR)
            INNER JOIN grade gr ON
                gr.grade_scheme_id = gs.id
                AND gr.grade_scheme_id = gs.id";
            $gradeSchemrs =  $this->executeQueryForList($query.$whereQuery.$orderBy);
           
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $gradeSchemrs;
    }
    
    /**
     * get All student Consolidated semester and overall mark details
     * @param $searchRequest 
     * @return $studentDetails 
     */
    public function getAllStudentConsolidatedSemesterAndOverallMarkDetails($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $whereQuery = "";
            $orderBy = null;
            if(!empty($searchRequest->orderBy)) {
                if($searchRequest->orderBy == 'AdmissionYear'){
                    $orderBy = " ORDER BY g.properties ->> '$.startYear' ASC";
                }
            }
            else{
                $orderBy = " ORDER BY sa.regNo ASC";
            }
            if(!empty($searchRequest->groupId)) {
                $whereQuery .= " AND g.id = '$searchRequest->groupId'";
            }
            if(!empty($searchRequest->courseTypeId)) {
                $whereQuery .= " AND p.course_type_id = '$searchRequest->courseTypeId'";
            }
            if(!empty($searchRequest->admissionYears)) {
                $admissionYearsString= "'" . implode("', '", $searchRequest->admissionYears) . "'" ;
                $whereQuery .= " AND g.properties ->> '$.startYear' IN ($admissionYearsString)";
            }
            if(!empty($searchRequest->departmentId)) {
                $whereQuery .= " AND g.properties ->> '$.departmentId' = '$searchRequest->departmentId'";
            }
            $query = "SELECT DISTINCT
                        sa.studentID as studentId,
                        sa.studentName,
                        sa.regNo,
                        g.id as groupId,
                        g.name as groupName,
                        g.properties ->> '$.startYear' as admissionYear,
                        g.properties ->> '$.departmentId' as departmentId,
                        p.course_type_id as courseTypeId,
                        dept.deptName as departmentName,
                        ecmd.cgpa as cgpa,
                        ecmd.percentage as overallPercentage,
                        ecmd.grade as overallGrade,
                        ecmd.class as overallClass,
                        ecmd.total_marks as totalMark,
                        ecmd.failed_status as overallFailedStatus,
                        act.id as academicTermId,
                        act.name as academicTermName,
                        esmd.mark_details ->> '$.latestExamMonth' as examMonth,
                        esmd.mark_details ->> '$.latestExamYear' as examYear,
                        esmd.mark_details ->> '$.latestExamType' as examRegType,
                        esmd.sgpa as semesterSgpa,
                        esmd.percentage as semesterPercentage,
                        esmd.grade as semesterGrade,
                        esmd.failed_status as semesterFailedStatus,
                        esmd.mark_details->>'$.latestExamYear' as latestExamYear,
                        esmd.mark_details->>'$.latestExamMonth' as latestExamMonth
                    FROM
                        `groups` g
                    INNER JOIN program p 
                        ON p.id  = g.properties->>'$.programId'
                    INNER JOIN ec_exam_registration_batch eerb ON
                        eerb.groups_id = g.id
                    INNER JOIN ec_exam_registration eer
                        ON eer.id = eerb.ec_exam_registration_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 
                        esar.ec_exam_registration_type = eer.type AND
                        CAST(esar.properties ->> '$.registrationStatus' AS CHAR) = 'REGISTERED' AND 
                        CAST(esar.properties ->> '$.feeStatus' AS CHAR) = 'PAID' 
                    INNER JOIN studentaccount sa ON 
                        sa.studentID = esar.student_id
                    INNER JOIN  academic_term act ON 
                        act.id = CAST(eerb.properties ->> '$.academicTermId'AS CHAR)
                    INNER JOIN  department dept ON 
                        dept.deptID = g.properties ->> '$.departmentId'
                    INNER JOIN ec_semester_mark_details esmd ON
                        esmd.groups_id = eerb.groups_id AND esmd.academic_term_id = act.id AND esmd.student_id = sa.studentID 
                    INNER JOIN  ec_course_mark_details ecmd ON
                        ecmd.groups_id = eerb.groups_id AND ecmd.student_id = sa.studentID 
                    WHERE 1=1 ";
            $studentDetails = $this->executeQueryForList($query.$whereQuery.$orderBy, $this->mapper[FinalConsolidatedReportServiceMapper::CONSOLIDATED_MARK_DETAILS]);
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $studentDetails;
    }
    /**
     * get Failed Student List
     * @param $searchRequest 
     * @return $programResult 
     */
    public function getFailedStudentList($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        $subjectStudentsDetails = [];
        $failedStudentRequest = new \stdClass;
        $additionalInfo = new \stdClass;
        $additionalInfo->collegeData = CommonExamService::getInstance()->getCollegeDetails();
        $failedStudentRequest->reportType = $searchRequest->reportType;
        if($failedStudentRequest->reportType == 'CONSOLIDATED'){
            $templateName = "consolidated-failed-student-list";
           
            $failedStudentRequest->courseTypeId = $searchRequest->courseTypeId;
            $failedStudentRequest->admissionYears = $searchRequest->admissionYear;
            $failedStudentRequest->academicTermId = $searchRequest->academicTermId;
            $failedStudentRequest->examRegistrationType =  ExamRegistrationTypeConstants::REGULAR;
            $failedStudentRequest->failedStudentsOnly =  true;
            $students = $this->getAllStudentSubjectMarkDetails($failedStudentRequest);
            if(empty($students)){
                throw new ExamControllerException(ExamControllerException::NO_REPORTS_DETAILS_FOUND,"No students found.");
            }
            foreach($students as $student){
                $subjectStudentsDetails[$student->subjectId]->id = $student->subjectId;
                $subjectStudentsDetails[$student->subjectId]->subjectCode = $student->subjectCode;
                $subjectStudentsDetails[$student->subjectId]->subjectName = $student->subjectName;
                $subjectStudentsDetails[$student->subjectId]->students[] = $student;
            }
            $subjectStudentsDetails = array_values($subjectStudentsDetails);
            
            $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/ConsolidatedReports/failedStudentList/$templateName.twig"), [ 'subjects'=>$subjectStudentsDetails,'additionalInfo'=>$additionalInfo]);
        }
        else if($failedStudentRequest->reportType == 'STUDENT_WISE'){
            $templateName = "consolidated-failed-list-student-wise";
           
            $additionalInfo = new \stdClass();
            $failedStudentRequest->courseTypeId = $searchRequest->courseTypeId;
            $failedStudentRequest->admissionYears = $searchRequest->admissionYear;
            $failedStudentRequest->groupId = $searchRequest->groupId;
            $failedStudentRequest->considerFailedSubjectOnly = 1;
            // $failedStudentRequest->examRegistrationType =  ExamRegistrationTypeConstants::REGULAR;
            // $failedStudentRequest->failedStudentsOnly =  true;
            $students = MarksCardService::getInstance()->getStudentSemesterWiseResult($failedStudentRequest);
            $additionalInfo->semesters =CommonExamService::getInstance()->getAllAcademicTermsDetailsByBatch($failedStudentRequest);
            $additionalInfo->collegeData = CommonExamService::getInstance()->getCollegeDetails();
            $additionalInfo->totalSemester = count($additionalInfo->semesters);
            if(empty($students)){
                throw new ExamControllerException(ExamControllerException::NO_REPORTS_DETAILS_FOUND,"No students found.");
            }
            foreach($students as $student){
                foreach($student->academicTerms as $academicTerms){
                    foreach($academicTerms->subjects as $subject){
                        $subjectStudentsDetails[$student->studentId]->studentId = $student->studentId;
                        $subjectStudentsDetails[$student->studentId]->regNo = $student->regNo;
                        $subjectStudentsDetails[$student->studentId]->name = $student->name;
                        $subjectStudentsDetails[$student->studentId]->studentId = $student->studentId;
                        $subjectStudentsDetails[$student->studentId]->academicTerms[$academicTerms->id]->orderNo = $academicTerms->OrderNo;
                        $subjectStudentsDetails[$student->studentId]->academicTerms[$academicTerms->id]->id = $academicTerms->id;
                        $subjectStudentsDetails[$student->studentId]->academicTerms[$academicTerms->id]->failedCount++;
                        $subjectStudentsDetails[$student->studentId]->failedCount++;
                        $subjectStudentsDetails[$student->studentId]->academicTerms[$academicTerms->id]->termName = $academicTerms->name;
                        $subjectStudentsDetails[$student->studentId]->academicTerms[$academicTerms->id]->subject[$subject->id]->id = $subject->id;
                        $subjectStudentsDetails[$student->studentId]->academicTerms[$academicTerms->id]->subject[$subject->id]->subjectCode = $subject->subjectCode;
                        $subjectStudentsDetails[$student->studentId]->academicTerms[$academicTerms->id]->subject[$subject->id]->subjectName = $subject->subjectName;
                        $subjectStudentsDetails[$student->studentId]->academicTerms[$academicTerms->id]->course[] = $subject->subjectName."(".$subject->subjectCode.")";
                        $subjectStudentsDetails[$student->studentId]->course[] = $subject->subjectName."(".$subject->subjectCode.")";
                    }
                }
            }
            uasort($subjectStudentsDetails, function ($a, $b) {
                return $a->regNo > $b->regNo;
            });
            $subjectStudentsDetails = array_values($subjectStudentsDetails);
            
            $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/ConsolidatedReports/failedStudentList/$templateName.twig"), [ 'subjects'=>$subjectStudentsDetails,'additionalInfo'=>$additionalInfo]);
        }
        else if($failedStudentRequest->reportType == 'SUBJECT_WISE'){
            $searchRequest->academicPaperSubjectIdUnique = stripslashes($searchRequest->academicPaperSubjectId);
            $studentDetails = [];
            $failedStudentRequest->courseTypeId = $searchRequest->courseTypeId;
            $failedStudentRequest->admissionYears = $searchRequest->admissionYear;
            $failedStudentRequest->academicTermId = $searchRequest->academicTermId;
            $failedStudentRequest->isConsolidatedView = $searchRequest->isConsolidatedView;
            $failedStudentRequest->academicPaperSubjectIdUnique = $searchRequest->academicPaperSubjectIdUnique;
            $failedStudentRequest->consolidatedFailedStudentsOnly =  true;   
            $failedStudentRequest->groupId = $searchRequest->groupId;
            $failedStudentRequest->orderBy = 'REGISTER_NO';
            $students = $this->getAllStudentSubjectMarkDetails($failedStudentRequest);
            $templateName = $failedStudentRequest->isConsolidatedView == 'true' ?  "consolidated-failed-student-list-suject-wise-consolidated-view-template" : "consolidated-failed-student-list-suject-wise-template";
            $additionalInfo->collegeData = CommonExamService::getInstance()->getCollegeDetails();
            $searchGroupRequest = new SearchGroupRequest;
            $searchGroupRequest->startYear = $searchRequest->admissionYear;
            $searchGroupRequest->courseTypeId = $searchRequest->courseTypeId;
            // $searchGroupRequest->currentTermId = $searchRequest->academicTermId;
            $searchGroupRequest->id = $failedStudentRequest->groupId;
            $searchGroupRequest->type = "BATCH";
            $batches = ECGroupService::getInstance()->searchGroupByRequest($searchGroupRequest);
            foreach($batches as $batch){
                $batchDetails[$batch->id]->id = $batch->id;
                $batchDetails[$batch->id]->name = $batch->name;
            }
            foreach($students as $student){
                $studentDetails[$student->studentId]->id = $student->studentId;
                $studentDetails[$student->studentId]->name = $student->studentName;
                $studentDetails[$student->studentId]->regNo = $student->regNo;
                $subjectStudentsDetails[$student->subjectId]->id = $student->subjectId;
                $subjectStudentsDetails[$student->subjectId]->subjectCode = $student->subjectCode;
                $subjectStudentsDetails[$student->subjectId]->subjectName = $student->subjectName;
                $subjectStudentsDetails[$student->subjectId]->groups[$student->groupId]->id = $student->groupId;
                $subjectStudentsDetails[$student->subjectId]->groups[$student->groupId]->failedStudentCount ++;
            }
            $batchDetails = array_values($batchDetails);
            $studentDetails = array_values($studentDetails);
            $additionalInfo->colspan =  count($batchDetails) + 3;
            $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/ConsolidatedReports/failedStudentList/$templateName.twig"), [ 'students'=>$studentDetails, 'batches'=>$batchDetails,'subjects'=>$subjectStudentsDetails,'additionalInfo'=>$additionalInfo]);
        }
        
        $prtContent = NULL;
            $prtContent .= '<html><head>';
            $prtContent .= "<style>
                </style>";
            $prtContent .= '</head><title>Failed Student List</title><body>';
            $prtContent .= $responseHtml;
            $prtContent .= '</body></html>';
            $totalWidth = 210;
            $totalHeight = 297;
            if($failedStudentRequest->reportType == 'STUDENT_WISE'){
                $totalWidth = 410;
                $totalHeight = 297;
            }
            $options = array(
                'page-width'     => $totalWidth."mm",
                'page-height'    => $totalHeight."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->subjects = $subjectStudentsDetails;
        $programResult->dispalyHtmlData = $responseHtml;
        $programResult->printData = PdfUtil::renderPdf($prtContent, $options);
        return  $programResult;
    }
      /**
     * get Program result report
     * @param $searchRequest 
     * @return $programResult 
     * @author Krishnajith
     */
    public function getProgramResultReport($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $request = new \stdClass;
            $request->groupId = $searchRequest->groupId;
            $request->examMonthYears = $searchRequest->examMonthYears;
            $request->passStatus = $searchRequest->passStatus;
            $request->considerSupplementary = $searchRequest->considerSupplementary == 'true' ? true : false;
            $request->publishEndDate = $searchRequest->endDate;
            $request->publishStartDate = $searchRequest->startDate;
            $request->filterRegisterNo = $searchRequest->filterRegisterNo;
            $programResult = ProgramResultGenerator::getInstance()->getProgramResultData($request);
            return $programResult;
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
    
    
    public function getGraduationBatchReport($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $request = new \stdClass;
            $additionalDetails = new \stdClass;
            global $COLLEGE_NAME, $autonomous, $PLACE;
            $additionalDetails->collageName = $COLLEGE_NAME;
            $additionalDetails->autonomous = $autonomous;
            $additionalDetails->place = $PLACE;
            $request->groupsId = $searchRequest->groupId;
            $request->groupId = $searchRequest->groupId;
            // $request->passedStudentsOnly = $searchRequest->isPassedStudentsOnly == 'true' ? true : false;
            $batchDetails = [];
            $batchDetailsArray = [];
            $additionalDetails->semesters =CommonExamService::getInstance()->getAllAcademicTermsDetailsByBatch($request);
            $additionalDetails->finalSemOrderNo = max(array_column($additionalDetails->semesters, "OrderNo"));
            $studentsDetails = $this->getAllStudentSemesterWiseConsolidatedMarkDetails($request);
            if($searchRequest->isStaffSideRequest == 'true'){
                $requestForExamRegistration = new SearchExamRegistrationRequest;
                $requestForExamRegistration->groupId = $searchRequest->groupId;
                $revaluationRegistrations = ExamRegistrationService::getInstance()->getAllExamRevaluation($requestForExamRegistration);    
            }
            if(empty($studentsDetails)){
                throw new ExamControllerException(ExamControllerException::NO_STUDENTS_IN_THIS_EXAM_REGISTRATION,"No Student(s) Found");
            }
            else{
                foreach( $studentsDetails as $key => $student){
                    if( $student->academicStatus == "DISCONTINUE"){ 
                        unset($studentsDetails[$key]);
                    }
                    $student->monthName = date("F", mktime(0, 0, 0, (int)$student->latestExamMonth, 10));
                    $yearCredits = 0;
                    $customFields = AmsCustomFieldsService::getInstance()->getAmsCustomFieldValue(AmsCustomFieldsEntities::STUDENT, $student->id, []);
                    if( $customFields ){
                        $student->ktuCode = CommonExamService::getInstance()->getCustomFieldObjectList($customFields)->studentData->KTU_CODE;
                    }
                    uasort($student->academicTerms, function ($a, $b) {
                        return $a->orderNo > $b->orderNo;
                    });
                    if($searchRequest->isStaffSideRequest == 'true'){
                        $student->withHeldExamRegIds = [];
                        $student->regularNotPublishedExamRegIds = [];
                        foreach($student->examRegistrations as $key => $examRegistration){
                            if( !($examRegistration->batchProperties->isResultPublished ) ||  (($examRegistration->batchProperties->isResultPublished) && (strtotime($examRegistration->batchProperties->publishingStartDate) > strtotime(date("Y-m-d H:i"))))) {
                                if($examRegistration->examType == 'REGULAR'){
                                    $student->regularNotPublishedExamRegIds[] = $examRegistration->id;
                                }
                                unset($student->examRegistrations[$key]);
                            }
                            else if(($examRegistration->examType) != 'REGULAR'){
                                if(!empty($examRegistration->blockReasons) || $examRegistration->isResultWithHeld == '1'){
                                    unset($student->examRegistrations[$key]);
                                }
                            }
                            else{
                                if($examRegistration->isResultWithHeld == '1'){
                                    $student->withHeldExamRegIds[] = $examRegistration->id;
                                    unset($student->examRegistrations[$key]);
                                }
                            }
                        }
                        $student->examRegistrationIds = array_column($student->examRegistrations,'id');
                    }
                    foreach($student->academicTerms as $academicKey => $academicTerm){
                        $academicTerm->isWithHeld = false;
                        if($searchRequest->isStaffSideRequest == 'true'){
                            foreach($academicTerm->subjects as $subject){
                                usort($subject->subjectMarkHistory, function($a, $b) {
                                    return ($a->examYear."-".date("m", mktime(0, 0, 0, (int)$a->examMonth, 10))."-".$a->examMarkType) < ($b->examYear."-".date("m", mktime(0, 0, 0, (int)$b->examMonth, 10))."-".$b->examMarkType);
                                });
                                foreach($subject->subjectMarkHistory as $subjectMarkHistory){
                                    if(in_array($subjectMarkHistory->examRegistrationId,$student->examRegistrationIds)){
                                        if ( $subjectMarkHistory->hasRevaluationMark ){
                                            $currentRegistration = reset(array_filter($revaluationRegistrations,function($value)use($subjectMarkHistory){
                                                return $value->id == $subjectMarkHistory->revaluationId;
                                            }));
                                            $revaluationBatch = reset($currentRegistration->groups);
                                            if ( $revaluationBatch->properties->isResultPublished == 1 && strtotime($revaluationBatch->properties->publishingStartDate) < strtotime(date("Y-m-d H:i"))){
                                                $subject->subjectFailedStatus = $subjectMarkHistory->resultStatus;
                                                $subject->creditGradePoint = $subjectMarkHistory->creditGradePoint;
                                            }
                                            else{
                                                $subject->subjectFailedStatus = $subjectMarkHistory->withoutRevaluationIsFailed == 1 ? 'FAILED' : 'PASSED' ;
                                                $subject->creditGradePoint = $subjectMarkHistory->withoutRevaluationCreditGradePoint;
                                            }
                                        }
                                        else{
                                            $subject->subjectFailedStatus = $subjectMarkHistory->resultStatus;
                                            $subject->creditGradePoint = $subjectMarkHistory->creditGradePoint;
                                        }
                                        break;
                                    }  
                                }
                                if ( $subjectMarkHistory->examMarkType == 'SUPPLY' &&  $subject->subjectFailedStatus == 'FAILED'){
                                    $regularHistory = reset(array_filter($subject->subjectMarkHistory,function($value){
                                        return $value->examMarkType == "REGULAR" AND $value->resultStatus == "PASSED";
                                    }));
                                    if ( $regularHistory && $regularHistory->hasRevaluationMark){
                                        $currentRegistration = reset(array_filter($revaluationRegistrations,function($value)use($regularHistory){
                                            return $value->id == $regularHistory->revaluationId;
                                        }));
                                        $revaluationBatch = reset($currentRegistration->groups);
                                        if ( $revaluationBatch->properties->isResultPublished == 1 && strtotime($revaluationBatch->properties->publishingStartDate) < strtotime(date("Y-m-d H:i"))){
                                            $subject->subjectFailedStatus = $regularHistory->resultStatus;
                                            $subject->creditGradePoint = $regularHistory->creditGradePoint;
                                        }
                                    }
                                }
                            }
                            // usort($academicTerm->semesterMarkHistory, function($a, $b) {
                            //     return ($a->examYear."-".date("m", mktime(0, 0, 0, (int)$a->examMonth, 10))) < ($b->examYear."-".date("m", mktime(0, 0, 0, (int)$b->examMonth, 10)));
                            // });
                            $regularHistory = array_filter($academicTerm->semesterMarkHistory,function($value){
                                return $value->historyType == "REGULAR";
                            });
                            $supplyHistory = array_filter($academicTerm->semesterMarkHistory,function($value){
                                return $value->historyType == "SUPPLEMENTARY";
                            });
                            usort($supplyHistory, function($a, $b) {
                                return ($a->examYear."-".date("m", mktime(0, 0, 0, (int)$a->examMonth, 10))) < ($b->examYear."-".date("m", mktime(0, 0, 0, (int)$b->examMonth, 10)));
                            });
                            $academicTerm->semesterMarkHistory = array_merge($supplyHistory, $regularHistory);
                            foreach($academicTerm->semesterMarkHistory as $semesterMarkHistory){
                                if(in_array($semesterMarkHistory->examRegistrationId,$student->examRegistrationIds)){
                                    if ( $semesterMarkHistory->hasRevaluationMark ){
                                        $currentRegistration = reset(array_filter($revaluationRegistrations,function($value)use($semesterMarkHistory){
                                            return $value->id == $semesterMarkHistory->revaluationId;
                                        }));
                                        $revaluationBatch = reset($currentRegistration->groups);
                                        if ( $revaluationBatch->properties->isResultPublished == 1 && strtotime($revaluationBatch->properties->publishingStartDate) < strtotime(date("Y-m-d H:i"))){
                                            $academicTerm->sgpa = $semesterMarkHistory->sgpa;
                                            $academicTerm->failedStatus = $semesterMarkHistory->failedStatus;
                                        }
                                        else{
                                            $academicTerm->sgpa = $semesterMarkHistory->withoutRevaluationsgpa;
                                            $academicTerm->failedStatus = $semesterMarkHistory->withoutRevaluationFailedStatus;
                                        }
                                    }
                                    else{
                                        $academicTerm->sgpa = $semesterMarkHistory->sgpa;
                                        $academicTerm->failedStatus = $semesterMarkHistory->failedStatus;
                                    }
                                    break;
                                }  
                                else if(in_array($semesterMarkHistory->examRegistrationId,$student->withHeldExamRegIds)){
                                    $academicTerm->sgpa = '-';
                                    $academicTerm->failedStatus = 'FAILED';
                                    $academicTerm->isWithHeld = true;
                                    break;
                                }
                                else if(in_array($semesterMarkHistory->examRegistrationId,$student->regularNotPublishedExamRegIds)){
                                    unset($student->academicTerms[$academicKey]);
                                    break;
                                }
                            }
                        }
                        $passedSubjects = [];
                        $passedSubjects = array_filter($academicTerm->subjects,function($value){
                            return $value->subjectFailedStatus == 'PASSED';
                        });
                        $academicTerm->earnedCredit = $academicTerm->isWithHeld ? 0 : array_sum(array_column($passedSubjects,'subjectCredit'));
                        $academicTerm->totalCreditGradePoint = array_sum(array_column($passedSubjects,'creditGradePoint'));
                        $academicTerm->totalCredit = array_sum(array_column($academicTerm->subjects,'subjectCredit'));
                        $yearCredits = $yearCredits + $academicTerm->earnedCredit;
                        $student->yearCredits[$academicTerm->id] = $yearCredits;
                    }
                    
                    $student->creditEarned = array_sum(array_column($student->academicTerms,'earnedCredit'));
                    $student->totalCredit = array_sum(array_column($student->academicTerms,'totalCredit'));
                    $student->totalCreditGradePoint = array_sum(array_column($student->academicTerms,'totalCreditGradePoint'));
                    $student->cgpa = $student->courseMarkDetails->rawCgpa ?? $student->cgpa;
                    if($searchRequest->isStaffSideRequest == 'true'){
                        $failedSemesters = array_filter($student->academicTerms,function($value){
                            return $value->failedStatus == 'FAILED';
                        });
                        if(empty($failedSemesters)){
                            $student->cgpa = $student->totalCreditGradePoint / $student->totalCredit;
                            $student->failedStatus = "PASSED";
                        }
                        else{
                            $student->failedStatus = "FAILED";
                        }
                    }
                    $student->cgpa = sprintf('%0.2f', round($student->cgpa, 2));
                    if($searchRequest->isPassedStudentsOnly == 'true'){
                        $failedSemesters = [];
                        $failedSemesters = array_filter($student->academicTerms,function($value){
                            return $value->failedStatus == 'FAILED';
                        });
                        if(!empty($failedSemesters)){
                            unset($studentsDetails[$key]);
                        }
                        if( $student->academicStatus == "FAILED"){ 
                            unset($studentsDetails[$key]);
                        }
                    }
                }
                if(empty($studentsDetails)){
                    throw new ExamControllerException(ExamControllerException::NO_STUDENTS_IN_THIS_EXAM_REGISTRATION,"No Student(s) Found");
                }
                $additionalDetails->groupName = reset($studentsDetails)->groupName;
                $additionalDetails->admissionYear = reset($studentsDetails)->admissionYear;
                $additionalDetails->disableCollegeRegisterNumber = $additionalDetails->admissionYear >= '2023' ? true : false;
                $additionalDetails->showYearCredits = $searchRequest->isPassedStudentsOnly == 'true' ? false : true;
                $additionalDetails->showYearCredits = reset($studentsDetails)->courseType != "UG" ? false : $additionalDetails->showYearCredits;
                $additionalDetails->showYearCredits = reset($studentsDetails)->courseType != "UG" ? false : $additionalDetails->showYearCredits;
                $baseUrl = "http://".$_SERVER['HTTP_HOST'];
        
                $collegeCode = $GLOBALS['COLLEGE_CODE'];
        
                $additionalDetails->collageLogo = "$baseUrl/libcommon/images/college/$collegeCode/logo.png";
                $examType = "EC_GRADUATION_BATCH_REPORT";
                $reportTemplate = StudentMarkListService::getInstance()->getUniversityMarkListTemplate($examType);
                if($reportTemplate && $reportTemplate == "Template_6"){
                    $templateName = "GraduationBatchReport_scek";
                }
                else{
                    $templateName = "GraduationBatchReport";
                }
                $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/ConsolidatedReports/$templateName.twig"), [ 'studentsDetails'=>$studentsDetails ,'additionalDetails'=>$additionalDetails]);
                $prtContent = NULL;
                $prtContent .= '<html><head>';
                $prtContent .= "<style>
                    h6 {font-size: 26px;} .text-center { text-align: center;} .align-middle {vertical-align: middle;}; tr.noBorder td {border: 0;  border-collapse:collapse;}
                    table, th, td {border: 1px solid black;border-collapse: collapse;}
                    </style>";
                $prtContent .= '</head><title>Pass Percentage Report</title><body>';
                $prtContent .= $responseHtml;
                $prtContent .= '</body></html>';
                $totalWidth = 310;
                $totalHeight = 297;
                $options = array(
                    'page-width'     => $totalWidth."mm",
                    'page-height'    => $totalHeight."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->printData = PdfUtil::renderPdf($prtContent, $options);
            return  $programResult;
            }
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
    public function getTranscriptMarksCard($searchRequest){
        $searchRequest = $this->realEscapeObject($searchRequest);
        $request = new \stdClass;
        $request->groupId = $searchRequest->groupId;
        $request->studentId = $searchRequest->studentId;
        $programResult = TranscriptMarkCardGenerator::getInstance()->getTranscriptMarksCardResulData($request);
        return $programResult;
    }
    /** list of supplementary exam's month and year semsterwise 
     * @param $request
     */
    public function getSupplyExamMonthAndYearSemesterWise($searchRequest)
    {
        $searchRequest = $this->realEscapeObject($searchRequest);
        $condition = '';
        if(empty($searchRequest->groupId)){
            throw new ProfessionalException(ProfessionalException::INVALID_REQUEST, 'Batch id is empty');
        }
        try {
            $groupIdString =  is_array($searchRequest->groupId) ? "'" . implode("','",$searchRequest->groupId) . "'" : "'".$searchRequest->groupId."'";
            $condition = " AND eerb.groups_id IN ($groupIdString)";
            $sql = "SELECT 
                        eerb.properties->>'$.academicTermId' AS semId,
                        eer.id,
                        eer.properties->>'$.examYear' AS examYear,
                        eer.properties->>'$.examMonth' AS examMonth
                    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.ec_exam_registration_type = eer.`type` AND
                        esar.am_assessment_id = eers.am_assessment_id
                        AND esar.properties->>'$.registrationType' = eer.`type`
                    WHERE
                        eer.`type` = 'SUPPLEMENTARY' AND eer.trashed IS NOT NULL $condition
                    GROUP BY 
                        eer.id 
                    ORDER BY
                        eer.properties->>'$.examYear',
                        CAST(eer.properties->>'$.examMonth' AS UNSIGNED ) ASC";
            $examDetails = $this->executeQueryForList($sql);
        } catch (\Exception $e) {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        $semesterWiseDetails = [];
        foreach ($examDetails as $examDetail) {
            $semesterWiseDetails[$examDetail->semId]->exams[] = $examDetail;
        }
        return $semesterWiseDetails;
    }
     /**
     * get Student Status Report 
     * @param $searchRequest 
     * @return $programResult 
     */
    public function getStudentStatusReport($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $request = new \stdClass;
            $additionalDetails = new \stdClass;
            $request->groupId = $searchRequest->groupId;
            $academicTermId = $searchRequest->academicTermId;
            $studentsDetails = $this->getAllStudentSemesterAndOverallMarkDetails($request);
            $semesterDetails = CommonExamService::getInstance()->getAcademicTermDetailsUptoCurrentAcademicTermId($academicTermId);
            uasort($semesterDetails, function ($a, $b) {
                return $a->orderNo > $b->orderNo;
            });
            $additionalDetails->semesters = $semesterDetails;
            $additionalDetails->totalColSpan = (count($semesterDetails)* 4)  + 6 +(count($semesterDetails) * 2);
            $additionalDetails->collegeData = CommonExamService::getInstance()->getCollegeDetails();
            $additionalDetails->semHeadCount = count($semesterDetails);
            $additionalDetails->lastSemester = end($semesterDetails);
            $additionalDetails->firstSemester = reset($semesterDetails);
            $additionalDetails->batchDetails = reset(CommonExamService::getInstance()->getBatchGroupDetailsByGroupId($request));
            $accademicTermIds = array_column($semesterDetails, 'id');
            foreach($studentsDetails as $student){
                if(in_array($student->academicTermId,$accademicTermIds)){
                    $student->courseMarkDetails = json_decode($student->courseMarkDetails);
                    $student->semesterMarkDetails = json_decode($student->semesterMarkDetails);
                    $studentList[$student->studentId]->id = $student->studentId;
                    $studentList[$student->studentId]->name = $student->studentName;
                    $studentList[$student->studentId]->regNo = $student->regNo;
                    $studentList[$student->studentId]->failedStatus = $student->overallFailedStatus;
                    $studentList[$student->studentId]->semesters[$student->academicTermId]->id = $student->academicTermId;
                    $studentList[$student->studentId]->semesters[$student->academicTermId]->name = $student->academicTerm;
                    $studentList[$student->studentId]->semesters[$student->academicTermId]->orderNo = $student->senesterOrderNo;
                    $studentList[$student->studentId]->semesters[$student->academicTermId]->sgpa = $student->semesterMarkDetails->sgpa;
                    $studentList[$student->studentId]->semesters[$student->academicTermId]->credit =  $student->semesterMarkDetails->totalEarnedCredits;
                    $studentList[$student->studentId]->semesters[$student->academicTermId]->arrearCount = $student->semesterMarkDetails->arrearCount;
                    $studentList[$student->studentId]->semesters[$student->academicTermId]->failedStatus = $student->semesterFailedStatus;
                    $studentList[$student->studentId]->semesters[$student->academicTermId]->semesterCgpa = $student->semesterMarkDetails->semesterCgpa;
                    $studentList[$student->studentId]->semesters[$student->academicTermId]->failedStatus = $student->semesterFailedStatus;
                }
            }
            foreach($studentList as $student){
                $customFields = AmsCustomFieldsService::getInstance()->getAmsCustomFieldValue(AmsCustomFieldsEntities::STUDENT, $student->id, []);
                if( $customFields ){
                    $student->ktuCode = CommonExamService::getInstance()->getCustomFieldObjectList($customFields)->studentData->KTU_CODE;
                }
                $student->totalEarnedCredit = array_sum(array_column($student->semesters,'credit'));
                uasort($student->semesters, function ($a, $b) {
                    return $a->orderNo > $b->orderNo;
                });
                $arrearCount = 0;
                foreach($student->semesters as $semester){
                    $arrearCount += (int)$semester->arrearCount;
                    $semester->addedArrearCount = $arrearCount;
                }
            }
            
            $templateName = 'student_status_report_template';
            if(empty($studentList)){
                throw new ExamControllerException(ExamControllerException::NO_STUDENTS_IN_THIS_EXAM_REGISTRATION,"No Students Found");
            }
            else{
                $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/ConsolidatedReports/studentStatusReport/$templateName.twig"), [ 'studentList'=>$studentList ,'additionalInfo'=>$additionalDetails]);
                $prtContent = NULL;
                $prtContent .= '<html><head>';
                $prtContent .= "<style>
                    .primary-table th{
                        text-align:center;
                        background: none !important;
                        height: 20mm  !important;
                        padding: 1mm 1mm !important;
                        border:1px solid #000;
                    }
                    .primary-table td{
                        padding:10px 5px 10px 5px !important;
                        line-height:20px !important;
                        height:10mm !important;
                        text-align:center;
                        vertical-align:middle !important;
                        /* font-size: 12px !important;  */
                        border:1px solid #000;
                    }
                    </style>";
                $prtContent .= '</head><title>Supply Result Notification Report</title><body>';
                $prtContent .= $responseHtml;
                $prtContent .= '</body></html>';
                
                $totalWidth = 420;
                $totalHeight = 297;
                $options = array(
                    'page-width'     => $totalWidth."mm",
                    'page-height'    => $totalHeight."mm",
                    'dpi'            => 96,
                    'margin-top' => "5mm",
                    'margin-left' => "7mm",
                    'margin-right' => "7mm",
                    'margin-bottom' => "5mm",
                    'footer-spacing' => -10,
                    // '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->printData = PdfUtil::renderPdf($prtContent, $options);
            return  $programResult;
            }
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
    public function getStudentCgpaReport($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $request = new \stdClass;
            $additionalDetails = new \stdClass;
            global $COLLEGE_NAME, $autonomous, $PLACE;
            $additionalDetails->collageName = $COLLEGE_NAME;
            $additionalDetails->autonomous = $autonomous;
            $additionalDetails->place = $PLACE;
            $request->groupsId = $searchRequest->groupId;
            $request->groupId = $searchRequest->groupId;
            $request->passedStudentsOnly = true;
            $batchDetails = [];
            $batchDetailsArray = [];
            $studentsDetails = $this->getAllStudentSemesterWiseMarkDetails($request);
            foreach( $studentsDetails as $key =>  $student){
                $student->percentage = round($student->percentage, 2);
                $student->cgpa = round($student->cgpa, 2);
                if (count($student->academicTerms) < $student->finalSem) {
                    $student->failedStatus = "FAILED";
                }
                if ($student->failedStatus == "FAILED") {
                    unset($studentsDetails[$key]);
                } 
                $student->examMonthYear = $student->latestExamMonth ?  date("M - Y", strtotime("01-" . $student->latestExamMonth . "-" . $student->latestExamYear)) : "";
            }
            if(empty($studentsDetails)){
                throw new ExamControllerException(ExamControllerException::NO_STUDENTS_IN_THIS_EXAM_REGISTRATION,"No Student(s) Found");
            }
            $additionalDetails->groupName = reset($studentsDetails)->groupName;
            $additionalDetails->admissionYear = reset($studentsDetails)->admissionYear;
            $additionalDetails->collegeData = CommonExamService::getInstance()->getCollegeDetails();
            $templateName = "StudentCgpaReport";
            $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/ConsolidatedReports/$templateName.twig"), [ 'studentsDetails'=>$studentsDetails ,'additionalDetails'=>$additionalDetails]);
            $prtContent = NULL;
            $prtContent .= '<html><head>';
            $prtContent .= "<style>
                h6 {font-size: 26px;} .text-center { text-align: center;} .align-middle {vertical-align: middle;}; tr.noBorder td {border: 0;  border-collapse:collapse;}
                table, th, td {border: 1px solid black;border-collapse: collapse;}
                </style>";
            $prtContent .= $responseHtml;
            $prtContent .= '</body></html>';
            $totalWidth = 310;
            $totalHeight = 297;
            $options = array(
                'page-width'     => $totalWidth."mm",
                'page-height'    => $totalHeight."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->printData = PdfUtil::renderPdf($prtContent, $options);
            return  $programResult;
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
         /**
     * get All Students (Semester Wise)Details
     * @param $searchRequest 
     * @return $studentDetails 
     */
    public function getAllStudentSemesterWiseConsolidatedMarkDetails($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try
        {
            $orderBy = " ORDER BY d.departmentDesc ASC, spa.properties->>'$.registerNumber' ASC";
            $whereQuery = "";
            if(!empty($searchRequest->courseTypeId)) {
                $whereQuery .= " AND p.course_type_id = '$searchRequest->courseTypeId'";
            }
            if(!empty($searchRequest->admissionYear)) {
                $whereQuery .= " AND g.properties ->> '$.startYear' = '$searchRequest->admissionYear'";
            }
            if(!empty($searchRequest->groupsId)) {
                $whereQuery .= " AND g.id = '$searchRequest->groupsId'";
            }
            if(!empty($searchRequest->passedStudentsOnly)) {
                if($searchRequest->passedStudentsOnly == true){
                    $whereQuery .= " AND esmd.failed_status = 'PASSED'";
                }
            }
            if(!empty($searchRequest->examRegistrationIds)) {
                $examRegistrationIdString= "'" . implode("', '", $searchRequest->examRegistrationIds) . "'" ;
                $whereQuery .= " AND eer.id IN ($examRegistrationIdString)";
            }
            $query = "SELECT DISTINCT
                    sa.studentID as studentId,
                    sa.studentName,
                    spa.properties->>'$.registerNumber' as regNo,
                    g.id as groupId,
                    g.name as groupName,
                    g.properties ->> '$.startYear' as admissionYear,
                    g.properties ->> '$.finalTermId' as finalSem,
                    act.id as academicTermId,
                    act.name as academicTerm,
                    act.properties ->> '$.orderNo' as termOrderNo,
                    p.name as programName,
                    d.deptName,
                    d.departmentDesc as departmentDescription,
                    d.deptID,
                    esmd.sgpa as semesterSgpa,
                    esmd.credit as semesterCredit,
                    esmd.percentage as semesterPercentage, 
                    esmd.grade as semesterGrade,
                    esmd.failed_status as semesterFailedStatus,
                    ecmdcourse.failed_status as courseFailedStatus,
                    ecmdcourse.cgpa,
                    ecmdcourse.percentage as coursePercentage,
                    ecmdcourse.grade as courseGrade,
                    ecmdcourse.mark_details->>'$.latestExamMonth' as latestExamMonth,
                    ecmdcourse.mark_details->>'$.latestExamYear' as latestExamYear,
                    ecmdcourse.mark_details AS courseMarkDetails,
                    eers.cm_academic_paper_subjects_id as academicPaperSubjectId,
                    esmdsubcon.mark_details ->>'$.credit' AS subjectCredit,
                    esmdsubcon.mark_details ->>'$.totalMarks' AS subjectTotalMarks,
                    esmdsubcon.mark_details ->>'$.markObtained' AS subjectMarkObtained,
                    esmdsubcon.failed_status AS subjectFailedStatus,
                    ct.course_Type as courseType,
                    esmd.mark_history as semesterMarkHistory,
                    esmdsubcon.mark_history as subjectMarkHistory,
                    eer.id as examRegId,
                    eerb.properties as examBatchProperties,
                    eserd.properties->>'$.isResultWithHeld' AS isResultWithHeld,
                    eer.type as examType,
                    spa.academic_status AS academicStatus
            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' AND 
                CAST(esar.properties ->> '$.feeStatus' AS CHAR) = 'PAID' AND 
                esar.ec_exam_registration_type = eer.type
            INNER JOIN studentaccount sa ON 
                sa.studentID = esar.student_id
            INNER JOIN ec_student_exam_registration_details eserd ON eserd.student_id = sa.studentID AND 
                eserd.ec_exam_registration_id = eer.id 
            INNER JOIN student_program_account spa ON 
                spa.student_id  = esar.student_id  
            INNER JOIN `groups` g ON g.id = spa.current_batch_id
            INNER JOIN program p 
                ON p.id  = g.properties->>'$.programId'AND p.id =  spa.current_program_id
            INNER JOIN department d ON
                d.deptID = g.properties ->> '$.departmentId'
            INNER JOIN course_type ct ON
                ct.courseTypeID = p.course_type_id
            INNER JOIN  academic_term act ON 
                act.id = CAST(eerb.properties ->> '$.academicTermId'AS CHAR)
            INNER JOIN ec_semester_mark_details esmd ON
                esmd.groups_id = eerb.groups_id AND esmd.academic_term_id = act.id AND esmd.student_id = sa.studentID 
            LEFT JOIN  ec_course_mark_details ecmdcourse ON ecmdcourse.student_id = sa.studentID 
            INNER JOIN ec_consolidated_subject_mark_details esmdsubcon ON
                esmdsubcon.groups_id = eerb.groups_id AND esmdsubcon.cm_academic_paper_subjects_id = eers.cm_academic_paper_subjects_id AND esmdsubcon.student_id = sa.studentID 
            WHERE 1=1 AND ( (eer.properties ->> '$.isHonorCourse' IS NULL OR eer.properties ->> '$.isHonorCourse' != '1') 
                AND (eer.properties ->> '$.isMinorCourse' IS NULL OR eer.properties ->> '$.isMinorCourse' != '1'))"; 
             $studentDetails = $this->executeQueryForList($query.$whereQuery.$orderBy, $this->mapper[FinalConsolidatedReportServiceMapper::SEMESTER_WISE_MARK_DETAILS]);
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $studentDetails;
    }        
    
     /**
     * get Student CGPA Report By Batch
     * @param $searchRequest 
     * @return $programResult 
     */
    public function getStudentForRankCertificate($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $request = new \stdClass;
            $additionalDetails = new \stdClass;
            $programResult = new \stdClass;
            global $COLLEGE_NAME, $autonomous, $PLACE;
            $additionalDetails->collageName = $COLLEGE_NAME;
            $additionalDetails->autonomous = $autonomous;
            $additionalDetails->place = $PLACE;
            // this groups ids tobe fetch current students details
            $request->groupIdList = $searchRequest->groupId;
            // for college requirement to get all students in batch
            // $request->passedStudentsOnly = true;
            $batchDetails = [];
            $batchDetailsArray = [];
            $studentsDetails = (array)$this->getAllStudentSemesterWiseMarkDetails($request);
            // remove not active students in selected batch
            foreach( $studentsDetails as $key =>  $student){
                if($student->academicStatus != "ACTIVE"){
                    unset($studentsDetails[$key]);
                }
            }
            // Fetch All Special Exam Details  by selected batches
            $requestForSpecialExam = new \stdClass;
            $requestForSpecialExam->isSpecialExamRegistration = true;
            $requestForSpecialExam->groupId = $searchRequest->groupId;
            $allSupplementaryExamRegistrations = (array) ExamRegistrationService::getInstance()->searchExamRegistrationByOtherDetails($requestForSpecialExam);
            $allSupplementaryExamRegistrationIds = array_column($allSupplementaryExamRegistrations,'id');
            $studentsCount = count($studentsDetails);
            $maxRank = round($studentsCount * 10 /100);
            $maxRank = ($maxRank > 10) ? 10 : $maxRank;
            foreach( $studentsDetails as $key =>  $student){
                $student->percentage = round($student->percentage, 2);
                $student->cgpa = round($student->courseMarkDetails->rawCgpa, 2);
                if (count($student->academicTerms) < $student->finalSem) {
                    $student->failedStatus = "FAILED";
                }
                if ($student->failedStatus == "FAILED") {
                    unset($studentsDetails[$key]);
                    continue;
                } 
                if($student->cgpa < 8){
                    unset($studentsDetails[$key]);
                    continue;
                }
                $isFailed = 0;
                foreach( $student->academicTerms as $academicTerm){
                    foreach( $academicTerm->subjects as $subject){
                        // check the subject have attend special exam then remove regular details in mark history
                        if(count($subject->subjectMarkHistory) == 2 && !empty($allSupplementaryExamRegistrationIds)){
                            $specialExamSubject = reset(array_filter($subject->subjectMarkHistory,function($value)use($allSupplementaryExamRegistrationIds){
                                return in_array($value->examRegistrationId, $allSupplementaryExamRegistrationIds);
                            }));
                            if(!empty($specialExamSubject)){
                                $subject->subjectMarkHistory = array_filter($subject->subjectMarkHistory,function($value)use($allSupplementaryExamRegistrationIds){
                                    return $value->examMarkType != 'REGULAR';
                                });
                            }
                        }
                        foreach( $subject->subjectMarkHistory as $subjectMarkHistory){
                            if ($subjectMarkHistory->resultStatus == "FAILED") {
                                $isFailed = 1;
                            } 
                        }
                    }
                }
                if ($isFailed == 1) {
                    unset($studentsDetails[$key]);
                    continue;
                } 
            }
            $additionalInfo = new \stdClass();
            $additionalInfo->totalStudents = $studentsCount;
            $rankStudents = $this->getRanksCalculated($studentsDetails, $maxRank);
            $programResult->students = $rankStudents ? $rankStudents : [];
            $programResult->additionalInfo = $additionalInfo;
            return  $programResult;
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
     /**
     * get Student CGPA Report By Batch
     * @param $searchRequest 
     * @return $programResult 
     */
    public function generateStudentRankCertificate($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        $student = (object)$searchRequest->student;
        $additionalInfo = (object)$searchRequest->additionalInfo;
        $programResult = new \stdClass();
        try {
            if (!empty($student)) {
                $student->rankInWords = CommonUtil::ordinalNumberInWords($student->rank);
                $student->examMonthYear = date("F Y", strtotime($student->latestExamYear . "-" . $student->latestExamMonth));
                $customFields = AmsCustomFieldsService::getInstance()->getAmsCustomFieldValue(AmsCustomFieldsEntities::STUDENT, $student->id, []);
                if( $customFields ){
                    $student->ktuCode = CommonExamService::getInstance()->getCustomFieldObjectList($customFields)->studentData->KTU_CODE;
                }
                $batchRequest = new \stdClass();
                $batchRequest->groupId = $student->groupId;
                $batchDetails = reset(CommonExamService::getInstance()->getBatchGroupDetailsByGroupId($batchRequest));
                $student->degreeName = $batchDetails->degreeName;
                $student->streamDesc = $batchDetails->streamDesc;
                if($student->courseType == "MTECH" || $student->courseType == "UG"){
                    $additionalInfo->enableSpecialization = true;
                }
                $additionalInfo->disableCollegeRegisterNumber = false;
                if($student->startYear >= '2023'){
                    $additionalInfo->disableCollegeRegisterNumber = true;
                }
                $student->yearOfStudy = $student->startYear . " - " . $student->endYear ;
                $student->qrcodeAllString = $student->registerNo.",".$student->name.",".$student->degreeName.",".$student->streamDesc;
                $templateName = "rankCertificate";
                $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/ConsolidatedReports/$templateName.twig"), [ 'student'=>$student ,'additionalInfo'=>$additionalInfo]);
            
                $totalWidth = 210;
                $totalHeight = 297;
                $options = array(
                    'page-width'     => $totalWidth."mm",
                    'page-height'    => $totalHeight."mm",
                    'dpi'            => 96,
                    'margin-top' => "120mm",
                    'margin-left' => "22mm",
                    'margin-right' => "22mm",
                    'margin-bottom' => "10mm",
                    // 'binary' => "/usr/local/bin/wkhtmltopdf", // For Mac
                    'user-style-sheet' => realpath(DOCUMENT_ROOT . "/libcommon/bootstrap/css/bootstrap.min.css")
                );
                $programResult->pdf = PdfUtil::renderPdf($responseHtml, $options);
            }
            return  $programResult;
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
    public function getRanksCalculated($students, $maxRank){
        $rankStudents = [];
        $studentCount = 0;
        $previousCgpa = 0;
        $skipRanks = 0;
        $rank = 1;
        uasort($students, function ($a, $b) {
            return $a->cgpa < $b->cgpa;
        });
        foreach ($students as $student) {
            $studentCount++;
            if ($previousCgpa !== null && $student->cgpa < $previousCgpa) {
                if ($studentCount > $maxRank) {
                    break;
                }
                $rank = $rank + 1; // Increase rank only if the current CGPA is less than the previous one
                $rank += $skipRanks; // Add skipped ranks to the current rank
                $skipRanks = 0; // Reset skipped ranks counter
            } elseif ($previousCgpa !== null && $student->cgpa === $previousCgpa) {
                $skipRanks++; // Increment skipped ranks if the current CGPA is the same as the previous one
            }
            // Assign the rank to the student
            $student->rank = $rank;
            $previousCgpa = $student->cgpa;
            $studentObject = new \stdClass();
            $studentObject->id = $student->id;
            $studentObject->name = $student->name;
            $studentObject->startYear = $student->startYear;
            $studentObject->endYear = $student->endYear;
            $studentObject->registerNo = $student->registerNo;
            $studentObject->groupId = $student->groupId;
            $studentObject->cgpa = $student->cgpa;
            $studentObject->courseType = $student->courseType;
            $studentObject->latestExamMonth = $student->latestExamMonth;
            $studentObject->latestExamYear = $student->latestExamYear;
            $studentObject->rank = $student->rank;
            $rankStudents[] = $studentObject;
        }
        return $rankStudents;
    }
     /**
     * get Student Overall Mark Report
     * @param $searchRequest 
     * @return $programResult 
     */
    public function getStudentOverallMarkReport($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $request = new \stdClass;
            $additionalDetails = new \stdClass;
            $request->groupsId = $searchRequest->groupId;
            $request->groupId = $searchRequest->groupId;
            $additionalDetails->semesters =CommonExamService::getInstance()->getAllAcademicTermsDetailsByBatch($request);
            $additionalDetails->finalSemOrderNo = max(array_column($additionalDetails->semesters, "OrderNo"));
            $studentsDetails = $this->getAllStudentSemesterWiseConsolidatedMarkDetails($request);
            
            if(empty($studentsDetails)){
                throw new ExamControllerException(ExamControllerException::NO_STUDENTS_IN_THIS_EXAM_REGISTRATION,"No Student(s) Found");
            }
            else{
                foreach( $studentsDetails as $key => $student){
                    uasort($student->academicTerms, function ($a, $b) {
                        return $a->orderNo > $b->orderNo;
                    });
                    foreach($student->academicTerms as $academicKey => $academicTerm){
                        $academicTerm->arrearsCount = count(array_filter($academicTerm->subjects,function($value){
                            return $value->subjectFailedStatus == 'FAILED';
                        }));
                        $academicTerm->earnedMarks = array_sum(array_column($academicTerm->subjects,'subjectMarkObtained'));
                        $academicTerm->totalMarks = array_sum(array_column($academicTerm->subjects,'subjectTotalMarks'));
                    }
                    
                    $student->earnedMarks = array_sum(array_column($student->academicTerms,'earnedMarks'));
                    $student->totalMarks = array_sum(array_column($student->academicTerms,'totalMarks'));
                    $student->percentage = $student->totalMarks ? ($student->earnedMarks / $student->totalMarks) * 100 : 0;
                    $student->cgpa = $student->courseMarkDetails->rawCgpa ?? $student->cgpa;
                    $student->class = $student->courseMarkDetails->class  ?? '-';
                    
                }
                if(empty($studentsDetails)){
                    throw new ExamControllerException(ExamControllerException::NO_STUDENTS_IN_THIS_EXAM_REGISTRATION,"No Student(s) Found");
                }
                $additionalDetails->groupName = reset($studentsDetails)->groupName;
                $additionalDetails->collegeData = CommonExamService::getInstance()->getCollegeDetails();
                $templateName = "StudentOverallMarkReport";
                $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/ConsolidatedReports/$templateName.twig"), [ 'studentsDetails'=>$studentsDetails ,'additionalDetails'=>$additionalDetails]);
                $prtContent = NULL;
                $prtContent .= '<html><head>';
                $prtContent .= "";
                $prtContent .= '</head><title>Pass Percentage Report</title><body>';
                $prtContent .= $responseHtml;
                $prtContent .= '</body></html>';
                $totalWidth = 420;
                $totalHeight = 297;
                $options = array(
                    'page-width'     => $totalWidth."mm",
                    'page-height'    => $totalHeight."mm",
                    'dpi'            => 96,
                    'margin-top' => "15mm",
                    'margin-left' => "10mm",
                    'margin-right' => "10mm",
                    'margin-bottom' => "15mm",
                    'disable-smart-shrinking',
                    // '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->printData = PdfUtil::renderPdf($prtContent, $options);
            return  $programResult;
            }
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
}