YetiForceCompany/YetiForceCRM

View on GitHub
modules/OSSTimeControl/models/TimeCounting.php

Summary

Maintainability
A
0 mins
Test Coverage
B
84%
<?php

/**
 * The file contains: CalculateSumOfExecutionTime class.
 *
 * @package   Model
 *
 * @copyright YetiForce S.A.
 * @license   YetiForce Public License 6.5 (licenses/LicenseEN.txt or yetiforce.com)
 * @author    Arkadiusz Adach <a.adach@yetiforce.com>
 * @author    Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com>
 */

/**
 * CalculateSumOfExecutionTime class.
 */
class OSSTimeControl_TimeCounting_Model
{
    /**
     * Recalculate status.
     */
    const RECALCULATE_STATUS = 'Accepted';

    /**
     * Column sum time.
     */
    const COLUMN_SUM_TIME = 'sum_time';

    /**
     * Column sum time subordinate.
     */
    const COLUMN_SUM_TIME_SUBORDINATE = 'sum_time_subordinate';

    /**
     * Field model name sum of time.
     *
     * @var \Vtiger_Field_Model
     */
    private $fieldModelSumTime;

    /**
     * Field model name sum of time subordinate.
     *
     * @var \Vtiger_Field_Model
     */
    private $fieldModelSumTimeSubordinate;

    /**
     * Module name.
     *
     * @var string
     */
    private $moduleName;

    /**
     * Field name parent id.
     *
     * @var string
     */
    private $columnNameParentId;

    /**
     * Is active total execution time.
     *
     * @var bool
     */
    private $isActiveSumTimeSubordinate = false;

    /**
     * Is active sum of time.
     *
     * @var bool
     */
    private $isActiveSumTime = false;

    /**
     * Primary key of table.
     *
     * @var string
     */
    private $primaryKey;

    /**
     * Record ID.
     *
     * @var int
     */
    private $recordId;

    /**
     * Relation field.
     *
     * @var string
     */
    private $relationField;

    /**
     * Construct.
     *
     * @param string $moduleName
     * @param int    $recordId
     * @param string $relationField
     */
    public function __construct(string $moduleName, int $recordId, string $relationField)
    {
        $this->recordId = $recordId;
        $this->relationField = $relationField;
        $this->moduleName = $moduleName;
        $moduleModel = Vtiger_Module_Model::getInstance($moduleName);
        $this->fieldModelSumTime = $moduleModel->getFieldByColumn(static::COLUMN_SUM_TIME);
        $this->isActiveSumTime = $this->fieldModelSumTime && $this->fieldModelSumTime->isActiveField();
        if ($this->isActiveSumTime) {
            $this->primaryKey = $moduleModel->getEntityInstance()->table_index;
            $this->columnNameParentId = \App\Field::getRelatedFieldForModule($moduleName, $moduleName)['columnname'] ?? null;
            if ($this->columnNameParentId) {
                $this->fieldModelSumTimeSubordinate = $moduleModel->getFieldByColumn(static::COLUMN_SUM_TIME_SUBORDINATE);
                $this->isActiveSumTimeSubordinate = $this->fieldModelSumTimeSubordinate && $this->fieldModelSumTimeSubordinate->isActiveField();
            }
        }
    }

    /**
     * Recalculate time control by record.
     *
     * @param string $moduleName
     * @param int    $recordId
     * @param string $relationField
     *
     * @return void
     */
    public static function recalculate(string $moduleName, int $recordId, string $relationField): void
    {
        (new self($moduleName, $recordId, $relationField))->recalculateTimeControl();
    }

    /**
     * Recalculate time control.
     *
     * @return void
     */
    public function recalculateTimeControl()
    {
        if ($this->isActiveSumTime) {
            \App\Db::getInstance()
                ->createCommand()
                ->update(
                    $this->fieldModelSumTime->getTableName(),
                    [static::COLUMN_SUM_TIME => $this->getSumTime()],
                    [$this->primaryKey => $this->recordId]
                )->execute();
            if ($this->isActiveSumTimeSubordinate) {
                $this->calculate($this->recordId);
            }
        }
    }

    /**
     * Get sum of time.
     *
     * @return float
     */
    private function getSumTime(): float
    {
        return round(
            (float) (new \App\QueryGenerator('OSSTimeControl'))
                ->createQuery()
                ->andWhere(['osstimecontrol_status' => static::RECALCULATE_STATUS, $this->relationField => $this->recordId])
                ->sum($this->fieldModelSumTime->getColumnName()),
            2
        );
    }

    /**
     * Calculate.
     *
     * @param int   $recordId
     * @param float $initialValue
     *
     * @return void
     */
    private function calculate(int $recordId, float $initialValue = 0)
    {
        $recordModel = \Vtiger_Record_Model::getInstanceById($recordId, $this->moduleName);
        $this->update(
            $recordId,
            round(($initialValue + (float) $recordModel->get(static::COLUMN_SUM_TIME)), 2)
        );
        $parentId = $recordModel->get($this->columnNameParentId);
        if (!empty($parentId)) {
            $this->calculate($parentId, $this->getSumTimeOfChildren($parentId));
        }
    }

    /**
     * Update.
     *
     * @param int   $recordId
     * @param float $sumTime
     *
     * @return void
     */
    private function update(int $recordId, float $sumTime)
    {
        \App\Db::getInstance()
            ->createCommand()
            ->update(
                $this->fieldModelSumTimeSubordinate->getTableName(),
            [$this->fieldModelSumTimeSubordinate->getColumnName() => $sumTime],
            [$this->primaryKey => $recordId]
        )->execute();
    }

    /**
     * Get sum time of children.
     *
     * @param int $recordId
     *
     * @return float
     */
    private function getSumTimeOfChildren(int $recordId): float
    {
        return (float) (new \App\QueryGenerator($this->moduleName))
            ->createQuery()
            ->andWhere([$this->columnNameParentId => $recordId])
            ->sum($this->fieldModelSumTimeSubordinate->getColumnName());
    }
}