]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - modules/ProjectTask/ProjectTask.php
Release 6.5.0
[Github/sugarcrm.git] / modules / ProjectTask / ProjectTask.php
1 <?php
2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4  * SugarCRM Community Edition is a customer relationship management program developed by
5  * SugarCRM, Inc. Copyright (C) 2004-2012 SugarCRM Inc.
6  * 
7  * This program is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU Affero General Public License version 3 as published by the
9  * Free Software Foundation with the addition of the following permission added
10  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13  * 
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
17  * details.
18  * 
19  * You should have received a copy of the GNU Affero General Public License along with
20  * this program; if not, see http://www.gnu.org/licenses or write to the Free
21  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301 USA.
23  * 
24  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26  * 
27  * The interactive user interfaces in modified source and object code versions
28  * of this program must display Appropriate Legal Notices, as required under
29  * Section 5 of the GNU Affero General Public License version 3.
30  * 
31  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32  * these Appropriate Legal Notices must retain the display of the "Powered by
33  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34  * technical reasons, the Appropriate Legal Notices must display the words
35  * "Powered by SugarCRM".
36  ********************************************************************************/
37
38
39
40
41
42
43
44
45
46
47
48
49
50 class ProjectTask extends SugarBean {
51         // database table columns
52         var $id;
53         var $date_entered;
54         var $date_modified;
55         //var $assigned_user_id;
56         //var $modified_user_id;
57         //var $created_by;
58         var $name;
59     var $description;
60     var $project_id;
61     var $project_task_id;
62     var $date_start;
63     var $date_finish;
64     var $duration;
65     var $duration_unit;
66     var $percent_complete;
67     var $parent_task_id;
68     var $predecessors;
69     var $priority;
70
71         // related information
72         var $assigned_user_name;
73         var $parent_name;
74         var $depends_on_name;
75         var $email_id;
76
77         var $table_name = 'project_task';
78         var $object_name = 'ProjectTask';
79         var $module_dir = 'ProjectTask';
80
81         var $field_name_map;
82         var $new_schema = true;
83
84         var $relationship_fields = array(
85                 'email_id' => 'emails',
86         );
87
88         
89         //////////////////////////////////////////////////////////////////
90         // METHODS
91         //////////////////////////////////////////////////////////////////
92
93         /*
94          *
95          */
96         function ProjectTask($init=true)
97         {
98                 parent::SugarBean();
99                 if ($init) {
100                         // default value for a clean instantiation
101                         $this->utilization = 100;
102
103                         global $current_user;
104                         if(empty($current_user))
105                         {
106                                 $this->assigned_user_id = 1;
107                                 $admin_user = new User();
108                                 $admin_user->retrieve($this->assigned_user_id);
109                                 $this->assigned_user_name = $admin_user->user_name;
110                         }
111                         else
112                         {
113                                 $this->assigned_user_id = $current_user->id;
114                                 $this->assigned_user_name = $current_user->user_name;
115                         }
116
117                 }
118         }
119
120         function save($check_notify = FALSE)
121         {
122                 //Bug 46012.  When saving new Project Tasks instance in a workflow, make sure we set a project_task_id value
123                 //associated with the Project if there is no project_task_id specified.
124         if ($this->in_workflow && empty($this->id) && empty($this->project_task_id) && !empty($this->project_id))
125         {
126             $this->project_task_id = $this->getNumberOfTasksInProject($this->project_id) + 1;
127         }
128         
129         $id = parent::save($check_notify);
130         $this->updateParentProjectTaskPercentage();
131         return $id;
132         }
133
134         /**
135          * overriding the base class function to do a join with users table
136          */
137
138         /*
139          *
140          */
141    function fill_in_additional_detail_fields()
142    {
143       $this->assigned_user_name = get_assigned_user_name($this->assigned_user_id);
144       $this->project_name = $this->_get_project_name($this->project_id);
145                 /*
146         $this->depends_on_name = $this->_get_depends_on_name($this->depends_on_id);
147                 if(empty($this->depends_on_name))
148                 {
149                         $this->depends_on_id = '';
150                 }
151                 $this->parent_name = $this->_get_parent_name($this->parent_id);
152                 if(empty($this->parent_name))
153                 {
154                         $this->parent_id = '';
155                 }
156         */
157    }
158
159         /*
160          *
161          */
162    function fill_in_additional_list_fields()
163    {
164       $this->assigned_user_name = get_assigned_user_name($this->assigned_user_id);
165       //$this->parent_name = $this->_get_parent_name($this->parent_id);
166       $this->project_name = $this->_get_project_name($this->project_id);
167    }
168
169         /*
170          *
171          */
172         function get_summary_text()
173         {
174                 return $this->name;
175         }
176
177         /*
178          *
179          */
180         function _get_depends_on_name($depends_on_id)
181         {
182                 $return_value = '';
183
184                 $query  = "SELECT name, assigned_user_id FROM {$this->table_name} WHERE id='{$depends_on_id}'";
185                 $result = $this->db->query($query,true," Error filling in additional detail fields: ");
186                 $row = $this->db->fetchByAssoc($result);
187                 if($row != null)
188                 {
189                         $this->depends_on_name_owner = $row['assigned_user_id'];
190                         $this->depends_on_name_mod = 'ProjectTask';
191                         $return_value = $row['name'];
192                 }
193
194                 return $return_value;
195         }
196
197     function _get_project_name($project_id)
198     {
199         $return_value = '';
200
201         $query  = "SELECT name, assigned_user_id FROM project WHERE id='{$project_id}'";
202         $result = $this->db->query($query,true," Error filling in additional detail fields: ");
203         $row = $this->db->fetchByAssoc($result);
204         if($row != null)
205         {
206             //$this->parent_name_owner = $row['assigned_user_id'];
207             //$this->parent_name_mod = 'Project';
208             $return_value = $row['name'];
209         }
210
211         return $return_value;
212     }
213         /*
214          *
215          */
216         function _get_parent_name($parent_id)
217         {
218                 $return_value = '';
219
220                 $query  = "SELECT name, assigned_user_id FROM project WHERE id='{$parent_id}'";
221                 $result = $this->db->query($query,true," Error filling in additional detail fields: ");
222                 $row = $this->db->fetchByAssoc($result);
223                 if($row != null)
224                 {
225                         $this->parent_name_owner = $row['assigned_user_id'];
226                         $this->parent_name_mod = 'Project';
227                         $return_value = $row['name'];
228                 }
229
230                 return $return_value;
231         }
232
233         /*
234          *
235          */
236         function build_generic_where_clause ($the_query_string)
237         {
238                 $where_clauses = array();
239                 $the_query_string = $GLOBALS['db']->quote($the_query_string);
240                 array_push($where_clauses, "project_task.name like '$the_query_string%'");
241
242                 $the_where = "";
243                 foreach($where_clauses as $clause)
244                 {
245                         if($the_where != "") $the_where .= " or ";
246                         $the_where .= $clause;
247                 }
248
249                 return $the_where;
250         }
251
252         function get_list_view_data(){
253                 global $action, $currentModule, $focus, $current_module_strings, $app_list_strings, $timedate, $locale;
254                 $today = $timedate->handle_offset(date($GLOBALS['timedate']->get_db_date_time_format(), time()), $timedate->dbDayFormat, true);
255                 $task_fields =$this->get_list_view_array();
256                 //$date_due = $timedate->to_db_date($task_fields['DATE_DUE'],false);
257         if (isset($this->parent_type))
258                         $task_fields['PARENT_MODULE'] = $this->parent_type;
259
260                 /*
261         if ($this->status != "Completed" && $this->status != "Deferred" ) {
262                         $task_fields['SET_COMPLETE'] = "<a href='index.php?return_module=$currentModule&return_action=$action&return_id=" . ((!empty($focus->id)) ? $focus->id : "") . "&module=ProjectTask&action=EditView&record={$this->id}&status=Completed'>".SugarThemeRegistry::current()->getImage("close_inline","alt='Close' border='0'")."</a>";
263                 }
264
265                 if( $date_due   < $today){
266                         $task_fields['DATE_DUE']= "<font class='overdueTask'>".$task_fields['DATE_DUE']."</font>";
267                 }else if( $date_due     == $today ){
268                         $task_fields['DATE_DUE'] = "<font class='todaysTask'>".$task_fields['DATE_DUE']."</font>";
269                 }else{
270                         $task_fields['DATE_DUE'] = "<font class='futureTask'>".$task_fields['DATE_DUE']."</font>";
271                 }
272         */
273
274         if ( !isset($task_fields["FIRST_NAME"]) )
275             $task_fields["FIRST_NAME"] = '';
276         if ( !isset($task_fields["LAST_NAME"]) )
277             $task_fields["LAST_NAME"] = '';
278                 $task_fields['CONTACT_NAME']= $locale->getLocaleFormattedName($task_fields["FIRST_NAME"],$task_fields["LAST_NAME"]);
279                 $task_fields['TITLE'] = '';
280                 if (!empty($task_fields['CONTACT_NAME'])) {
281                         $task_fields['TITLE'] .= $current_module_strings['LBL_LIST_CONTACT'].": ".$task_fields['CONTACT_NAME'];
282                 }
283
284                 return $task_fields;
285         }
286
287         function bean_implements($interface){
288                 switch($interface){
289                         case 'ACL':return true;
290                 }
291                 return false;
292         }
293         function listviewACLHelper(){
294                 $array_assign = parent::listviewACLHelper();
295                 $is_owner = false;
296                 if(!empty($this->parent_name)){
297
298                         if(!empty($this->parent_name_owner)){
299                                 global $current_user;
300                                 $is_owner = $current_user->id == $this->parent_name_owner;
301                         }
302                 }
303                         if(ACLController::checkAccess('Project', 'view', $is_owner)){
304                                 $array_assign['PARENT'] = 'a';
305                         }else{
306                                 $array_assign['PARENT'] = 'span';
307                         }
308                 $is_owner = false;
309                 if(!empty($this->depends_on_name)){
310
311                         if(!empty($this->depends_on_name_owner)){
312                                 global $current_user;
313                                 $is_owner = $current_user->id == $this->depends_on_name_owner;
314                         }
315                 }
316                         if( ACLController::checkAccess('ProjectTask', 'view', $is_owner)){
317                                 $array_assign['PARENT_TASK'] = 'a';
318                         }else{
319                                 $array_assign['PARENT_TASK'] = 'span';
320                         }
321
322                 return $array_assign;
323         }
324
325     function create_export_query(&$order_by, &$where, $relate_link_join='')
326     {
327         $custom_join = $this->custom_fields->getJOIN(true, true,$where);
328                 if($custom_join)
329                                 $custom_join['join'] .= $relate_link_join;
330                 $query = "SELECT
331                                 project_task.*,
332                 users.user_name as assigned_user_name ";
333         if($custom_join){
334                         $query .=  $custom_join['select'];
335                 }
336
337         $query .= " FROM project_task LEFT JOIN project ON project_task.project_id=project.id AND project.deleted=0 ";
338
339                 if($custom_join){
340                         $query .=  $custom_join['join'];
341                 }
342         $query .= " LEFT JOIN users
343                         ON project_task.assigned_user_id=users.id ";
344
345         $where_auto = " project_task.deleted=0 ";
346
347         if($where != "")
348                 $query .= "where ($where) AND ".$where_auto;
349         else
350             $query .= "where ".$where_auto;
351
352         if(!empty($order_by)){
353                 //check to see if order by variable already has table name by looking for dot "."
354                 $table_defined_already = strpos($order_by, ".");
355
356                 if($table_defined_already === false){
357                         //table not defined yet, define accounts to avoid "ambigous column" SQL error
358                         $query .= " ORDER BY $order_by";
359                 }else{
360                         //table already defined, just add it to end of query
361                     $query .= " ORDER BY $order_by";
362                 }
363         }
364         return $query;
365     }
366
367
368     /**
369     * This method recalculates the percent complete of a parent task
370     */
371     public function updateParentProjectTaskPercentage()
372         {
373
374                 if (empty($this->parent_task_id))
375                 {
376                         return;
377                 }
378
379                 if (!empty($this->project_id))
380                 {
381             //determine parent task
382             $parentProjectTask = $this->getProjectTaskParent();
383
384             //get task children
385             if ($parentProjectTask)
386             {
387                 $subProjectTasks = $parentProjectTask->getAllSubProjectTasks();
388
389                 $totalHours = 0;
390                 $cumulativeDone = 0;
391
392                 //update cumulative calculation - mimics gantt calculation
393                 foreach ($subProjectTasks as $key => $value)
394                 {
395                     if ($value->duration == "")
396                     {
397                         $value->duration = 0;
398                     }
399
400                     if ($value->percent_complete == "")
401                     {
402                         $value->percent_complete = 0;
403                     }
404
405                     if ($value->duration_unit == "Hours")
406                     {
407                         $totalHours += $value->duration;
408                         $cumulativeDone += $value->duration * ($value->percent_complete / 100);
409                     }
410                     else
411                     {
412                         $totalHours += ($value->duration * 8);
413                         $cumulativeDone += ($value->duration * 8) * ($value->percent_complete / 100);
414                     }
415                 }
416
417                 $cumulativePercentage = 0;
418                                 if ($totalHours != 0)
419                 {
420                                         $cumulativePercentage = ($cumulativeDone/$totalHours) * 100;
421                 }
422
423                 $parentProjectTask->percent_complete = round($cumulativePercentage);
424                 $parentProjectTask->save(isset($GLOBALS['check_notify']) ? $GLOBALS['check_notify'] : '');
425             }
426                 }
427         }
428
429     /**
430     * Retrieves the parent project task of a project task
431     * returns project task bean
432     */
433     function getProjectTaskParent()
434     {
435
436         $projectTaskParent=false;
437
438         if (!empty($this->parent_task_id) && !empty($this->project_id))
439         {
440             $query = "SELECT id FROM project_task WHERE project_id = '{$this->project_id}' AND project_task_id = '{$this->parent_task_id}' AND deleted = 0 ORDER BY date_modified DESC";
441             $project_task_id = $this->db->getOne($query, true, "Error retrieving parent project task");
442
443             if (!empty($project_task_id))
444             {
445                 $projectTaskParent = BeanFactory::getBean('ProjectTask', $project_task_id);
446             }
447         }
448
449         return $projectTaskParent;
450     }
451
452     /**
453     * Retrieves all the child project tasks of a project task
454     * returns project task bean array
455     */
456     function getAllSubProjectTasks()
457     {
458                 $projectTasksBeans = array();
459
460         if (!empty($this->project_task_id) && !empty($this->project_id))
461                 {
462             //select all tasks from a project
463             $query = "SELECT id, project_task_id, parent_task_id FROM project_task WHERE project_id = '{$this->project_id}' AND deleted = 0 ORDER BY project_task_id";
464
465             $result = $this->db->query($query, true, "Error retrieving child project tasks");
466
467             $projectTasks=array();
468             while($row = $this->db->fetchByAssoc($result))
469             {
470                 $projectTasks[$row['id']]['project_task_id'] = $row['project_task_id'];
471                 $projectTasks[$row['id']]['parent_task_id'] = $row['parent_task_id'];
472             }
473
474             $potentialParentTaskIds[$this->project_task_id] = $this->project_task_id;
475             $actualParentTaskIds=array();
476             $subProjectTasks=array();
477
478             $startProjectTasksCount=0;
479             $endProjectTasksCount=0;
480
481             //get all child tasks
482             $run = true;
483             while ($run)
484             {
485                 $count=0;
486
487                 foreach ($projectTasks as $id=>$values)
488                 {
489                     if (in_array($values['parent_task_id'], $potentialParentTaskIds))
490                     {
491                         $potentialParentTaskIds[$values['project_task_id']] = $values['project_task_id'];
492                         $actualParentTaskIds[$values['parent_task_id']] = $values['parent_task_id'];
493
494                         $subProjectTasks[$id]=$values;
495                         $count=$count+1;
496                     }
497                 }
498
499                 $endProjectTasksCount = count($subProjectTasks);
500
501                 if ($startProjectTasksCount == $endProjectTasksCount)
502                 {
503                     $run = false;
504                 }
505                 else
506                 {
507                     $startProjectTasksCount = $endProjectTasksCount;
508                 }
509             }
510
511             foreach($subProjectTasks as $id=>$values)
512             {
513                 //ignore tasks that are parents
514                 if(!in_array($values['project_task_id'], $actualParentTaskIds))
515                 {
516                     $projectTaskBean = BeanFactory::getBean('ProjectTask', $id);
517                     array_push($projectTasksBeans, $projectTaskBean);
518                 }
519             }
520                 }
521
522                 return $projectTasksBeans;
523         }
524         
525         
526         /**
527          * getNumberOfTasksInProject
528          * 
529          * Returns the count of project_tasks for the given project_id
530          * 
531          * This is a private helper function to get the number of project tasks for a given project_id.
532          * 
533          * @param $project_id integer value of the project_id associated with this ProjectTask instance
534          * @return total integer value of the count of project tasks, 0 if none found
535          */
536     private function getNumberOfTasksInProject($project_id='')
537     {
538         if(!empty($project_id))
539         {
540                 $query = "SELECT count(project_task_id) AS total FROM project_task WHERE project_id = '{$project_id}'";
541                 $result = $this->db->query($query, true);
542                 if($result)
543                 {
544                         $row = $this->db->fetchByAssoc($result);
545                         if(!empty($row['total']))
546                         {
547                            return $row['total'];
548                         }
549                 }
550         }
551         return 0;
552     }   
553 }
554
555 function getUtilizationDropdown($focus, $field, $value, $view) {
556         global $app_list_strings;
557
558         if($view == 'EditView') {
559                 global $app_list_strings;
560         $html = '<select name="'.$field.'">';
561         $html .= get_select_options_with_id($app_list_strings['project_task_utilization_options'], $value);
562         $html .= '</select>';
563         return $html;
564     }
565
566     return translate('project_task_utilization_options', '', $focus->$field);
567 }
568 ?>