30 require_once DOL_DOCUMENT_ROOT.
'/core/class/commonobject.class.php';
31 require_once DOL_DOCUMENT_ROOT.
'/core/class/commonobjectline.class.php';
32 require_once DOL_DOCUMENT_ROOT.
'/projet/class/project.class.php';
33 require_once DOL_DOCUMENT_ROOT.
'/core/class/timespent.class.php';
44 public $element =
'project_task';
49 public $table_element =
'projet_task';
54 public $fk_element =
'fk_element';
59 public $picto =
'projecttask';
64 protected $childtables = array(
65 'element_time' => array(
'name' =>
'Task',
'parent' =>
'projet_task',
'parentkey' =>
'fk_element',
'parenttypefield' =>
'elementtype',
'parenttypevalue' =>
'task')
71 public $fk_task_parent = 0;
83 public $duration_effective;
84 public $planned_workload;
105 public $fk_user_creat;
110 public $fk_user_valid;
114 public $timespent_min_date;
115 public $timespent_max_date;
116 public $timespent_total_duration;
117 public $timespent_total_amount;
118 public $timespent_nblinesnull;
119 public $timespent_nblines;
123 public $timespent_id;
124 public $timespent_duration;
125 public $timespent_old_duration;
126 public $timespent_date;
127 public $timespent_datehour;
128 public $timespent_withhour;
129 public $timespent_fk_user;
130 public $timespent_thm;
131 public $timespent_note;
132 public $timespent_fk_product;
133 public $timespent_invoiceid;
134 public $timespent_invoicelineid;
136 public $comments = array();
141 public $budget_amount;
146 public $project_budget_amount;
169 public function create($user, $notrigger = 0)
171 global $conf, $langs;
179 $this->label = trim($this->label);
182 if (!empty($this->date_start) && !empty($this->date_end) && $this->date_start > $this->date_end) {
183 $this->errors[] = $langs->trans(
'StartDateCannotBeAfterEndDate');
191 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.
"projet_task (";
193 $sql .=
", fk_projet";
195 $sql .=
", fk_task_parent";
197 $sql .=
", description";
199 $sql .=
", fk_user_creat";
202 $sql .=
", planned_workload";
203 $sql .=
", progress";
204 $sql .=
", budget_amount";
205 $sql .=
") VALUES (";
206 $sql .= (!empty($this->entity) ? (int) $this->entity : (
int) $conf->entity);
207 $sql .=
", ".((int) $this->fk_project);
208 $sql .=
", ".(!empty($this->
ref) ?
"'".$this->db->escape($this->
ref).
"'" :
'null');
209 $sql .=
", ".((int) $this->fk_task_parent);
210 $sql .=
", '".$this->db->escape($this->label).
"'";
212 $sql .=
", '".$this->db->idate($now).
"'";
213 $sql .=
", ".((int) $user->id);
214 $sql .=
", ".($this->date_start ?
"'".$this->db->idate($this->date_start).
"'" :
'null');
215 $sql .=
", ".($this->date_end ?
"'".$this->db->idate($this->date_end).
"'" :
'null');
216 $sql .=
", ".(($this->planned_workload !=
'' && $this->planned_workload >= 0) ? ((
int) $this->planned_workload) :
'null');
217 $sql .=
", ".(($this->progress !=
'' && $this->progress >= 0) ? ((
int) $this->progress) :
'null');
218 $sql .=
", ".(($this->budget_amount !=
'' && $this->budget_amount >= 0) ? ((
int) $this->budget_amount) :
'null');
223 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
224 $resql = $this->db->query(
$sql);
226 $error++; $this->errors[] =
"Error ".$this->db->lasterror();
230 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.
"projet_task");
254 foreach ($this->errors as $errmsg) {
255 dol_syslog(get_class($this).
"::create ".$errmsg, LOG_ERR);
256 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
258 $this->db->rollback();
275 public function fetch($id, $ref =
'', $loadparentdata = 0)
277 global $langs, $conf;
282 $sql .=
" t.entity,";
283 $sql .=
" t.fk_projet as fk_project,";
284 $sql .=
" t.fk_task_parent,";
286 $sql .=
" t.description,";
287 $sql .=
" t.duration_effective,";
288 $sql .=
" t.planned_workload,";
292 $sql .=
" t.fk_user_creat,";
293 $sql .=
" t.fk_user_valid,";
294 $sql .=
" t.fk_statut,";
295 $sql .=
" t.progress,";
296 $sql .=
" t.budget_amount,";
297 $sql .=
" t.priority,";
298 $sql .=
" t.note_private,";
299 $sql .=
" t.note_public,";
301 if (!empty($loadparentdata)) {
302 $sql .=
", t2.ref as task_parent_ref";
303 $sql .=
", t2.rang as task_parent_position";
305 $sql .=
" FROM ".MAIN_DB_PREFIX.
"projet_task as t";
306 if (!empty($loadparentdata)) {
307 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"projet_task as t2 ON t.fk_task_parent = t2.rowid";
311 $sql .=
"entity IN (".getEntity(
'project').
")";
312 $sql .=
" AND t.ref = '".$this->db->escape($ref).
"'";
314 $sql .=
"t.rowid = ".((int) $id);
317 dol_syslog(get_class($this).
"::fetch", LOG_DEBUG);
318 $resql = $this->db->query(
$sql);
320 $num_rows = $this->db->num_rows($resql);
323 $obj = $this->db->fetch_object($resql);
325 $this->
id = $obj->rowid;
326 $this->
ref = $obj->ref;
327 $this->entity = $obj->entity;
328 $this->fk_project = $obj->fk_project;
329 $this->fk_task_parent = $obj->fk_task_parent;
330 $this->label = $obj->label;
332 $this->duration_effective = $obj->duration_effective;
333 $this->planned_workload = $obj->planned_workload;
334 $this->date_c = $this->db->jdate($obj->datec);
335 $this->date_start = $this->db->jdate($obj->dateo);
336 $this->date_end = $this->db->jdate($obj->datee);
337 $this->fk_user_creat = $obj->fk_user_creat;
338 $this->fk_user_valid = $obj->fk_user_valid;
339 $this->fk_statut = $obj->fk_statut;
340 $this->progress = $obj->progress;
341 $this->budget_amount = $obj->budget_amount;
342 $this->priority = $obj->priority;
343 $this->note_private = $obj->note_private;
344 $this->note_public = $obj->note_public;
345 $this->rang = $obj->rang;
347 if (!empty($loadparentdata)) {
348 $this->task_parent_ref = $obj->task_parent_ref;
349 $this->task_parent_position = $obj->task_parent_position;
356 $this->db->free($resql);
364 $this->error =
"Error ".$this->db->lasterror();
377 public function update($user =
null, $notrigger = 0)
379 global $conf, $langs;
383 if (isset($this->fk_project)) {
384 $this->fk_project = trim($this->fk_project);
386 if (isset($this->
ref)) {
387 $this->
ref = trim($this->
ref);
389 if (isset($this->fk_task_parent)) {
390 $this->fk_task_parent = (int) $this->fk_task_parent;
392 if (isset($this->label)) {
393 $this->label = trim($this->label);
398 if (isset($this->duration_effective)) {
399 $this->duration_effective = trim($this->duration_effective);
401 if (isset($this->planned_workload)) {
402 $this->planned_workload = trim($this->planned_workload);
404 if (isset($this->budget_amount)) {
405 $this->budget_amount = trim($this->budget_amount);
408 if (!empty($this->date_start) && !empty($this->date_end) && $this->date_start > $this->date_end) {
409 $this->errors[] = $langs->trans(
'StartDateCannotBeAfterEndDate');
417 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"projet_task SET";
418 $sql .=
" fk_projet=".(isset($this->fk_project) ? $this->fk_project :
"null").
",";
419 $sql .=
" ref=".(isset($this->
ref) ?
"'".$this->db->escape($this->
ref).
"'" :
"'".$this->db->escape($this->
id).
"'").
",";
420 $sql .=
" fk_task_parent=".(isset($this->fk_task_parent) ? $this->fk_task_parent :
"null").
",";
421 $sql .=
" label=".(isset($this->label) ?
"'".$this->db->escape($this->label).
"'" :
"null").
",";
423 $sql .=
" duration_effective=".(isset($this->duration_effective) ? $this->duration_effective :
"null").
",";
424 $sql .=
" planned_workload=".((isset($this->planned_workload) && $this->planned_workload !=
'') ? $this->planned_workload :
"null").
",";
425 $sql .=
" dateo=".($this->date_start !=
'' ?
"'".$this->db->idate($this->date_start).
"'" :
'null').
",";
426 $sql .=
" datee=".($this->date_end !=
'' ?
"'".$this->db->idate($this->date_end).
"'" :
'null').
",";
427 $sql .=
" progress=".(($this->progress !=
'' && $this->progress >= 0) ? $this->progress :
'null').
",";
428 $sql .=
" budget_amount=".(($this->budget_amount !=
'' && $this->budget_amount >= 0) ? $this->budget_amount :
'null').
",";
429 $sql .=
" rang=".((!empty($this->rang)) ? $this->rang :
"0");
430 $sql .=
" WHERE rowid=".((int) $this->
id);
434 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
435 $resql = $this->db->query(
$sql);
437 $error++; $this->errors[] =
"Error ".$this->db->lasterror();
448 if (!$error && !empty($conf->global->PROJECT_CLASSIFY_CLOSED_WHEN_ALL_TASKS_DONE)) {
450 $project =
new Project($this->db);
451 if ($project->fetch($this->fk_project) > 0) {
453 $project->getLinesArray(
null);
454 $projectCompleted = array_reduce(
456 function ($allTasksCompleted, $task) {
457 return $allTasksCompleted && $task->progress >= 100;
461 if ($projectCompleted) {
462 if ($project->setClose($user) <= 0) {
471 $this->errors[] = $project->error;
486 if (!$error && (is_object($this->oldcopy) && $this->oldcopy->ref !== $this->ref)) {
488 if ($conf->project->dir_output) {
489 $project =
new Project($this->db);
490 $project->fetch($this->fk_project);
494 if (file_exists($olddir)) {
495 include_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
498 $langs->load(
"errors");
499 $this->error = $langs->trans(
'ErrorFailToRenameDir', $olddir, $newdir);
508 foreach ($this->errors as $errmsg) {
509 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
510 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
512 $this->db->rollback();
528 public function delete($user, $notrigger = 0)
531 global $conf, $langs;
532 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
539 dol_syslog(get_class($this).
"::delete Can't delete record as it has some sub tasks", LOG_WARNING);
540 $this->error =
'ErrorRecordHasSubTasks';
541 $this->db->rollback();
546 if (!empty($objectisused)) {
547 dol_syslog(get_class($this).
"::delete Can't delete record as it has some child", LOG_WARNING);
548 $this->error =
'ErrorRecordHasChildren';
549 $this->db->rollback();
557 $this->error =
'ErrorFailToDeleteLinkedContact';
559 $this->db->rollback();
565 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"element_time";
566 $sql .=
" WHERE fk_element = ".((int) $this->
id).
" AND elementtype = 'task'";
568 $resql = $this->db->query(
$sql);
570 $error++; $this->errors[] =
"Error ".$this->db->lasterror();
575 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"projet_task_extrafields";
576 $sql .=
" WHERE fk_object = ".((int) $this->
id);
578 $resql = $this->db->query(
$sql);
580 $error++; $this->errors[] =
"Error ".$this->db->lasterror();
585 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"projet_task";
586 $sql .=
" WHERE rowid=".((int) $this->
id);
588 $resql = $this->db->query(
$sql);
590 $error++; $this->errors[] =
"Error ".$this->db->lasterror();
607 foreach ($this->errors as $errmsg) {
608 dol_syslog(get_class($this).
"::delete ".$errmsg, LOG_ERR);
609 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
611 $this->db->rollback();
615 if ($conf->project->dir_output) {
616 $projectstatic =
new Project($this->db);
617 $projectstatic->fetch($this->fk_project);
620 dol_syslog(get_class($this).
"::delete dir=".$dir, LOG_DEBUG);
621 if (file_exists($dir)) {
622 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
625 $this->error =
'ErrorFailToDeleteDir';
626 $this->db->rollback();
648 $sql =
"SELECT COUNT(*) as nb";
649 $sql .=
" FROM ".MAIN_DB_PREFIX.
"projet_task";
650 $sql .=
" WHERE fk_task_parent = ".((int) $this->
id);
652 dol_syslog(get_class($this).
"::hasChildren", LOG_DEBUG);
653 $resql = $this->db->query(
$sql);
655 $error++; $this->errors[] =
"Error ".$this->db->lasterror();
657 $obj = $this->db->fetch_object($resql);
661 $this->db->free($resql);
681 $sql =
"SELECT COUNT(*) as nb";
682 $sql .=
" FROM ".MAIN_DB_PREFIX.
"element_time";
683 $sql .=
" WHERE fk_element = ".((int) $this->
id);
684 $sql .=
" AND elementtype = 'task'";
686 dol_syslog(get_class($this).
"::hasTimeSpent", LOG_DEBUG);
687 $resql = $this->db->query(
$sql);
689 $error++; $this->errors[] =
"Error ".$this->db->lasterror();
691 $obj = $this->db->fetch_object($resql);
695 $this->db->free($resql);
717 $langs->load(
'projects');
720 $datas[
'picto'] =
img_picto(
'', $this->picto).
' <u>'.$langs->trans(
"Task").
'</u>';
721 if (!empty($this->
ref)) {
722 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'Ref').
':</b> '.$this->ref;
724 if (!empty($this->label)) {
725 $datas[
'label'] =
'<br><b>'.$langs->trans(
'LabelTask').
':</b> '.$this->label;
727 if ($this->date_start || $this->date_end) {
728 $datas[
'range'] =
"<br>".get_date_range($this->date_start, $this->date_end,
'', $langs, 0);
746 public function getNomUrl($withpicto = 0, $option =
'', $mode =
'task', $addlabel = 0, $sep =
' - ', $notooltip = 0, $save_lastsearch_value = -1)
748 global $conf, $langs, $user;
750 if (!empty($conf->dol_no_mouse_hover)) {
757 'objecttype' => $this->element,
759 $classfortooltip =
'classfortooltip';
762 $classfortooltip =
'classforajaxtooltip';
763 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
769 $url = DOL_URL_ROOT.
'/projet/tasks/'.$mode.
'.php?id='.$this->
id.($option ==
'withproject' ?
'&withproject=1' :
'');
771 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
772 if ($save_lastsearch_value == -1 && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
773 $add_save_lastsearch_values = 1;
775 if ($add_save_lastsearch_values) {
776 $url .=
'&save_lastsearch_values=1';
780 if (empty($notooltip)) {
781 if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
782 $label = $langs->trans(
"ShowTask");
783 $linkclose .=
' alt="'.dol_escape_htmltag($label, 1).
'"';
785 $linkclose .= ($label ?
' title="'.dol_escape_htmltag($label, 1).
'"' :
' title="tocomplete"');
786 $linkclose .= $dataparams.
' class="'.$classfortooltip.
' nowraponall"';
788 $linkclose .=
' class="nowraponall"';
791 $linkstart =
'<a href="'.$url.
'"';
792 $linkstart .= $linkclose.
'>';
795 $picto =
'projecttask';
797 $result .= $linkstart;
799 $result .=
img_object(($notooltip ?
'' : $label), $picto,
'class="paddingright"', 0, 0, $notooltip ? 0 : 1);
801 if ($withpicto != 2) {
802 $result .= $this->ref;
805 if ($withpicto != 2) {
806 $result .= (($addlabel && $this->label) ? $sep.dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) :
'');
823 $this->fk_project =
'';
825 $this->fk_task_parent =
null;
826 $this->label =
'Specimen task TK01';
827 $this->duration_effective =
'';
828 $this->fk_user_creat =
null;
829 $this->progress =
'25';
830 $this->fk_statut =
null;
831 $this->note =
'This is a specimen task not';
857 public function getTasksArray($usert =
null, $userp =
null, $projectid = 0, $socid = 0, $mode = 0, $filteronproj =
'', $filteronprojstatus =
'-1', $morewherefilter =
'', $filteronprojuser = 0, $filterontaskuser = 0, $extrafields = array(), $includebilltime = 0, $search_array_options = array(), $loadextras = 0, $loadRoleMode = 1, $sortfield =
'', $sortorder =
'')
859 global $conf, $hookmanager;
867 if ($filteronprojuser > 0 || $filterontaskuser > 0) {
870 $sql .=
" p.rowid as projectid, p.ref, p.title as plabel, p.public, p.fk_statut as projectstatus, p.usage_bill_time,";
871 $sql .=
" t.rowid as taskid, t.ref as taskref, t.label, t.description, t.fk_task_parent, t.duration_effective, t.progress, t.fk_statut as status,";
872 $sql .=
" t.dateo as date_start, t.datee as date_end, t.planned_workload, t.rang,";
873 $sql .=
" t.description, ";
874 $sql .=
" t.budget_amount, ";
875 $sql .=
" s.rowid as thirdparty_id, s.nom as thirdparty_name, s.email as thirdparty_email,";
876 $sql .=
" p.fk_opp_status, p.opp_amount, p.opp_percent, p.budget_amount as project_budget_amount";
877 if (!empty($extrafields->attributes[
'projet'][
'label'])) {
878 foreach ($extrafields->attributes[
'projet'][
'label'] as $key => $val) {
879 $sql .= ($extrafields->attributes[
'projet'][
'type'][$key] !=
'separate' ?
",efp.".$key.
" as options_".$key :
'');
882 if (!empty($extrafields->attributes[
'projet_task'][
'label'])) {
883 foreach ($extrafields->attributes[
'projet_task'][
'label'] as $key => $val) {
884 $sql .= ($extrafields->attributes[
'projet_task'][
'type'][$key] !=
'separate' ?
",efpt.".$key.
" as options_".$key :
'');
887 if ($includebilltime) {
888 $sql .=
", SUM(tt.element_duration * ".$this->db->ifsql(
"invoice_id IS NULL",
"1",
"0").
") as tobill, SUM(tt.element_duration * ".$this->db->ifsql(
"invoice_id IS NULL",
"0",
"1").
") as billed";
891 $sql .=
" FROM ".MAIN_DB_PREFIX.
"projet as p";
892 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe as s ON p.fk_soc = s.rowid";
893 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"projet_extrafields as efp ON (p.rowid = efp.fk_object)";
896 if ($filteronprojuser > 0) {
897 $sql .=
", ".MAIN_DB_PREFIX.
"element_contact as ec";
898 $sql .=
", ".MAIN_DB_PREFIX.
"c_type_contact as ctc";
900 $sql .=
", ".MAIN_DB_PREFIX.
"projet_task as t";
901 if ($includebilltime) {
902 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"element_time as tt ON (tt.fk_element = t.rowid AND tt.elementtype='task')";
904 if ($filterontaskuser > 0) {
905 $sql .=
", ".MAIN_DB_PREFIX.
"element_contact as ec2";
906 $sql .=
", ".MAIN_DB_PREFIX.
"c_type_contact as ctc2";
908 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"projet_task_extrafields as efpt ON (t.rowid = efpt.fk_object)";
909 $sql .=
" WHERE p.entity IN (".getEntity(
'project').
")";
910 $sql .=
" AND t.fk_projet = p.rowid";
911 } elseif ($mode == 1) {
912 if ($filteronprojuser > 0) {
913 $sql .=
", ".MAIN_DB_PREFIX.
"element_contact as ec";
914 $sql .=
", ".MAIN_DB_PREFIX.
"c_type_contact as ctc";
916 if ($filterontaskuser > 0) {
917 $sql .=
", ".MAIN_DB_PREFIX.
"projet_task as t";
918 if ($includebilltime) {
919 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"element_time as tt ON (tt.fk_element = t.rowid AND tt.elementtype='task')";
921 $sql .=
", ".MAIN_DB_PREFIX.
"element_contact as ec2";
922 $sql .=
", ".MAIN_DB_PREFIX.
"c_type_contact as ctc2";
924 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"projet_task as t on t.fk_projet = p.rowid";
925 if ($includebilltime) {
926 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"element_time as tt ON (tt.fk_element = t.rowid AND tt.elementtype = 'task')";
929 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"projet_task_extrafields as efpt ON (t.rowid = efpt.fk_object)";
930 $sql .=
" WHERE p.entity IN (".getEntity(
'project').
")";
932 return 'BadValueForParameterMode';
935 if ($filteronprojuser > 0) {
936 $sql .=
" AND p.rowid = ec.element_id";
937 $sql .=
" AND ctc.rowid = ec.fk_c_type_contact";
938 $sql .=
" AND ctc.element = 'project'";
939 $sql .=
" AND ec.fk_socpeople = ".((int) $filteronprojuser);
940 $sql .=
" AND ec.statut = 4";
941 $sql .=
" AND ctc.source = 'internal'";
943 if ($filterontaskuser > 0) {
944 $sql .=
" AND t.fk_projet = p.rowid";
945 $sql .=
" AND p.rowid = ec2.element_id";
946 $sql .=
" AND ctc2.rowid = ec2.fk_c_type_contact";
947 $sql .=
" AND ctc2.element = 'project_task'";
948 $sql .=
" AND ec2.fk_socpeople = ".((int) $filterontaskuser);
949 $sql .=
" AND ec2.statut = 4";
950 $sql .=
" AND ctc2.source = 'internal'";
953 $sql .=
" AND p.fk_soc = ".((int) $socid);
956 $sql .=
" AND p.rowid IN (".$this->db->sanitize($projectid).
")";
961 if ($filteronprojstatus && $filteronprojstatus !=
'-1') {
962 $sql .=
" AND p.fk_statut IN (".$this->db->sanitize($filteronprojstatus).
")";
964 if ($morewherefilter) {
965 $sql .= $morewherefilter;
968 $extrafieldsobjectkey =
'projet_task';
969 $extrafieldsobjectprefix =
'efpt.';
971 include DOL_DOCUMENT_ROOT.
'/core/tpl/extrafields_list_search_sql.tpl.php';
973 $parameters = array();
974 $reshook = $hookmanager->executeHooks(
'printFieldListWhere', $parameters);
975 $sql .= $hookmanager->resPrint;
976 if ($includebilltime) {
977 $sql .=
" GROUP BY p.rowid, p.ref, p.title, p.public, p.fk_statut, p.usage_bill_time,";
978 $sql .=
" t.datec, t.dateo, t.datee, t.tms,";
979 $sql .=
" t.rowid, t.ref, t.label, t.description, t.fk_task_parent, t.duration_effective, t.progress, t.fk_statut,";
980 $sql .=
" t.dateo, t.datee, t.planned_workload, t.rang,";
981 $sql .=
" t.description, ";
982 $sql .=
" t.budget_amount, ";
983 $sql .=
" s.rowid, s.nom, s.email,";
984 $sql .=
" p.fk_opp_status, p.opp_amount, p.opp_percent, p.budget_amount";
985 if (!empty($extrafields->attributes[
'projet'][
'label'])) {
986 foreach ($extrafields->attributes[
'projet'][
'label'] as $key => $val) {
987 $sql .= ($extrafields->attributes[
'projet'][
'type'][$key] !=
'separate' ?
",efp.".$key :
'');
990 if (!empty($extrafields->attributes[
'projet_task'][
'label'])) {
991 foreach ($extrafields->attributes[
'projet_task'][
'label'] as $key => $val) {
992 $sql .= ($extrafields->attributes[
'projet_task'][
'type'][$key] !=
'separate' ?
",efpt.".$key :
'');
997 if ($sortfield && $sortorder) {
998 $sql .= $this->db->order($sortfield, $sortorder);
1000 $sql .=
" ORDER BY p.ref, t.rang, t.dateo";
1004 dol_syslog(get_class($this).
"::getTasksArray", LOG_DEBUG);
1005 $resql = $this->db->query(
$sql);
1007 $num = $this->db->num_rows($resql);
1013 $obj = $this->db->fetch_object($resql);
1015 if ($loadRoleMode) {
1016 if ((!$obj->public) && (is_object($userp))) {
1021 if (is_object($usert)) {
1029 $tasks[$i] =
new Task($this->db);
1030 $tasks[$i]->id = $obj->taskid;
1031 $tasks[$i]->ref = $obj->taskref;
1032 $tasks[$i]->fk_project = $obj->projectid;
1033 $tasks[$i]->projectref = $obj->ref;
1034 $tasks[$i]->projectlabel = $obj->plabel;
1035 $tasks[$i]->projectstatus = $obj->projectstatus;
1037 $tasks[$i]->fk_opp_status = $obj->fk_opp_status;
1038 $tasks[$i]->opp_amount = $obj->opp_amount;
1039 $tasks[$i]->opp_percent = $obj->opp_percent;
1040 $tasks[$i]->budget_amount = $obj->budget_amount;
1041 $tasks[$i]->project_budget_amount = $obj->project_budget_amount;
1042 $tasks[$i]->usage_bill_time = $obj->usage_bill_time;
1044 $tasks[$i]->label = $obj->label;
1045 $tasks[$i]->description = $obj->description;
1046 $tasks[$i]->fk_parent = $obj->fk_task_parent;
1047 $tasks[$i]->fk_task_parent = $obj->fk_task_parent;
1048 $tasks[$i]->duration = $obj->duration_effective;
1049 $tasks[$i]->planned_workload = $obj->planned_workload;
1051 if ($includebilltime) {
1052 $tasks[$i]->tobill = $obj->tobill;
1053 $tasks[$i]->billed = $obj->billed;
1056 $tasks[$i]->progress = $obj->progress;
1057 $tasks[$i]->fk_statut = $obj->status;
1058 $tasks[$i]->public = $obj->public;
1059 $tasks[$i]->date_start = $this->db->jdate($obj->date_start);
1060 $tasks[$i]->date_end = $this->db->jdate($obj->date_end);
1061 $tasks[$i]->rang = $obj->rang;
1063 $tasks[$i]->socid = $obj->thirdparty_id;
1064 $tasks[$i]->thirdparty_id = $obj->thirdparty_id;
1065 $tasks[$i]->thirdparty_name = $obj->thirdparty_name;
1066 $tasks[$i]->thirdparty_email = $obj->thirdparty_email;
1068 if (!empty($extrafields->attributes[
'projet'][
'label'])) {
1069 foreach ($extrafields->attributes[
'projet'][
'label'] as $key => $val) {
1070 if ($extrafields->attributes[
'projet'][
'type'][$key] !=
'separate') {
1071 $tmpvar =
'options_'.$key;
1072 $tasks[$i]->{
'options_'.$key} = $obj->$tmpvar;
1077 if (!empty($extrafields->attributes[
'projet_task'][
'label'])) {
1078 foreach ($extrafields->attributes[
'projet_task'][
'label'] as $key => $val) {
1079 if ($extrafields->attributes[
'projet_task'][
'type'][$key] !=
'separate') {
1080 $tmpvar =
'options_'.$key;
1081 $tasks[$i]->{
'options_'.$key} = $obj->$tmpvar;
1087 $tasks[$i]->fetch_optionals();
1093 $this->db->free($resql);
1113 $arrayroles = array();
1115 dol_syslog(get_class($this).
"::getUserRolesForProjectsOrTasks userp=".is_object($userp).
" usert=".is_object($usert).
" projectid=".$projectid.
" taskid=".$taskid);
1118 if (empty($userp) && empty($usert)) {
1119 $this->error =
"CallWithWrongParameters";
1122 if (!empty($userp) && !empty($usert)) {
1123 $this->error =
"CallWithWrongParameters";
1128 $sql =
"SELECT pt.rowid as pid, ec.element_id, ctc.code, ctc.source";
1130 $sql .=
" FROM ".MAIN_DB_PREFIX.
"projet as pt";
1132 if ($usert && $filteronprojstatus > -1) {
1133 $sql .=
" FROM ".MAIN_DB_PREFIX.
"projet as p, ".MAIN_DB_PREFIX.
"projet_task as pt";
1135 if ($usert && $filteronprojstatus <= -1) {
1136 $sql .=
" FROM ".MAIN_DB_PREFIX.
"projet_task as pt";
1138 $sql .=
", ".MAIN_DB_PREFIX.
"element_contact as ec";
1139 $sql .=
", ".MAIN_DB_PREFIX.
"c_type_contact as ctc";
1140 $sql .=
" WHERE pt.rowid = ec.element_id";
1141 if ($userp && $filteronprojstatus > -1) {
1142 $sql .=
" AND pt.fk_statut = ".((int) $filteronprojstatus);
1144 if ($usert && $filteronprojstatus > -1) {
1145 $sql .=
" AND pt.fk_projet = p.rowid AND p.fk_statut = ".((int) $filteronprojstatus);
1148 $sql .=
" AND ctc.element = 'project'";
1151 $sql .=
" AND ctc.element = 'project_task'";
1153 $sql .=
" AND ctc.rowid = ec.fk_c_type_contact";
1155 $sql .=
" AND ec.fk_socpeople = ".((int) $userp->id);
1158 $sql .=
" AND ec.fk_socpeople = ".((int) $usert->id);
1160 $sql .=
" AND ec.statut = 4";
1161 $sql .=
" AND ctc.source = 'internal'";
1164 $sql .=
" AND pt.rowid IN (".$this->db->sanitize($projectid).
")";
1167 $sql .=
" AND pt.fk_projet IN (".$this->db->sanitize($projectid).
")";
1172 $sql .=
" ERROR SHOULD NOT HAPPENS";
1175 $sql .=
" AND pt.rowid = ".((int) $taskid);
1180 dol_syslog(get_class($this).
"::getUserRolesForProjectsOrTasks execute request", LOG_DEBUG);
1181 $resql = $this->db->query(
$sql);
1183 $num = $this->db->num_rows($resql);
1186 $obj = $this->db->fetch_object($resql);
1187 if (empty($arrayroles[$obj->pid])) {
1188 $arrayroles[$obj->pid] = $obj->code;
1190 $arrayroles[$obj->pid] .=
','.$obj->code;
1194 $this->db->free($resql);
1211 $contactAlreadySelected = array();
1212 $tab = $this->liste_contact(-1, $source);
1217 if ($source ==
'thirdparty') {
1218 $contactAlreadySelected[$i] = $tab[$i][
'socid'];
1220 $contactAlreadySelected[$i] = $tab[$i][
'id'];
1224 return $contactAlreadySelected;
1237 global $conf, $langs;
1239 dol_syslog(get_class($this).
"::addTimeSpent", LOG_DEBUG);
1245 if (!is_object($user)) {
1246 dol_print_error(
'',
"Method addTimeSpent was called with wrong parameter user");
1251 if (isset($this->timespent_note)) {
1252 $this->timespent_note = trim($this->timespent_note);
1254 if (empty($this->timespent_datehour)) {
1255 $this->timespent_datehour = $this->timespent_date;
1258 if (!empty($conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS)) {
1259 require_once DOL_DOCUMENT_ROOT.
'/core/lib/date.lib.php';
1262 if ($this->timespent_date < $restrictBefore) {
1263 $this->error = $langs->trans(
'TimeRecordingRestrictedToNMonthsBack', $conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS);
1264 $this->errors[] = $this->error;
1273 $timespent->fk_element = $this->id;
1274 $timespent->elementtype =
'task';
1275 $timespent->element_date = $this->timespent_date;
1276 $timespent->element_datehour = $this->timespent_datehour;
1277 $timespent->element_date_withhour = $this->timespent_withhour;
1278 $timespent->element_duration = $this->timespent_duration;
1279 $timespent->fk_user = $this->timespent_fk_user;
1280 $timespent->fk_product = $this->timespent_fk_product;
1281 $timespent->note = $this->timespent_note;
1282 $timespent->datec = $this->db->idate($now);
1284 if ($timespent->create($user) > 0) {
1285 $tasktime_id = $this->db->last_insert_id(MAIN_DB_PREFIX.
"element_time");
1286 $ret = $tasktime_id;
1287 $this->timespent_id = $ret;
1291 $result = $this->call_trigger(
'TASK_TIMESPENT_CREATE', $user);
1298 $this->error = $this->db->lasterror();
1304 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"projet_task";
1305 $sql .=
" SET duration_effective = (SELECT SUM(element_duration) FROM ".MAIN_DB_PREFIX.
"element_time as ptt where ptt.elementtype = 'task' AND ptt.fk_element = ".((int) $this->
id).
")";
1306 if (isset($this->progress)) {
1307 $sql .=
", progress = ".((float) $this->progress);
1309 $sql .=
" WHERE rowid = ".((int) $this->
id);
1311 dol_syslog(get_class($this).
"::addTimeSpent", LOG_DEBUG);
1312 if (!$this->db->query(
$sql)) {
1313 $this->error = $this->db->lasterror();
1318 $resql_thm_user = $this->db->query(
"SELECT thm FROM " . MAIN_DB_PREFIX .
"user WHERE rowid = " . ((
int) $timespent->fk_user));
1319 if (!empty($resql_thm_user)) {
1320 $obj_thm_user = $this->db->fetch_object($resql_thm_user);
1321 $timespent->thm = $obj_thm_user->thm;
1323 $res_update = $timespent->update($user);
1325 dol_syslog(get_class($this).
"::addTimeSpent", LOG_DEBUG);
1326 if ($res_update <= 0) {
1327 $this->error = $this->db->lasterror();
1333 $this->db->commit();
1335 $this->db->rollback();
1350 $arrayres = array();
1353 $sql .=
" s.rowid as socid,";
1354 $sql .=
" s.nom as thirdparty_name,";
1355 $sql .=
" s.email as thirdparty_email,";
1356 $sql .=
" ptt.rowid,";
1357 $sql .=
" ptt.fk_element as fk_task,";
1358 $sql .=
" ptt.element_date as task_date,";
1359 $sql .=
" ptt.element_datehour as task_datehour,";
1360 $sql .=
" ptt.element_date_withhour as task_date_withhour,";
1361 $sql .=
" ptt.element_duration as task_duration,";
1362 $sql .=
" ptt.fk_user,";
1363 $sql .=
" ptt.note,";
1364 $sql .=
" ptt.thm,";
1365 $sql .=
" pt.rowid as task_id,";
1366 $sql .=
" pt.ref as task_ref,";
1367 $sql .=
" pt.label as task_label,";
1368 $sql .=
" p.rowid as project_id,";
1369 $sql .=
" p.ref as project_ref,";
1370 $sql .=
" p.title as project_label,";
1371 $sql .=
" p.public as public";
1372 $sql .=
" FROM ".MAIN_DB_PREFIX.
"element_time as ptt, ".MAIN_DB_PREFIX.
"projet_task as pt, ".MAIN_DB_PREFIX.
"projet as p";
1373 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe as s ON p.fk_soc = s.rowid";
1374 $sql .=
" WHERE ptt.fk_element = pt.rowid AND pt.fk_projet = p.rowid";
1375 $sql .=
" AND ptt.elementtype = 'task'";
1376 $sql .=
" AND pt.rowid = ".((int) $this->
id);
1377 $sql .=
" AND pt.entity IN (".getEntity(
'project').
")";
1378 if ($morewherefilter) {
1379 $sql .= $morewherefilter;
1382 dol_syslog(get_class($this).
"::fetchAllTimeSpent", LOG_DEBUG);
1383 $resql = $this->db->query(
$sql);
1385 $num = $this->db->num_rows($resql);
1389 $obj = $this->db->fetch_object($resql);
1391 $newobj =
new stdClass();
1393 $newobj->socid = $obj->socid;
1394 $newobj->thirdparty_name = $obj->thirdparty_name;
1395 $newobj->thirdparty_email = $obj->thirdparty_email;
1397 $newobj->fk_project = $obj->project_id;
1398 $newobj->project_ref = $obj->project_ref;
1399 $newobj->project_label = $obj->project_label;
1400 $newobj->public = $obj->project_public;
1402 $newobj->fk_task = $obj->task_id;
1403 $newobj->task_ref = $obj->task_ref;
1404 $newobj->task_label = $obj->task_label;
1406 $newobj->timespent_line_id = $obj->rowid;
1407 $newobj->timespent_line_date = $this->db->jdate($obj->task_date);
1408 $newobj->timespent_line_datehour = $this->db->jdate($obj->task_datehour);
1409 $newobj->timespent_line_withhour = $obj->task_date_withhour;
1410 $newobj->timespent_line_duration = $obj->task_duration;
1411 $newobj->timespent_line_fk_user = $obj->fk_user;
1412 $newobj->timespent_line_thm = $obj->thm;
1413 $newobj->timespent_line_note = $obj->note;
1415 $arrayres[] = $newobj;
1420 $this->db->free($resql);
1422 $this->lines = $arrayres;
1426 $this->error =
"Error ".$this->db->lasterror();
1441 if (is_object($userobj)) {
1442 $userid = $userobj->id;
1448 if (empty($id) && empty($userid)) {
1449 dol_syslog(
"getSummaryOfTimeSpent called on a not loaded task without user param defined", LOG_ERR);
1456 $sql .=
" MIN(t.element_datehour) as min_date,";
1457 $sql .=
" MAX(t.element_datehour) as max_date,";
1458 $sql .=
" SUM(t.element_duration) as total_duration,";
1459 $sql .=
" SUM(t.element_duration / 3600 * ".$this->db->ifsql(
"t.thm IS NULL", 0,
"t.thm").
") as total_amount,";
1460 $sql .=
" COUNT(t.rowid) as nblines,";
1461 $sql .=
" SUM(".$this->db->ifsql(
"t.thm IS NULL", 1, 0).
") as nblinesnull";
1462 $sql .=
" FROM ".MAIN_DB_PREFIX.
"element_time as t";
1463 $sql .=
" WHERE t.elementtype='task'";
1464 if ($morewherefilter) {
1465 $sql .= $morewherefilter;
1468 $sql .=
" AND t.fk_element = ".((int) $id);
1471 $sql .=
" AND t.fk_user = ".((int) $userid);
1474 dol_syslog(get_class($this).
"::getSummaryOfTimeSpent", LOG_DEBUG);
1475 $resql = $this->db->query(
$sql);
1477 $obj = $this->db->fetch_object($resql);
1479 $result[
'min_date'] = $obj->min_date;
1480 $result[
'max_date'] = $obj->max_date;
1481 $result[
'total_duration'] = $obj->total_duration;
1483 $this->timespent_min_date = $this->db->jdate($obj->min_date);
1484 $this->timespent_max_date = $this->db->jdate($obj->max_date);
1485 $this->timespent_total_duration = $obj->total_duration;
1486 $this->timespent_total_amount = $obj->total_amount;
1487 $this->timespent_nblinesnull = ($obj->nblinesnull ? $obj->nblinesnull : 0);
1488 $this->timespent_nblines = ($obj->nblines ? $obj->nblines : 0);
1490 $this->db->free($resql);
1516 $sql .=
" SUM(t.element_duration) as nbseconds,";
1517 $sql .=
" SUM(t.element_duration / 3600 * ".$this->db->ifsql(
"t.thm IS NULL", 0,
"t.thm").
") as amount, SUM(".$this->db->ifsql(
"t.thm IS NULL", 1, 0).
") as nblinesnull";
1518 $sql .=
" FROM ".MAIN_DB_PREFIX.
"element_time as t";
1519 $sql .=
" WHERE t.elementtype='task' AND t.fk_element = ".((int) $id);
1520 if (is_object($fuser) && $fuser->id > 0) {
1521 $sql .=
" AND fk_user = ".((int) $fuser->id);
1524 $datefieldname =
"element_datehour";
1525 $sql .=
" AND (".$datefieldname.
" >= '".$this->db->idate($dates).
"' OR ".$datefieldname.
" IS NULL)";
1528 $datefieldname =
"element_datehour";
1529 $sql .=
" AND (".$datefieldname.
" <= '".$this->db->idate($datee).
"' OR ".$datefieldname.
" IS NULL)";
1533 dol_syslog(get_class($this).
"::getSumOfAmount", LOG_DEBUG);
1534 $resql = $this->db->query(
$sql);
1536 $obj = $this->db->fetch_object($resql);
1538 $result[
'amount'] = $obj->amount;
1539 $result[
'nbseconds'] = $obj->nbseconds;
1540 $result[
'nblinesnull'] = $obj->nblinesnull;
1542 $this->db->free($resql);
1561 $timespent->fetch($id);
1563 dol_syslog(get_class($this).
"::fetchTimeSpent", LOG_DEBUG);
1565 if ($timespent->id > 0) {
1566 $this->timespent_id = $timespent->id;
1567 $this->
id = $timespent->fk_element;
1568 $this->timespent_date = $this->db->jdate($timespent->element_date);
1569 $this->timespent_datehour = $this->db->jdate($timespent->element_datehour);
1570 $this->timespent_withhour = $timespent->element_date_withhour;
1571 $this->timespent_duration = $timespent->element_duration;
1572 $this->timespent_fk_user = $timespent->fk_user;
1573 $this->timespent_fk_product = $timespent->fk_product;
1574 $this->timespent_thm = $timespent->thm;
1575 $this->timespent_note = $timespent->note;
1592 $arrayres = array();
1595 $sql .=
" s.rowid as socid,";
1596 $sql .=
" s.nom as thirdparty_name,";
1597 $sql .=
" s.email as thirdparty_email,";
1598 $sql .=
" ptt.rowid,";
1599 $sql .=
" ptt.fk_element as fk_task,";
1600 $sql .=
" ptt.element_date as task_date,";
1601 $sql .=
" ptt.element_datehour as task_datehour,";
1602 $sql .=
" ptt.element_date_withhour as task_date_withhour,";
1603 $sql .=
" ptt.element_duration as task_duration,";
1604 $sql .=
" ptt.fk_user,";
1605 $sql .=
" ptt.note,";
1606 $sql .=
" ptt.thm,";
1607 $sql .=
" pt.rowid as task_id,";
1608 $sql .=
" pt.ref as task_ref,";
1609 $sql .=
" pt.label as task_label,";
1610 $sql .=
" p.rowid as project_id,";
1611 $sql .=
" p.ref as project_ref,";
1612 $sql .=
" p.title as project_label,";
1613 $sql .=
" p.public as public";
1614 $sql .=
" FROM ".MAIN_DB_PREFIX.
"element_time as ptt, ".MAIN_DB_PREFIX.
"projet_task as pt, ".MAIN_DB_PREFIX.
"projet as p";
1615 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe as s ON p.fk_soc = s.rowid";
1616 $sql .=
" WHERE ptt.fk_element = pt.rowid AND pt.fk_projet = p.rowid";
1617 $sql .=
" AND ptt.elementtype = 'task'";
1618 $sql .=
" AND ptt.fk_user = ".((int) $userobj->id);
1619 $sql .=
" AND pt.entity IN (".getEntity(
'project').
")";
1620 if ($morewherefilter) {
1621 $sql .= $morewherefilter;
1624 dol_syslog(get_class($this).
"::fetchAllTimeSpent", LOG_DEBUG);
1625 $resql = $this->db->query(
$sql);
1627 $num = $this->db->num_rows($resql);
1631 $obj = $this->db->fetch_object($resql);
1633 $newobj =
new stdClass();
1635 $newobj->socid = $obj->socid;
1636 $newobj->thirdparty_name = $obj->thirdparty_name;
1637 $newobj->thirdparty_email = $obj->thirdparty_email;
1639 $newobj->fk_project = $obj->project_id;
1640 $newobj->project_ref = $obj->project_ref;
1641 $newobj->project_label = $obj->project_label;
1642 $newobj->public = $obj->project_public;
1644 $newobj->fk_task = $obj->task_id;
1645 $newobj->task_ref = $obj->task_ref;
1646 $newobj->task_label = $obj->task_label;
1648 $newobj->timespent_id = $obj->rowid;
1649 $newobj->timespent_date = $this->db->jdate($obj->task_date);
1650 $newobj->timespent_datehour = $this->db->jdate($obj->task_datehour);
1651 $newobj->timespent_withhour = $obj->task_date_withhour;
1652 $newobj->timespent_duration = $obj->task_duration;
1653 $newobj->timespent_fk_user = $obj->fk_user;
1654 $newobj->timespent_thm = $obj->thm;
1655 $newobj->timespent_note = $obj->note;
1657 $arrayres[] = $newobj;
1662 $this->db->free($resql);
1665 $this->error =
"Error ".$this->db->lasterror();
1681 global $conf, $langs;
1686 if ($this->timespent_date ==
'') {
1687 $this->error = $langs->trans(
"ErrorFieldRequired", $langs->transnoentities(
"Date"));
1690 if (!($this->timespent_fk_user > 0)) {
1691 $this->error = $langs->trans(
"ErrorFieldRequired", $langs->transnoentities(
"User"));
1696 if (empty($this->timespent_datehour)) {
1697 $this->timespent_datehour = $this->timespent_date;
1699 if (isset($this->timespent_note)) {
1700 $this->timespent_note = trim($this->timespent_note);
1703 if (!empty($conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS)) {
1704 require_once DOL_DOCUMENT_ROOT.
'/core/lib/date.lib.php';
1707 if ($this->timespent_date < $restrictBefore) {
1708 $this->error = $langs->trans(
'TimeRecordingRestrictedToNMonthsBack', $conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS);
1709 $this->errors[] = $this->error;
1717 $timespent->fetch($this->timespent_id);
1718 $timespent->element_date = $this->timespent_date;
1719 $timespent->element_datehour = $this->timespent_datehour;
1720 $timespent->element_date_withhour = $this->timespent_withhour;
1721 $timespent->element_duration = $this->timespent_duration;
1722 $timespent->fk_user = $this->timespent_fk_user;
1723 $timespent->fk_product = $this->timespent_fk_product;
1724 $timespent->note = $this->timespent_note;
1725 $timespent->invoice_id = $this->timespent_invoiceid;
1726 $timespent->invoice_line_id = $this->timespent_invoicelineid;
1728 dol_syslog(get_class($this).
"::updateTimeSpent", LOG_DEBUG);
1729 if ($timespent->update($user) > 0) {
1732 $result = $this->call_trigger(
'TASK_TIMESPENT_MODIFY', $user);
1734 $this->db->rollback();
1744 $this->error = $this->db->lasterror();
1745 $this->db->rollback();
1749 if ($ret == 1 && (($this->timespent_old_duration != $this->timespent_duration) || !empty($conf->global->TIMESPENT_ALWAYS_UPDATE_THM))) {
1750 if ($this->timespent_old_duration != $this->timespent_duration) {
1752 $sql =
"UPDATE " . MAIN_DB_PREFIX .
"projet_task";
1753 $sql .=
" SET duration_effective = (SELECT SUM(element_duration) FROM " . MAIN_DB_PREFIX .
"element_time as ptt where ptt.elementtype = 'task' AND ptt.fk_element = " . ((int) $this->
id) .
")";
1754 if (isset($this->progress)) {
1755 $sql .=
", progress = " . ((
float) $this->progress);
1757 $sql .=
" WHERE rowid = " . ((int) $this->
id);
1759 dol_syslog(get_class($this) .
"::updateTimeSpent", LOG_DEBUG);
1760 if (!$this->db->query(
$sql)) {
1761 $this->error = $this->db->lasterror();
1762 $this->db->rollback();
1769 if (empty($timespent->thm) || !empty($conf->global->TIMESPENT_ALWAYS_UPDATE_THM)) {
1770 $resql_thm_user = $this->db->query(
"SELECT thm FROM " . MAIN_DB_PREFIX .
"user WHERE rowid = " . ((
int) $timespent->fk_user));
1771 if (!empty($resql_thm_user)) {
1772 $obj_thm_user = $this->db->fetch_object($resql_thm_user);
1773 $timespent->thm = $obj_thm_user->thm;
1775 $res_update = $timespent->update($user);
1778 dol_syslog(get_class($this).
"::updateTimeSpent", LOG_DEBUG);
1779 if ($res_update <= 0) {
1780 $this->error = $this->db->lasterror();
1786 $this->db->commit();
1800 global $conf, $langs;
1804 if (!empty($conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS)) {
1805 require_once DOL_DOCUMENT_ROOT.
'/core/lib/date.lib.php';
1808 if ($this->timespent_date < $restrictBefore) {
1809 $this->error = $langs->trans(
'TimeRecordingRestrictedToNMonthsBack', $conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS);
1810 $this->errors[] = $this->error;
1819 $result = $this->call_trigger(
'TASK_TIMESPENT_DELETE', $user);
1828 $timespent->fetch($this->timespent_id);
1830 $res_del = $timespent->delete($user);
1833 $error++; $this->errors[] =
"Error ".$this->db->lasterror();
1838 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"projet_task";
1839 $sql .=
" SET duration_effective = duration_effective - ".$this->db->escape($this->timespent_duration ? $this->timespent_duration : 0);
1840 $sql .=
" WHERE rowid = ".((int) $this->
id);
1842 dol_syslog(get_class($this).
"::delTimeSpent", LOG_DEBUG);
1843 if ($this->db->query(
$sql)) {
1846 $this->error = $this->db->lasterror();
1853 foreach ($this->errors as $errmsg) {
1854 dol_syslog(get_class($this).
"::delTimeSpent ".$errmsg, LOG_ERR);
1855 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
1857 $this->db->rollback();
1860 $this->db->commit();
1879 public function createFromClone(
User $user, $fromid, $project_id, $parent_task_id, $clone_change_dt =
false, $clone_affectation =
false, $clone_time =
false, $clone_file =
false, $clone_note =
false, $clone_prog =
false)
1881 global $langs, $conf;
1890 $clone_task =
new Task($this->db);
1891 $origin_task =
new Task($this->db);
1893 $clone_task->context[
'createfromclone'] =
'createfromclone';
1898 $clone_task->fetch($fromid);
1899 $clone_task->fetch_optionals();
1902 $origin_task->fetch($fromid);
1905 $obj = empty($conf->global->PROJECT_TASK_ADDON) ?
'mod_task_simple' : $conf->global->PROJECT_TASK_ADDON;
1906 if (!empty($conf->global->PROJECT_TASK_ADDON) && is_readable(DOL_DOCUMENT_ROOT.
"/core/modules/project/task/".$conf->global->PROJECT_TASK_ADDON.
".php")) {
1907 require_once DOL_DOCUMENT_ROOT.
"/core/modules/project/task/".$conf->global->PROJECT_TASK_ADDON.
'.php';
1908 $modTask =
new $obj;
1909 $defaultref = $modTask->getNextValue(0, $clone_task);
1912 $ori_project_id = $clone_task->fk_project;
1914 $clone_task->id = 0;
1915 $clone_task->ref = $defaultref;
1916 $clone_task->fk_project = $project_id;
1917 $clone_task->fk_task_parent = $parent_task_id;
1918 $clone_task->date_c = $datec;
1919 $clone_task->planned_workload = $origin_task->planned_workload;
1920 $clone_task->rang = $origin_task->rang;
1923 if ($clone_change_dt) {
1924 $projectstatic =
new Project($this->db);
1925 $projectstatic->fetch($ori_project_id);
1928 $orign_project_dt_start = $projectstatic->date_start;
1931 if (!empty($clone_task->date_start)) {
1932 $clone_task->date_start = $now + $clone_task->date_start - $orign_project_dt_start;
1936 if (!empty($clone_task->date_end)) {
1937 $clone_task->date_end = $now + $clone_task->date_end - $orign_project_dt_start;
1942 $clone_task->progress = 0;
1946 $result = $clone_task->create($user);
1950 $this->error = $clone_task->error;
1956 $clone_task_id = $clone_task->id;
1957 $clone_task_ref = $clone_task->ref;
1961 $clone_task->note_private =
'';
1962 $clone_task->note_public =
'';
1965 $res = $clone_task->update_note(
dol_html_entity_decode($clone_task->note_public, ENT_QUOTES | ENT_HTML5),
'_public');
1967 $this->error .= $clone_task->error;
1969 $this->db->rollback();
1971 $this->db->commit();
1975 $res = $clone_task->update_note(
dol_html_entity_decode($clone_task->note_private, ENT_QUOTES | ENT_HTML5),
'_private');
1977 $this->error .= $clone_task->error;
1979 $this->db->rollback();
1981 $this->db->commit();
1987 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
1990 $projectstatic =
new Project($this->db);
1991 $projectstatic->fetch($ori_project_id);
1992 $ori_project_ref = $projectstatic->ref;
1994 if ($ori_project_id != $project_id) {
1995 $projectstatic->fetch($project_id);
1996 $clone_project_ref = $projectstatic->ref;
1998 $clone_project_ref = $ori_project_ref;
2004 $filearray =
dol_dir_list($ori_task_dir,
"files", 0,
'',
'(\.meta|_preview.*\.png)$',
'', SORT_ASC, 1);
2005 foreach ($filearray as $key => $file) {
2006 if (!file_exists($clone_task_dir)) {
2008 $this->error .= $langs->trans(
'ErrorInternalErrorDetected').
':dol_mkdir';
2013 $rescopy =
dol_copy($ori_task_dir.
'/'.$file[
'name'], $clone_task_dir.
'/'.$file[
'name'], 0, 1);
2014 if (is_numeric($rescopy) && $rescopy < 0) {
2015 $this->error .= $langs->trans(
"ErrorFailToCopyFile", $ori_task_dir.
'/'.$file[
'name'], $clone_task_dir.
'/'.$file[
'name']);
2022 if ($clone_affectation) {
2023 $origin_task =
new Task($this->db);
2024 $origin_task->fetch($fromid);
2026 foreach (array(
'internal',
'external') as $source) {
2027 $tab = $origin_task->liste_contact(-1, $source);
2031 $clone_task->add_contact($tab[$i][
'id'], $tab[$i][
'code'], $tab[$i][
'source']);
2032 if ($clone_task->error ==
'DB_ERROR_RECORD_ALREADY_EXISTS') {
2033 $langs->load(
"errors");
2034 $this->error .= $langs->trans(
"ErrorThisContactIsAlreadyDefinedAsThisType");
2037 if ($clone_task->error !=
'') {
2038 $this->error .= $clone_task->error;
2052 unset($clone_task->context[
'createfromclone']);
2055 $this->db->commit();
2056 return $clone_task_id;
2058 $this->db->rollback();
2059 dol_syslog(get_class($this).
"::createFromClone nbError: ".$error.
" error : ".$this->error, LOG_ERR);
2073 return $this->LibStatut($this->fk_statut, $mode);
2090 $this->statuts[0] =
'Draft';
2091 $this->statuts[1] =
'ToDo';
2092 $this->statuts[2] =
'Running';
2093 $this->statuts[3] =
'Finish';
2094 $this->statuts[4] =
'Transfered';
2095 $this->statuts_short[0] =
'Draft';
2096 $this->statuts_short[1] =
'ToDo';
2097 $this->statuts_short[2] =
'Running';
2098 $this->statuts_short[3] =
'Completed';
2099 $this->statuts_short[4] =
'Transfered';
2102 return $langs->trans($this->statuts[$status]);
2103 } elseif ($mode == 1) {
2104 return $langs->trans($this->statuts_short[$status]);
2105 } elseif ($mode == 2) {
2107 return img_picto($langs->trans($this->statuts_short[$status]),
'statut0').
' '.$langs->trans($this->statuts_short[$status]);
2108 } elseif ($status == 1) {
2109 return img_picto($langs->trans($this->statuts_short[$status]),
'statut1').
' '.$langs->trans($this->statuts_short[$status]);
2110 } elseif ($status == 2) {
2111 return img_picto($langs->trans($this->statuts_short[$status]),
'statut3').
' '.$langs->trans($this->statuts_short[$status]);
2112 } elseif ($status == 3) {
2113 return img_picto($langs->trans($this->statuts_short[$status]),
'statut6').
' '.$langs->trans($this->statuts_short[$status]);
2114 } elseif ($status == 4) {
2115 return img_picto($langs->trans($this->statuts_short[$status]),
'statut6').
' '.$langs->trans($this->statuts_short[$status]);
2116 } elseif ($status == 5) {
2117 return img_picto($langs->trans($this->statuts_short[$status]),
'statut5').
' '.$langs->trans($this->statuts_short[$status]);
2119 } elseif ($mode == 3) {
2121 return img_picto($langs->trans($this->statuts_short[$status]),
'statut0');
2122 } elseif ($status == 1) {
2123 return img_picto($langs->trans($this->statuts_short[$status]),
'statut1');
2124 } elseif ($status == 2) {
2125 return img_picto($langs->trans($this->statuts_short[$status]),
'statut3');
2126 } elseif ($status == 3) {
2127 return img_picto($langs->trans($this->statuts_short[$status]),
'statut6');
2128 } elseif ($status == 4) {
2129 return img_picto($langs->trans($this->statuts_short[$status]),
'statut6');
2130 } elseif ($status == 5) {
2131 return img_picto($langs->trans($this->statuts_short[$status]),
'statut5');
2133 } elseif ($mode == 4) {
2135 return img_picto($langs->trans($this->statuts_short[$status]),
'statut0').
' '.$langs->trans($this->statuts[$status]);
2136 } elseif ($status == 1) {
2137 return img_picto($langs->trans($this->statuts_short[$status]),
'statut1').
' '.$langs->trans($this->statuts[$status]);
2138 } elseif ($status == 2) {
2139 return img_picto($langs->trans($this->statuts_short[$status]),
'statut3').
' '.$langs->trans($this->statuts[$status]);
2140 } elseif ($status == 3) {
2141 return img_picto($langs->trans($this->statuts_short[$status]),
'statut6').
' '.$langs->trans($this->statuts[$status]);
2142 } elseif ($status == 4) {
2143 return img_picto($langs->trans($this->statuts_short[$status]),
'statut6').
' '.$langs->trans($this->statuts[$status]);
2144 } elseif ($status == 5) {
2145 return img_picto($langs->trans($this->statuts_short[$status]),
'statut5').
' '.$langs->trans($this->statuts[$status]);
2147 } elseif ($mode == 5) {
2157 } elseif ($mode == 6) {
2180 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
2184 $outputlangs->load(
"projects");
2187 $modele =
'nodefault';
2189 if (!empty($this->model_pdf)) {
2190 $modele = $this->model_pdf;
2191 } elseif (!empty($this->modelpdf)) {
2192 $modele = $this->modelpdf;
2193 } elseif (!empty($conf->global->PROJECT_TASK_ADDON_PDF)) {
2194 $modele = $conf->global->PROJECT_TASK_ADDON_PDF;
2198 $modelpath =
"core/modules/project/task/doc/";
2200 return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref);
2214 global $conf, $langs;
2220 $projectstatic =
new Project($this->db);
2221 $projectsListId = $projectstatic->getProjectsAuthorizedForUser($user, 0, 1, $socid);
2224 $sql =
"SELECT p.rowid as projectid, p.fk_statut as projectstatus,";
2225 $sql .=
" t.rowid as taskid, t.progress as progress, t.fk_statut as status,";
2226 $sql .=
" t.dateo as date_start, t.datee as datee";
2227 $sql .=
" FROM ".MAIN_DB_PREFIX.
"projet as p";
2230 $sql .=
", ".MAIN_DB_PREFIX.
"projet_task as t";
2231 $sql .=
" WHERE p.entity IN (".getEntity(
'project', 0).
')';
2232 $sql .=
" AND p.fk_statut = 1";
2233 $sql .=
" AND t.fk_projet = p.rowid";
2234 $sql .=
" AND (t.progress IS NULL OR t.progress < 100)";
2235 if (empty($user->rights->projet->all->lire)) {
2236 $sql .=
" AND p.rowid IN (".$this->db->sanitize($projectsListId).
")";
2244 $resql = $this->db->query(
$sql);
2246 $task_static =
new Task($this->db);
2249 $response->warning_delay = $conf->project->task->warning_delay / 60 / 60 / 24;
2250 $response->label = $langs->trans(
"OpenedTasks");
2251 if ($user->hasRight(
"projet",
"all",
"lire")) {
2252 $response->url = DOL_URL_ROOT.
'/projet/tasks/list.php?mainmenu=project';
2254 $response->url = DOL_URL_ROOT.
'/projet/tasks/list.php?mode=mine&mainmenu=project';
2259 while ($obj = $this->db->fetch_object($resql)) {
2260 $response->nbtodo++;
2262 $task_static->projectstatus = $obj->projectstatus;
2263 $task_static->progress = $obj->progress;
2264 $task_static->fk_statut = $obj->status;
2265 $task_static->date_end = $this->db->jdate($obj->datee);
2267 if ($task_static->hasDelay()) {
2268 $response->nbtodolate++;
2274 $this->error = $this->db->error();
2291 $mine = 0; $socid = $user->socid;
2293 $projectstatic =
new Project($this->db);
2294 $projectsListId = $projectstatic->getProjectsAuthorizedForUser($user, $mine, 1, $socid);
2297 $sql =
"SELECT count(p.rowid) as nb";
2298 $sql .=
" FROM ".MAIN_DB_PREFIX.
"projet as p";
2299 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe as s on p.fk_soc = s.rowid";
2300 if (empty($user->rights->societe->client->voir) && !$socid) {
2301 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe_commerciaux as sc ON sc.fk_soc = s.rowid";
2303 $sql .=
", ".MAIN_DB_PREFIX.
"projet_task as t";
2304 $sql .=
" WHERE p.entity IN (".getEntity(
'project', 0).
')';
2305 $sql .=
" AND t.fk_projet = p.rowid";
2306 if ($mine || empty($user->rights->projet->all->lire)) {
2307 $sql .=
" AND p.rowid IN (".$this->db->sanitize($projectsListId).
")";
2312 $sql .=
" AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".((int) $socid).
")";
2314 if (empty($user->rights->societe->client->voir) && !$socid) {
2315 $sql .=
" AND ((s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $user->id).
") OR (s.rowid IS NULL))";
2318 $resql = $this->db->query(
$sql);
2321 while ($obj = $this->db->fetch_object($resql)) {
2322 $this->nb[
"tasks"] = $obj->nb;
2324 $this->db->free($resql);
2328 $this->error = $this->db->error();
2342 if (!($this->progress >= 0 && $this->progress < 100)) {
2348 $datetouse = ($this->date_end > 0) ? $this->date_end : ((isset($this->datee) && $this->datee > 0) ? $this->datee : 0);
2350 return ($datetouse > 0 && ($datetouse < ($now - $conf->project->task->warning_delay)));
2362 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
2364 $return =
'<div class="box-flex-item box-flex-grow-zero">';
2365 $return .=
'<div class="info-box info-box-sm info-box-kanban">';
2366 $return .=
'<span class="info-box-icon bg-infobox-action">';
2369 $return .=
'</span>';
2370 $return .=
'<div class="info-box-content">';
2371 $return .=
'<span class="info-box-ref">'.(method_exists($this,
'getNomUrl') ? $this->getNomUrl(1) : $this->ref).
'</span>';
2372 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
2373 if (!empty($arraydata[
'projectlink'])) {
2376 $return .=
'<br><span class="info-box-status ">'.$arraydata[
'projectlink'].
'</span>';
2378 if (property_exists($this,
'budget_amount')) {
2381 if (property_exists($this,
'duration_effective')) {
2382 $return .=
'<br><br><div class="info-box-label progressinkanban">'.getTaskProgressView($this,
false,
true).
'</div>';
2384 $return .=
'</div>';
2385 $return .=
'</div>';
2386 $return .=
'</div>';