Passed
Push — developer ( 6b5868...bed0f9 )
by Radosław
22:42 queued 03:39
created

ProjectMilestone_Module_Model::updateProgress()   A

Complexity

Conditions 5
Paths 12

Size

Total Lines 24
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
eloc 20
dl 0
loc 24
ccs 0
cts 20
cp 0
rs 9.2888
c 0
b 0
f 0
cc 5
nc 12
nop 4
crap 30
1
<?php
2
/* +***********************************************************************************
3
 * The contents of this file are subject to the vtiger CRM Public License Version 1.0
4
 * ("License"); You may not use this file except in compliance with the License
5
 * The Original Code is:  vtiger CRM Open Source
6
 * The Initial Developer of the Original Code is vtiger.
7
 * Portions created by vtiger are Copyright (C) vtiger.
8
 * All Rights Reserved.
9
 * *********************************************************************************** */
10
11
class ProjectMilestone_Module_Model extends Vtiger_Module_Model
12
{
13
	/**
14
	 * Cache for estimated work time.
15
	 *
16
	 * @var float[]
17
	 */
18
	protected static $cacheEstimatedWorkTime = [];
19
20
	/**
21
	 * Get children by parent ID.
22
	 *
23
	 * @param int $id
24
	 *
25
	 * @return int[]
26
	 */
27
	protected static function getChildren(int $id): array
28
	{
29
		return (new \App\Db\Query())
30
			->select(['id' => 'vtiger_projectmilestone.projectmilestoneid', 'vtiger_projectmilestone.projectmilestone_progress'])
31
			->from('vtiger_projectmilestone')
32
			->innerJoin('vtiger_crmentity', 'vtiger_projectmilestone.projectmilestoneid = vtiger_crmentity.crmid')
33
			->where(['vtiger_crmentity.deleted' => [0, 2]])
34
			->andWhere(['vtiger_projectmilestone.parentid' => $id])->all();
35
	}
36
37
	/**
38
	 * Calculate the progress of tasks.
39
	 *
40
	 * @param int   $id
41
	 * @param float $estimatedWorkTime
42
	 * @param float $progressInHours
43
	 *
44
	 * @throws \App\Exceptions\AppException
45
	 */
46
	protected static function calculateProgressOfTasks(int $id, float &$estimatedWorkTime, float &$progressInHours)
47
	{
48
		$row = (new \App\Db\Query())
49
			->select([
50
				'estimated_work_time' => new \yii\db\Expression('SUM(vtiger_projecttask.estimated_work_time)'),
51
				'progress_in_hours' => new \yii\db\Expression('SUM(vtiger_projecttask.estimated_work_time * vtiger_projecttask.projecttaskprogress / 100)')
52
			])
53
			->from('vtiger_projecttask')
54
			->innerJoin('vtiger_crmentity', 'vtiger_projecttask.projecttaskid = vtiger_crmentity.crmid')
55
			->where(['vtiger_crmentity.deleted' => [0, 2]])
56
			->andWhere(['vtiger_projecttask.projectmilestoneid' => $id])
57
			->one();
58
		if (false !== $row && null !== $row['estimated_work_time']) {
59
			$estimatedWorkTime += (float) $row['estimated_work_time'];
60
			$progressInHours += (float) $row['progress_in_hours'];
61
		}
62
	}
63
64
	/**
65
	 * Calculate estimated work time.
66
	 *
67
	 * @param int   $id
68
	 * @param float $estimatedWorkTime
69
	 *
70
	 * @throws \App\Exceptions\AppException
71
	 *
72
	 * @return float
73
	 */
74
	public static function calculateEstimatedWorkTime(int $id, float $estimatedWorkTime = 0): float
75
	{
76
		if (isset(static::$cacheEstimatedWorkTime[$id])) {
77
			$estimatedWorkTime += static::$cacheEstimatedWorkTime[$id];
78
		} else {
79
			$progressInHours = 0;
80
			$tmpEstimatedWorkTime = 0;
81
			foreach (static::getChildren($id) as $child) {
82
				$tmpEstimatedWorkTime += static::calculateEstimatedWorkTime($child['id']);
83
			}
84
			static::calculateProgressOfTasks($id, $tmpEstimatedWorkTime, $progressInHours);
85
			static::$cacheEstimatedWorkTime[$id] = $tmpEstimatedWorkTime;
86
			$estimatedWorkTime += $tmpEstimatedWorkTime;
87
		}
88
		return $estimatedWorkTime;
89
	}
90
91
	/**
92
	 * Update progress milestone.
93
	 *
94
	 * @param int      $id
95
	 * @param float    $estimatedWorkTime
96
	 * @param float    $progressInHours
97
	 * @param int|null $callerId
98
	 *
99
	 * @throws \App\Exceptions\AppException
100
	 */
101
	public static function updateProgress(int $id, float $estimatedWorkTime = 0, float $progressInHours = 0, ?int $callerId = null)
102
	{
103
		$recordModel = Vtiger_Record_Model::getInstanceById($id);
104
		foreach (static::getChildren($id) as $child) {
105
			if ($callerId !== $child['id']) {
106
				$childEstimatedWorkTime = static::calculateEstimatedWorkTime($child['id']);
107
				$estimatedWorkTime += $childEstimatedWorkTime;
108
				$progressInHours += ($childEstimatedWorkTime * $child['projectmilestone_progress'] / 100);
109
			}
110
		}
111
		static::calculateProgressOfTasks($id, $estimatedWorkTime, $progressInHours);
112
		$projectProgress = $estimatedWorkTime ? round((100 * $progressInHours) / $estimatedWorkTime) : 0;
113
		$recordModel->set('projectmilestone_progress', $projectProgress);
114
		$recordModel->set('estimated_work_time', $estimatedWorkTime);
115
		$recordModel->save();
116
		if ($recordModel->isEmpty('parentid')) {
117
			static::$cacheEstimatedWorkTime[$id] = $estimatedWorkTime;
118
			Project_Module_Model::updateProgress($recordModel->get('projectid'));
119
		} else {
120
			static::updateProgress(
121
				$recordModel->get('parentid'),
122
				$estimatedWorkTime,
123
				$progressInHours,
124
				$id
125
			);
126
		}
127
	}
128
129
	/**
130
	 * Function to get list view query for popup window.
131
	 *
132
	 * @param Vtiger_ListView_Model $listviewModel
133
	 * @param \App\QueryGenerator   $queryGenerator
134
	 */
135
	public function getQueryByRelatedField(Vtiger_ListView_Model $listviewModel, App\QueryGenerator $queryGenerator)
136
	{
137
		if ('Project' === $listviewModel->get('src_module') && !$listviewModel->isEmpty('filterFields')) {
138
			$filterFields = $listviewModel->get('filterFields');
139
			if (!empty($filterFields['projectid'])) {
140
				$queryGenerator->addNativeCondition(['projectid' => (int) $filterFields['projectid']]);
141
			}
142
		}
143
	}
144
}
145