YetiForceCompany/YetiForceCRM

View on GitHub
modules/Project/models/Module.php

Summary

Maintainability
A
0 mins
Test Coverage
D
68%
<?php
/**
 * Project module model class.
 *
 * @package   Module
 *
 * @copyright YetiForce S.A.
 * @license   YetiForce Public License 6.5 (licenses/LicenseEN.txt or yetiforce.com)
 * @author    Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com>
 */
class Project_Module_Model extends Vtiger_Module_Model
{
    /**
     * Calculate estimated work time.
     *
     * @param int   $id
     * @param float $estimatedWorkTime
     *
     * @throws \App\Exceptions\AppException
     *
     * @return float
     */
    public static function calculateEstimatedWorkTime(int $id, float $estimatedWorkTime = 0): float
    {
        $progressInHours = 0;
        foreach (static::getChildren($id) as $child) {
            $estimatedWorkTime += static::calculateEstimatedWorkTime($child['id']);
        }
        static::calculateProgressOfMilestones($id, $estimatedWorkTime, $progressInHours);
        return $estimatedWorkTime;
    }

    /**
     * Get children by parent ID.
     *
     * @param int $id
     *
     * @return int[]
     */
    protected static function getChildren(int $id): array
    {
        return (new \App\Db\Query())
            ->select(['id' => 'vtiger_project.projectid', 'vtiger_project.progress'])
            ->from('vtiger_project')
            ->innerJoin('vtiger_crmentity', 'vtiger_project.projectid = vtiger_crmentity.crmid')
            ->where(['vtiger_crmentity.deleted' => [0, 2]])
            ->andWhere(['vtiger_project.parentid' => $id])->all();
    }

    /**
     * Calculate the progress of milestones.
     *
     * @param int   $id
     * @param float $estimatedWorkTime
     * @param float $progressInHours
     *
     * @throws \App\Exceptions\AppException
     */
    protected static function calculateProgressOfMilestones(int $id, float &$estimatedWorkTime, float &$progressInHours)
    {
        $dataReader = (new \App\Db\Query())
            ->select([
                'id' => 'vtiger_projectmilestone.projectmilestoneid',
                'projectmilestonename' => 'vtiger_projectmilestone.projectmilestonename',
                'projectmilestone_progress' => 'vtiger_projectmilestone.projectmilestone_progress',
            ])
            ->from('vtiger_projectmilestone')
            ->innerJoin('vtiger_crmentity', 'vtiger_projectmilestone.projectmilestoneid = vtiger_crmentity.crmid')
            ->where(['vtiger_crmentity.deleted' => [0, 2]])
            ->andWhere(['vtiger_projectmilestone.projectid' => $id])
            ->andWhere(['or', ['vtiger_projectmilestone.parentid' => 0], ['vtiger_projectmilestone.parentid' => null]])
            ->createCommand()->query();
        while ($row = $dataReader->read()) {
            $milestoneEstimatedWorkTime = ProjectMilestone_Module_Model::calculateEstimatedWorkTime($row['id']);
            $estimatedWorkTime += $milestoneEstimatedWorkTime;
            $progressInHours += ($milestoneEstimatedWorkTime * (float) $row['projectmilestone_progress']) / 100;
        }
        $dataReader->close();
    }

    /** {@inheritdoc} */
    public function getSideBarLinks($linkParams)
    {
        $links = parent::getSideBarLinks($linkParams);
        $links['SIDEBARLINK'][] = Vtiger_Link_Model::getInstanceFromValues([
            'linktype' => 'SIDEBARLINK',
            'linklabel' => 'LBL_VIEW_GANTT',
            'linkurl' => 'index.php?module=Project&view=Gantt',
            'linkicon' => 'fas fa-briefcase',
        ]);
        return $links;
    }

    /**
     * Update progress in project.
     *
     * @param int      $id
     * @param float    $estimatedWorkTime
     * @param float    $progressInHours
     * @param int|null $callerId
     *
     * @throws \App\Exceptions\AppException
     *
     * @return array
     */
    public static function updateProgress(int $id, float $estimatedWorkTime = 0, float $progressInHours = 0, ?int $callerId = null): array
    {
        $recordModel = Vtiger_Record_Model::getInstanceById($id);
        foreach (static::getChildren($id) as $child) {
            if ($callerId !== $child['id']) {
                $childEstimatedWorkTime = static::calculateEstimatedWorkTime($child['id']);
                $estimatedWorkTime += $childEstimatedWorkTime;
                $progressInHours += ($childEstimatedWorkTime * $child['progress'] / 100);
            }
        }
        static::calculateProgressOfMilestones($id, $estimatedWorkTime, $progressInHours);
        $projectProgress = $estimatedWorkTime ? round((100 * $progressInHours) / $estimatedWorkTime) : 0;
        $recordModel->set('progress', $projectProgress);
        $recordModel->set('estimated_work_time', $estimatedWorkTime);
        $recordModel->save();
        if (!$recordModel->isEmpty('parentid') && $recordModel->get('parentid') !== $callerId) {
            static::updateProgress(
                $recordModel->get('parentid'),
                $estimatedWorkTime,
                $progressInHours,
                $id
            );
        }
        return [
            'estimatedWorkTime' => $estimatedWorkTime,
            'projectProgress' => $projectProgress
        ];
    }
}