HEX
Server: LiteSpeed
System: Linux premium260.web-hosting.com 4.18.0-553.45.1.lve.el8.x86_64 #1 SMP Wed Mar 26 12:08:09 UTC 2025 x86_64
User: aliazzsr (627)
PHP: 7.4.33
Disabled: NONE
Upload Files
File: /home/aliazzsr/api.crm.vqode.com/models/search/ProjectsStatistics.php
<?php
namespace app\models\search;

use app\components\formatters\DateFormatter;
use app\components\helpers\FormatHelper;
use app\models\core\Project;
use app\models\enums\ProjectsStatisticsGroup as Group;
use app\models\enums\StatisticsPeriod as Period;
use yii\behaviors\AttributeTypecastBehavior;
use yii\db\ActiveQuery;
use yii\db\Expression;
use yii\db\Query;
use yii\helpers\ArrayHelper;

class ProjectsStatistics extends Project
{
    /** @var string */
    public $group;

    /** @var string */
    public $period;

    protected $joinTable;
    protected $andWhere;

    protected $_joinAlias;

    protected $_bd;
    protected $_ed;

    public function init()
    {
        parent::init();

        $this->_joinAlias = 'grptab01';
    }

    public function formName()
    {
        return '';
    }

    public function rules()
    {
        return [
            [['group', 'period'], 'required'],
            [['group', 'period'], 'string'],
            [['group_id'], 'integer'],
            [['period'], 'validatePeriod'],
            [['group'], 'in', 'range' => Group::getConstantsByName(), 'message' => 'Unknown group.'],
            [['group', 'period', 'group_id'], 'safe'],
        ];
    }

    /**
     * Validates period and extracts interval limits
     */
    public function validatePeriod()
    {
        if (in_array($this->period, Period::getConstantsByName())) {
            return;
        }

        $dateFormat = '/^\d{2}\/\d{2}\/\d{4}$/';
        list($bd, $ed) = explode('-', $this->period);

        if (preg_match($dateFormat, $bd) && preg_match($dateFormat, $ed)) {
            $this->_bd = DateFormatter::toMysql($bd);
            $this->_ed = DateFormatter::toMysql($ed);
        } else {
            $this->addError('period', 'Invalid period.');
        }
    }

    /**
     * @inheritdoc
     */
    public function safeAttributes()
    {
        return [
            'group_id', 'group', 'period',
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributes()
    {
        return array_merge(parent::attributes(), [
            'group_id', 'group_name',
            'count', 'count_percentage',
            'value', 'value_percentage',
            'edv', 'edv_percentage',
            'efv', 'efv_percentage',
        ]);
    }

    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        $behaviors = parent::behaviors();

        $behaviors['projects_statistics'] = [
            'class' => AttributeTypecastBehavior::className(),
            'attributeTypes' => [
                'group_id' => AttributeTypecastBehavior::TYPE_INTEGER,
                'edv' => AttributeTypecastBehavior::TYPE_FLOAT,
                'efv' => AttributeTypecastBehavior::TYPE_FLOAT,
                'value' => AttributeTypecastBehavior::TYPE_FLOAT,
                'count' => AttributeTypecastBehavior::TYPE_INTEGER,
                'edv_percentage' => [FormatHelper::className(), 'toPercent'],
                'efv_percentage' => [FormatHelper::className(), 'toPercent'],
                'value_percentage' => [FormatHelper::className(), 'toPercent'],
                'count_percentage' => [FormatHelper::className(), 'toPercent'],
            ],
            'typecastAfterValidate' => true,
            'typecastBeforeSave' => true,
            'typecastAfterFind' => true,
        ];

        return $behaviors;
    }

    /**
     *
     * @return array
     */
    public function search()
    {
        $this->resolveJoinTable();

        $query = self::find();
        $query->joinWith($this->joinTable . ' as ' . $this->_joinAlias);
        $query->andWhere($this->getPeriodWhereClause());

        return $this->group_id ? $this->listProjects($query) : $this->aggregateProjects($query);
    }

    /**
     * Returns projects by search parameters loaded
     * @param Query $query
     * @return array
     */
    protected function listProjects(Query $query)
    {
        $query->andWhere([$this->_joinAlias . '.id' => $this->group_id]);

        return $query->all();
    }

    /**
     * Returns projects statistics by search parameters loaded
     * @param Query $query
     * @return array
     */
    protected function aggregateProjects(Query $query)
    {
        $aggAlias = 'aggsq01';
        $aggregateQuery = clone $query;
        $aggregateQuery->select([
            'count' => 'count(*)',
            'value' => 'sum({{project}}.value)',
            'edv' => 'sum({{project}}.edv)',
            'efv' => 'sum({{project}}.efv)',
        ]);

        $query->select([
            'group_id' => $this->_joinAlias . '.id',
            'group_name' => 'max(' . $this->_joinAlias . '.name)',
            'count' => 'count(*)',
            'value' => 'sum({{project}}.value)',
            'edv' => 'sum({{project}}.edv)',
            'efv' => 'sum({{project}}.efv)',
            'count_percentage' => '1.0 * count(*) / ' . $aggAlias . '.count',
            'value_percentage' => '1.0 * sum({{project}}.value) / ' . $aggAlias . '.value',
            'edv_percentage' => '1.0 * sum({{project}}.edv) / ' . $aggAlias . '.edv',
            'efv_percentage' => '1.0 * sum({{project}}.efv) / ' . $aggAlias . '.efv',
        ]);
        $query->innerJoin([$aggAlias => $aggregateQuery]);

        $query->groupBy([
            $this->_joinAlias . '.id',
        ]);

        return $query->all();
    }

    /**
     * @return ActiveQuery
     */
    protected function getActiveStage()
    {
        return $this->getStage()->andWhere(['active' => true]);
    }

    /**
     * @return ActiveQuery
     */
    protected function getInactiveStage()
    {
        return $this->getStage()->andWhere(['active' => false]);
    }

    /**
     * Sets this.joinTable by this.group loaded
     */
    protected function resolveJoinTable()
    {
        $tablesMap = [
            Group::RIBA => 'riba',
            Group::SECTOR => 'sector',
            Group::STAGE => 'stage',
            Group::STAGE_ACTIVE => 'activeStage',
            Group::STAGE_INACTIVE => 'inactiveStage',
            Group::USER => 'creator',
            Group::COMPANY => 'companies',
        ];

        $this->joinTable = ArrayHelper::getValue($tablesMap, $this->group);
    }

    /**
     * @return array
     */
    protected function getPeriodWhereClause()
    {
        $arbitraryClauses = ['BETWEEN', '{{project}}.created', $this->_bd, $this->_ed];

        $clausesMap = [
            Period::MONTH => [
                'MONTH({{project}}.created)' => new Expression('MONTH(NOW())'),
                'YEAR({{project}}.created)' => new Expression('YEAR(NOW())'),
            ],
            Period::YEAR => [
                'YEAR({{project}}.created)' => new Expression('YEAR(NOW())'),
            ],
            Period::TOTAL => [

            ],
        ];

        return ArrayHelper::getValue($clausesMap, $this->period, $arbitraryClauses);
    }
}