Ejemplo n.º 1
0
    /**
     * Пошук із врахування зовнішніх реляційних відношень.
     * Enjoy this code with smiles / %) %) %) /.
     * @param bool $return_array_of_models default false
     * @return \CActiveDataProvider
     */
    public function search_rel($return_array_of_models = false)
    {
        Yii::import('application.models.Qualifications');
        $rating_order_mode = 0;
        $page_size = 3;
        if (is_numeric($this->rating_order_mode)) {
            $rating_order_mode = $this->rating_order_mode;
        }
        if (is_numeric($this->page_size) && $this->page_size > 0) {
            $page_size = $this->page_size;
        }
        $criteria = new CDbCriteria();
        //З якими відношеннями маємо справу
        $with_rel = array();
        array_push($with_rel, 'sepciality');
        array_push($with_rel, 'person');
        array_push($with_rel, 'olymp');
        array_push($with_rel, 'entrantdoc');
        array_push($with_rel, 'educationForm');
        array_push($with_rel, 'edbo');
        array_push($with_rel, 'documentSubject1');
        array_push($with_rel, 'documentSubject2');
        array_push($with_rel, 'documentSubject3');
        array_push($with_rel, 'documentSubject1.subject1');
        array_push($with_rel, 'documentSubject2.subject2');
        array_push($with_rel, 'documentSubject3.subject3');
        //array_push($with_rel, 'ZnoKoef1');
        //array_push($with_rel, 'ZnoKoef2');
        //array_push($with_rel, 'ZnoKoef3');
        $with_rel['sepciality.facultet'] = array('select' => false);
        $with_rel['person.country'] = array('select' => false);
        $with_rel['status'] = array('select' => false);
        $with_rel['pbenefits'] = array('select' => false);
        $with_rel['pbenefits.psbenefit'] = array('select' => false);
        $with_rel['pbenefits.psbenefit.benefit'] = array('select' => false);
        $criteria->with = $with_rel;
        //також йде вибірка ::
        // ПІБ персон і спеціальності,
        // формат поля спеціальності: (( код_спеціальності назва_спеціальності[ (назва_напряму)] , форма: назва_форми ))
        // загальна сума балів для рейтингу,
        // кількість пільг,
        // список назв пільг (являє собою рядок із сепаратором : ";;"),
        // список ID пільг (являє собою рядок із сепаратором : ";;"),
        // список значень у документах (поле : AtestatValue, являє собою рядок із сепаратором : ";"),
        // список типів документів (являє собою рядок із сепаратором : ";"),
        // відмітка про позаконкурсний вступ або ж про те, що є відповідна пільга,
        // відмітка про першочерговий вступ або ж про те, що є відповідна пільга,
        // список відміток про позаконкурсний вступ (до відповідних пільг),
        // список відміток про першочерговий вступ (до відповідних пільг).
        // Остання редакція: Жиленко О.С. ЕПК
        $criteria->select = array('*', new CDbExpression("concat_ws(' ',trim(person.LastName),trim(person.FirstName),trim(person.MiddleName)) AS NAME"), new CDbExpression("concat_ws(' '," . "sepciality.SpecialityClasifierCode," . "(case substr(sepciality.SpecialityClasifierCode,1,1) when '6' then " . "sepciality.SpecialityDirectionName else sepciality.SpecialityName end)," . "(case sepciality.SpecialitySpecializationName when '' then '' " . " else concat('(',sepciality.SpecialitySpecializationName,')') end)" . ",',',concat('форма: ',educationForm.PersonEducationFormName)) AS SPEC"), new CDbExpression('ROUND(
            IF( ISNULL(entrantdoc.AtestatValue),
                0.0, 
                IF( t.QualificationID = ' . Qualifications::$bakalavr . ', 
                    set_bal(entrantdoc.AtestatValue)* ' . Yii::app()->params['scoreweight_AtestatValue'] . ' , 
                    entrantdoc.AtestatValue
                )
            )
          ,2) AS ZnoDocValue'), new CDbExpression('ROUND(
            IF(ISNULL(entrantdoc.AtestatValue),0.0,entrantdoc.AtestatValue),2) AS PointDocValue'), new CDbExpression('(ROUND((
        ROUND(
        IF( ISNULL(entrantdoc.AtestatValue),
                        0.0, 
                        IF( t.QualificationID = ' . Qualifications::$bakalavr . ', 
                            set_bal(entrantdoc.AtestatValue)* ' . Yii::app()->params['scoreweight_AtestatValue'] . ' , 
                            entrantdoc.AtestatValue
                        )
        ),2)+
        IF(ISNULL(documentSubject1.SubjectValue),0.0,documentSubject1.SubjectValue*sepciality.ZnoKoef1)+
        IF(ISNULL(documentSubject2.SubjectValue),0.0,documentSubject2.SubjectValue*sepciality.ZnoKoef2)+
        IF(ISNULL(documentSubject3.SubjectValue),0.0,documentSubject3.SubjectValue*sepciality.ZnoKoef3)+
        IF(ISNULL(t.AdditionalBall),0.0,t.AdditionalBall)+
        IF(ISNULL(t.CoursedpBall),0.0,t.CoursedpBall* ' . Yii::app()->params['scoreweight_CoursedpBall'] . ')+
        IF(ISNULL(olymp.OlympiadAwardBonus),0.0,olymp.OlympiadAwardBonus)+
        IF(ISNULL(t.Exam1Ball),0.0,t.Exam1Ball*sepciality.ZnoKoef1)+
        IF(ISNULL(t.Exam2Ball),0.0,t.Exam2Ball*sepciality.ZnoKoef2)+
        IF(ISNULL(t.Exam3Ball),0.0,t.Exam3Ball*sepciality.ZnoKoef3)),2)) AS ComputedPoints'), new CDbExpression('COUNT(DISTINCT benefit.idBenefit) AS cntBenefit'), new CDbExpression('IF(documentSubject1.SubjectID 
        IN(SELECT ssj.SubjectID FROM specialitysubjects ssj WHERE ssj.isProfile=1 AND ssj.SpecialityID=t.SepcialityID),
          documentSubject1.SubjectValue,
          IF(documentSubject2.SubjectID 
            IN(SELECT ssj.SubjectID FROM specialitysubjects ssj WHERE ssj.isProfile=1 AND ssj.SpecialityID=t.SepcialityID),
            documentSubject2.SubjectValue,
            IF(documentSubject3.SubjectID 
              IN(SELECT ssj.SubjectID FROM specialitysubjects ssj WHERE ssj.isProfile=1 AND ssj.SpecialityID=t.SepcialityID),documentSubject3.SubjectValue, 0
            )
          )
      ) AS ProfileSubjectValue'), new CDbExpression('GROUP_CONCAT(benefit.BenefitName ' . 'ORDER BY benefit.BenefitName ASC SEPARATOR \';;\') AS BenefitList'), new CDbExpression('GROUP_CONCAT(benefit.idBenefit ' . 'ORDER BY benefit.BenefitName ASC SEPARATOR \';;\') AS idBenefitList'), new CDbExpression('if(sum(benefit.isPZK)>0,1,0) AS isOutOfComp'), new CDbExpression('if(sum(benefit.isPV)>0,1,0) AS isExtraEntry'), new CDbExpression('GROUP_CONCAT(benefit.isPZK ' . 'ORDER BY benefit.BenefitName ASC SEPARATOR \';;\') AS isOutOfCompList'), new CDbExpression('GROUP_CONCAT(benefit.isPV ' . 'ORDER BY benefit.BenefitName ASC SEPARATOR \';;\') AS isExtraEntryList'), new CDbExpression('(SELECT SUM(IF((ISNULL(prsp.isCopyEntrantDoc) OR prsp.isCopyEntrantDoc = 0),1,0)) 
        FROM personspeciality prsp WHERE prsp.PersonID=t.PersonID) AS AnyOriginal'), new CDbExpression('(IF(ISNULL(documentSubject1.SubjectValue),0.0,documentSubject1.SubjectValue)+
        IF(ISNULL(documentSubject2.SubjectValue),0.0,documentSubject2.SubjectValue)+
        IF(ISNULL(documentSubject3.SubjectValue),0.0,documentSubject3.SubjectValue)) AS ZNOSum'), new CDbExpression('lower(IF(ISNULL(edbo.DocSeria),"none",edbo.DocSeria)) AS tDocSeria'), new CDbExpression('lower(IF(ISNULL(entrantdoc.Series),"none",transliterate(entrantdoc.Series))) AS tDocSeries'), new CDbExpression('CONCAT((CASE t.QualificationID 
                WHEN 1 THEN "Б" 
                WHEN 2 THEN "СМ" 
                WHEN 3 THEN "СМ" 
                WHEN 4 THEN "МС" END), t.CourseID, "-", LPAD(t.PersonRequestNumber,5,"0")) AS PersonCase'));
        //оформлення єдиного запиту на вибірку
        $criteria->together = true;
        //якщо прийшов searchID, то пошукати на співпадання з ID заявки, персони і ЄДЕБО
        if (is_numeric($this->searchID)) {
            $criteria->addCondition('(t.idPersonSpeciality=' . $this->searchID . ') ' . 'OR (person.idPerson=' . $this->searchID . ') ' . 'OR (t.edboID=' . $this->searchID . ')');
        } else {
            if (strlen($this->searchID) > 2) {
                $criteria->compare('status.PersonRequestStatusTypeName', $this->searchID, true);
            }
        }
        //пошук факультету з використанням частини рядка його назви
        $criteria->compare('facultet.FacultetFullName', $this->searchFaculty->FacultetFullName, true);
        // Yii::log("abit-ext-param:".$this->ext_param, CLogger::LEVEL_INFO, 'system.db.x');
        switch ($this->ext_param) {
            case 1:
                //якщо встановлений прапорець, щоб шукати лише неточності (неспівпадання у нас і даними ЄДЕБО)
                // тоді додаткові умови ::
                //  щоб сума усіх балів не співпадала
                //  щоб ПІБ не співпадало
                //  щоб країна громадянства не співпадала
                //  щоб відмітка у документі (атестат або диплом) не співпадала
                //  щоб номер і серія документа (атестата або диплому) не співпадали
                //  щоб відмітка першочерговості не співпадала
                //  щоб відмітка позаконкурсного вступу не співпадала
                //  щоб відмітка вступу за цільовим направленням не співпадала
                //  щоб відмітка копії/оригінала не співпадала
                //  щоб напрям або спеціальність або форма не співпадали
                //  щоб статус заяви не співпадав
                //  --! щоб серія документа вступу не співпадала
                //    OR (lower(IF(ISNULL(entrantdoc.Series),"none",entrantdoc.Series)) COLLATE utf8_unicode_ci
                //    NOT LIKE lower(IF(ISNULL(edbo.DocSeria),"none",edbo.DocSeria)) COLLATE utf8_unicode_ci)
                //    Qualifications::$bakalavr
                // Yii::log(" Qualifications::bakalavr:", CLogger::LEVEL_INFO, 'system.db.x');
                // Yii::log(" Qualifications::bakalavr:". Qualifications::$bakalavr, CLogger::LEVEL_INFO, 'system.db.x');
                $criteria->addCondition('
        (
            ABS(

                (
                    IF( ISNULL(entrantdoc.AtestatValue),
                        0.0, 
                        IF( t.QualificationID = ' . Qualifications::$bakalavr . ', 
                            set_bal(entrantdoc.AtestatValue)* ' . Yii::app()->params['scoreweight_AtestatValue'] . ' , 
                            entrantdoc.AtestatValue
                        )
                    )
                    +

                    IF(ISNULL(documentSubject1.SubjectValue),0.0,documentSubject1.SubjectValue*sepciality.ZnoKoef1)+
                    IF(ISNULL(documentSubject2.SubjectValue),0.0,documentSubject2.SubjectValue*sepciality.ZnoKoef2)+
                    IF(ISNULL(documentSubject3.SubjectValue),0.0,documentSubject3.SubjectValue*sepciality.ZnoKoef3)+
                    IF(ISNULL(t.AdditionalBall),0.0,t.AdditionalBall)+
                    IF(ISNULL(t.CoursedpBall),0.0,t.CoursedpBall*' . Yii::app()->params['scoreweight_CoursedpBall'] . ')+
                    IF(ISNULL(olymp.OlympiadAwardBonus),0.0,olymp.OlympiadAwardBonus)+
                    IF(ISNULL(t.Exam1Ball),0.0,t.Exam1Ball*sepciality.ZnoKoef1)+
                    IF(ISNULL(t.Exam2Ball),0.0,t.Exam2Ball*sepciality.ZnoKoef2)+
                    IF( ISNULL(t.Exam3Ball),0.0,t.Exam3Ball*sepciality.ZnoKoef3)
                )
                - edbo.RatingPoints
            ) > 0.001
            
            OR
            
            (
                REPLACE(
                    REPLACE(
                        REPLACE( 
                            concat_ws(\' \',trim(person.LastName),trim(person.FirstName),trim(person.MiddleName)), 
                            "  ", " "
                        ),
                        "  ", " "
                    ), 
                    "  ", " "
                ) 
                NOT LIKE 
                REPLACE( 
                    REPLACE( 
                        REPLACE( 
                            edbo.PIB, "  ", " "
                        ), 
                        "  ", " " 
                     ), "  ", " " 
                )
            )
        
            OR (edbo.Country NOT LIKE country.CountryName) 
            
            OR (ROUND(edbo.DocPoint,2) <> ROUND(
                IF(ISNULL(entrantdoc.AtestatValue),0.0,entrantdoc.AtestatValue),2)) 
            
            OR (edbo.DocNumber NOT LIKE entrantdoc.Numbers) 
        
            OR (edbo.Benefit <> 
              if(isnull(benefit.isPZK),0,benefit.isPZK))
            
            OR (edbo.PriorityEntry <> 
              if(isnull(benefit.isPV),0,benefit.isPV))

            OR (edbo.Quota=0 AND t.QuotaID > 0)
            OR (edbo.Quota=1 AND (t.QuotaID IS NULL OR t.QuotaID = 0))
        
            OR (edbo.OD=1 AND t.isCopyEntrantDoc=1)
            OR (edbo.OD=0 AND (t.isCopyEntrantDoc IS NULL OR t.isCopyEntrantDoc = 0))
            
            OR (
                (edbo.EduForm NOT LIKE educationForm.PersonEducationFormName) 
                OR (edbo.Direction NOT LIKE sepciality.SpecialityDirectionName AND t.QualificationID = 1) 
                OR (edbo.Speciality NOT LIKE sepciality.SpecialityName AND t.QualificationID > 1) 
                OR (sepciality.SpecialitySpecializationName NOT LIKE CONCAT("%",edbo.Specialization,"%"))
            )
            OR (
                MID(status.PersonRequestStatusTypeName,1,6) COLLATE utf8_unicode_ci NOT LIKE MID(edbo.Status,1,6)
            ) 
        ) AND edbo.ID IS NOT NULL');
                break;
            case 4:
                //якщо встановлений прапорець, щоб шукати лише неточності в оригіналах
                // тоді додаткові умови ::
                //  щоб відмітка копії/оригінала не співпадала
                $criteria->addCondition('(
       (edbo.OD=1 AND t.isCopyEntrantDoc=1)
          OR (edbo.OD=0 AND (t.isCopyEntrantDoc IS NULL OR t.isCopyEntrantDoc = 0)))');
                break;
            case 5:
                //якщо встановлений прапорець, щоб шукати лише неточності в балах
                // тоді додаткові умови ::
                //  щоб відмітка у документі (атестат або диплом) не співпадала
                $criteria->addCondition('(
        (ROUND(edbo.DocPoint,2) <> ROUND(
            IF(ISNULL(entrantdoc.AtestatValue),0.0,entrantdoc.AtestatValue),2)))');
                break;
            case 6:
                //якщо встановлений прапорець, щоб шукати лише неточності у відмітках пільгового вступу
                // тоді додаткові умови ::
                //  ??????щоб відмітка першочерговості не співпадала
                //  щоб відмітка позаконкурсного вступу не співпадала
                //  щоб відмітка вступу за цільовим направленням не співпадала
                $conditionPart = '(
           ( edbo.Benefit <> BIT_OR(IFNULL(benefit.isPZK,0))   )
    
        OR (edbo.PriorityEntry <> BIT_OR(IFNULL(benefit.isPV,0)) )

        OR (edbo.Quota=0 AND t.QuotaID > 0)
        OR (edbo.Quota=1 AND (t.QuotaID IS NULL OR t.QuotaID = 0)))';
                if (strlen($criteria->having) > 0) {
                    $criteria->having .= ' AND ' . $conditionPart;
                } else {
                    $criteria->having = $conditionPart;
                }
                break;
            case 7:
                //якщо встановлений прапорець, щоб шукати лише неточності в сумі балів ЗНО
                // тоді додаткові умови ::
                //
                $criteria->addCondition('(
               ABS(
                  - SUBSTRING(LEFT(edbo.DetailPoints,LOCATE("+Е:",edbo.DetailPoints)-1),LOCATE("+ЗНО:",edbo.DetailPoints)+5)
                  + 
                  (
                     IF(ISNULL(documentSubject1.SubjectValue),0.0,documentSubject1.SubjectValue*sepciality.ZnoKoef1)
                     +
                     IF(ISNULL(documentSubject2.SubjectValue),0.0,documentSubject2.SubjectValue*sepciality.ZnoKoef2)
                     +
                     IF(ISNULL(documentSubject3.SubjectValue),0.0,documentSubject3.SubjectValue*sepciality.ZnoKoef3)
                  )
               ) > 0.001
      )');
                break;
            case 8:
                //якщо встановлений прапорець, щоб шукати лише неточності для країни громадянства
                // тоді додаткові умови ::
                //
                $criteria->addCondition('(edbo.Country NOT LIKE country.CountryName)');
                break;
                //якщо встановлений прапорець, щоб шукати лише неточності для аттестату
                // Жиленко О.С.
            //якщо встановлений прапорець, щоб шукати лише неточності для аттестату
            // Жиленко О.С.
            case 9:
                $criteria->addCondition('(entrantdoc.TypeID = 2)  AND ' . '(' . '(lower(transliterate(edbo.DocSeria)) <> lower(transliterate(entrantdoc.Series)))' . 'OR (edbo.DocNumber <> entrantdoc.numbers)' . 'OR (ROUND(edbo.DocPoint,2) <> ROUND(IF(ISNULL(entrantdoc.AtestatValue),0.0,entrantdoc.AtestatValue),2))' . 'OR (edbo.DocDate <> STR_TO_DATE(entrantdoc.DateGet, \'%Y/%m/%d\'))' . ')');
                break;
        }
        if ($rating_order_mode) {
            //якщо сортувати для рейтингу, тоді відібрати лише потрібні статуси заявок
            $status_in = '(';
            $status_ids = array();
            if ($this->status_confirmed) {
                $status_ids[] = '4';
            }
            if ($this->status_committed) {
                $status_ids[] = '5';
            }
            if ($this->status_submitted) {
                $status_ids[] = '7';
            }
            $status_in .= implode(',', $status_ids) . ')';
            if ($status_in != '()') {
                $criteria->addCondition('t.StatusID IN ' . $status_in);
            } else {
                $criteria->addCondition('t.StatusID IN (1,4,5,7,8)');
            }
        }
        if ($this->ext_param == 3) {
            //якщо потрібно вибрати тільки ті дані, що відповідають даним з таблиці edbo_data
            $criteria->addCondition('edbo.ID IS NOT NULL');
        }
        if ($this->ext_param == 2) {
            //якщо потрібно вибрати тільки ті дані, що не відповідають даним з таблиці edbo_data
            $criteria->addCondition('edbo.ID IS NULL');
        }
        if ($this->ForeignOnly) {
            $criteria->addCondition('country.CountryName NOT LIKE "Україна"');
        }
        if (is_numeric($this->searchBenefit->BenefitName)) {
            //якщо частина назви пільги - число, то сприймати це як кількість пільг
            $criteria->having = 'cntBenefit=' . $this->searchBenefit->BenefitName;
            if ($this->searchBenefit->BenefitName > 1) {
                $page_size = 1000;
            }
        }
        if (!is_numeric($this->searchBenefit->BenefitName)) {
            //пошук за частиною назви пільги
            $criteria->compare('benefit.BenefitName', $this->searchBenefit->BenefitName, true);
        }
        if ($this->NAME) {
            //пошук прізвища
            $name_keys = explode(' ', $this->NAME);
            foreach ($name_keys as $key) {
                $criteria->addCondition('concat_ws(" ",person.LastName,person.FirstName,person.MiddleName) ' . 'LIKE "%' . $key . '%"');
            }
        }
        if (is_numeric($this->QualificationID) && $this->QualificationID > 0 && !$rating_order_mode) {
            $criteria->compare('t.QualificationID', $this->QualificationID);
        }
        if (is_numeric($this->CourseID) && $this->CourseID > 0 && !$rating_order_mode) {
            $criteria->compare('t.CourseID', $this->CourseID);
        }
        if ($this->DateFrom && $this->DateTo && !$rating_order_mode) {
            $condition_date1 = date('Y-m-d', strtotime(str_replace('.', '-', $this->DateFrom))) . ' 00:00:00';
            $condition_date2 = date('Y-m-d', strtotime(str_replace('.', '-', $this->DateTo))) . ' 23:59:59';
            $criteria->addCondition("t.CreateDate BETWEEN '" . $condition_date1 . "' " . "AND '" . $condition_date2 . "'");
        }
        if ($this->SPEC && !$rating_order_mode) {
            //пошук спеціальності та спеціалізації
            $keys = explode(' ', $this->SPEC);
            foreach ($keys as $key) {
                $criteria->addCondition("concat_ws(' '," . "sepciality.SpecialityClasifierCode," . "(case substr(sepciality.SpecialityClasifierCode,1,1) when '6' then " . "sepciality.SpecialityDirectionName else sepciality.SpecialityName end)," . "(case sepciality.SpecialitySpecializationName when '' then '' " . " else concat('(',sepciality.SpecialitySpecializationName,')') end)" . ",',',concat('форма: ',educationForm.PersonEducationFormName)) LIKE '%" . $key . "%'");
            }
        } else {
            if ($rating_order_mode) {
                $criteria->compare("t.SepcialityID", $this->SepcialityID);
            }
        }
        //дані групуються по ІД заявки
        $criteria->group = "t.idPersonSpeciality";
        //параметр сортування даних для формування рейтингу
        $rating_order = 'isOutOfComp DESC,' . 'IF (t.QuotaID IS NULL, 0, t.QuotaID) DESC,' . 'ComputedPoints DESC,' . 'IF(SUM(benefit.isPV)>0,1,0) DESC, 
            IF(ISNULL(entrantdoc.PersonDocumentsAwardsTypesID),0,10-entrantdoc.PersonDocumentsAwardsTypesID) DESC, 
            ProfileSubjectValue DESC';
        //якщо є відмітка першочергового вступу - що ж... нехай щастить!
        if ($rating_order_mode > 0) {
            //якщо сортувати треба для формування рейтингу
            $criteria->order = $rating_order;
            //відобразаити усі записи на одній сторінці
            $page_size = 50000;
            Personspeciality::$is_rating_order = true;
        }
        if ($return_array_of_models) {
            //для формування рейтингу в Excel-файлі
            return Personspeciality::model()->findAll($criteria);
        }
        //стандартно повертається джерело даних
        $dataProvider = new CActiveDataProvider($this, array('criteria' => $criteria, 'sort' => array('defaultOrder' => array('idPersonSpeciality' => CSort::SORT_DESC), 'attributes' => array('NAME' => array('asc' => 'NAME', 'desc' => 'NAME DESC'), 'SPEC' => array('asc' => 'SPEC', 'desc' => 'SPEC DESC'), 'benefit.BenefitName' => array('asc' => 'benefit.BenefitName', 'desc' => 'benefit.BenefitName DESC'), 'facultet.FacultetFullName' => array('asc' => 'facultet.FacultetFullName', 'desc' => 'facultet.FacultetFullName DESC'), '*')), 'pagination' => array('pageSize' => $page_size)));
        //$dataProvider->setTotalItemCount(count($this->findAll($criteria)));
        return $dataProvider;
    }