From 3a4b11b824e16b05474f3b32249d97c7065b125b Mon Sep 17 00:00:00 2001 From: Jessica-creat <135526403+Jessica-creat@users.noreply.github.com> Date: Fri, 7 Nov 2025 00:09:14 +0100 Subject: [PATCH] NEW add timespent API endpoints for projects and tasks add also cascading assignment of contacts to tasks (#35897) * demande d'ajout timespent * feat(api): add timespent endpoints for projects and tasks * add contact to product * correction prettier * revert * feat(api): update timespent endpoints in api_projects and api_tasks * Update api_projects.class.php * Remove blank line before docblock in api_tasks.class.php Removed unnecessary blank line before the docblock for the get contacts method. * Update api_tasks.class.php * Clarify return type in api_projects.class.php Updated return type annotation for contact information array. * Refine return type in get timespent method Updated return type annotation for timespent method. * Return raw contacts instead of cleaned data * Update api_projects.class.php * Return contacts array instead of cleaned data Modified the return value to return the contacts array directly instead of cleaned data. --------- Co-authored-by: Laurent Destailleur --- htdocs/projet/class/api_projects.class.php | 242 ++++++++++++++++++--- htdocs/projet/class/api_tasks.class.php | 176 +++++++++++++-- 2 files changed, 365 insertions(+), 53 deletions(-) diff --git a/htdocs/projet/class/api_projects.class.php b/htdocs/projet/class/api_projects.class.php index 554d35ff07a..e7294a43a4d 100644 --- a/htdocs/projet/class/api_projects.class.php +++ b/htdocs/projet/class/api_projects.class.php @@ -4,6 +4,7 @@ * Copyright (C) 2024-2025 MDW * Copyright (C) 2025 Charlene Benke * Copyright (C) 2025 Frédéric France + * Copyright (C) 2025 Jessica Kowal * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,8 +22,8 @@ use Luracast\Restler\RestException; -require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; -require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php'; +require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php'; +require_once DOL_DOCUMENT_ROOT . '/projet/class/task.class.php'; /** * API class for projects @@ -84,7 +85,7 @@ class Projects extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('project', $this->project->id)) { - throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); } $this->project->fetchObjectLinked(); @@ -115,7 +116,7 @@ class Projects extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('project', $this->project->id)) { - throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); } $this->project->fetchObjectLinked(); @@ -146,7 +147,7 @@ class Projects extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('project', $this->project->id)) { - throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); } $this->project->fetchObjectLinked(); @@ -177,7 +178,7 @@ class Projects extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('project', $this->project->id)) { - throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); } $this->project->fetchObjectLinked(); @@ -220,34 +221,34 @@ class Projects extends DolibarrApi } $sql = "SELECT t.rowid"; - $sql .= " FROM ".MAIN_DB_PREFIX."projet as t"; - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe AS s ON (s.rowid = t.fk_soc)"; - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."projet_extrafields AS ef ON ef.fk_object = t.rowid"; // So we will be able to filter on extrafields + $sql .= " FROM " . MAIN_DB_PREFIX . "projet as t"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe AS s ON (s.rowid = t.fk_soc)"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "projet_extrafields AS ef ON ef.fk_object = t.rowid"; // So we will be able to filter on extrafields if ($category > 0) { - $sql .= ", ".MAIN_DB_PREFIX."categorie_project as c"; + $sql .= ", " . MAIN_DB_PREFIX . "categorie_project as c"; } - $sql .= ' WHERE t.entity IN ('.getEntity('project').')'; + $sql .= ' WHERE t.entity IN (' . getEntity('project') . ')'; if ($socids) { - $sql .= " AND t.fk_soc IN (".$this->db->sanitize($socids).")"; + $sql .= " AND t.fk_soc IN (" . $this->db->sanitize($socids) . ")"; } // Search on sale representative if ($search_sale && $search_sale != '-1') { if ($search_sale == -2) { - $sql .= " AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."societe_commerciaux as sc WHERE sc.fk_soc = t.fk_soc)"; + $sql .= " AND NOT EXISTS (SELECT sc.fk_soc FROM " . MAIN_DB_PREFIX . "societe_commerciaux as sc WHERE sc.fk_soc = t.fk_soc)"; } elseif ($search_sale > 0) { - $sql .= " AND EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."societe_commerciaux as sc WHERE sc.fk_soc = t.fk_soc AND sc.fk_user = ".((int) $search_sale).")"; + $sql .= " AND EXISTS (SELECT sc.fk_soc FROM " . MAIN_DB_PREFIX . "societe_commerciaux as sc WHERE sc.fk_soc = t.fk_soc AND sc.fk_user = " . ((int) $search_sale) . ")"; } } // Select projects of given category if ($category > 0) { - $sql .= " AND c.fk_categorie = ".((int) $category)." AND c.fk_project = t.rowid "; + $sql .= " AND c.fk_categorie = " . ((int) $category) . " AND c.fk_project = t.rowid "; } // Add sql filters if ($sqlfilters) { $errormessage = ''; $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage); if ($errormessage) { - throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); + throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage); } } @@ -280,7 +281,7 @@ class Projects extends DolibarrApi $i++; } } else { - throw new RestException(503, 'Error when retrieve project list : '.$this->db->lasterror()); + throw new RestException(503, 'Error when retrieve project list : ' . $this->db->lasterror()); } //if $pagination_data is true the response will contain element data with all values and element pagination with pagination data(total,page,limit) @@ -348,7 +349,7 @@ class Projects extends DolibarrApi $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); foreach ($dirmodels as $reldir) { - $file = dol_buildpath($reldir."core/modules/project/".$modele.'.php', 0); + $file = dol_buildpath($reldir . "core/modules/project/" . $modele . '.php', 0); if (file_exists($file)) { $filefound = 1; $classname = $modele; @@ -416,12 +417,12 @@ class Projects extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('ficheinter', $this->project->id)) { - throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); } $result = $this->project->add_contact($fk_socpeople, $type_contact, $source, $notrigger); if ($result < 0) { - throw new RestException(500, 'Error : '.$this->project->error); + throw new RestException(500, 'Error : ' . $this->project->error); } return $this->_cleanObjectDatas($this->project); @@ -454,7 +455,7 @@ class Projects extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('project', $this->project->id)) { - throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); } foreach (array('internal', 'external') as $source) { $contacts = $this->project->liste_contact(-1, $source); @@ -494,7 +495,7 @@ class Projects extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('project', $this->project->id)) { - throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); } $this->project->getLinesArray(DolibarrApiAccess::$user); $result = array(); @@ -534,10 +535,10 @@ class Projects extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('project', $this->project->id)) { - throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); } - require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php'; + require_once DOL_DOCUMENT_ROOT . '/projet/class/task.class.php'; $taskstatic = new Task($this->db); $userp = DolibarrApiAccess::$user; if ($userid > 0) { @@ -712,7 +713,7 @@ class Projects extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('project', $this->project->id)) { - throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); } foreach ($request_data as $field => $value) { if ($field == 'id') { @@ -760,11 +761,11 @@ class Projects extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('project', $this->project->id)) { - throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); } if (!$this->project->delete(DolibarrApiAccess::$user)) { - throw new RestException(500, 'Error when delete project : '.$this->project->error); + throw new RestException(500, 'Error when delete project : ' . $this->project->error); } return array( @@ -808,7 +809,7 @@ class Projects extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('project', $this->project->id)) { - throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); } $result = $this->project->setValid(DolibarrApiAccess::$user, $notrigger); @@ -816,7 +817,7 @@ class Projects extends DolibarrApi throw new RestException(304, 'Error nothing done. May be object is already validated'); } if ($result < 0) { - throw new RestException(500, 'Error when validating Project: '.$this->project->error); + throw new RestException(500, 'Error when validating Project: ' . $this->project->error); } return array( @@ -1016,6 +1017,189 @@ class Projects extends DolibarrApi } + + + /** + * Get contacts of given project + * + * Return an array with contact information + * + * @param int $id ID of project + * @param string $type Type of the contact + * @return array Array with cleaned properties + * + * @url GET {id}/contacts + * + * @throws RestException + */ + public function getContacts($id, $type = '') + { + if (!DolibarrApiAccess::$user->hasRight('projet', 'lire')) { + throw new RestException(403); + } + + $result = $this->project->fetch($id); + if (!$result) { + throw new RestException(404, 'Project not found'); + } + + if (!DolibarrApi::_checkAccessToResource('project', $this->project->id)) { + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); + } + + $contacts = $this->project->liste_contact(-1, 'external', 0, $type); + $socpeoples = $this->project->liste_contact(-1, 'internal', 0, $type); + + $contacts = array_merge($contacts, $socpeoples); + + return $contacts; + } + + /** + * Adds a contact to a project + * + * @param int $id Project ID + * @param int $fk_socpeople Id of thirdparty contact (if source = 'external') or id of user (if source = 'internal') to link + * @param string $type_contact Type of contact (code). Must a code found into table llx_c_type_contact. For example: BILLING + * @param string $source external=Contact extern (llx_socpeople), internal=Contact intern (llx_user) + * @param int $notrigger Disable all triggers + * @param int[] $affect_to_tasks Array of task IDs to also add the contact to (empty array = all tasks, null = no tasks) + * + * @url POST {id}/contacts + * + * @return object + * + * @throws RestException 304 + * @throws RestException 401 + * @throws RestException 404 + * @throws RestException 500 System error + */ + public function addToContact($id, $fk_socpeople, $type_contact, $source, $notrigger = 0, $affect_to_tasks = null) + { + if (!DolibarrApiAccess::$user->hasRight('projet', 'creer')) { + throw new RestException(403); + } + + $result = $this->project->fetch($id); + if (!$result) { + throw new RestException(404, 'Project not found'); + } + + if (!DolibarrApi::_checkAccessToResource('project', $this->project->id)) { + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); + } + + // Ajouter le contact au projet + $result = $this->project->add_contact($fk_socpeople, $type_contact, $source, $notrigger); + if ($result <= 0) { + throw new RestException(500, 'Error : ' . $this->project->error . 'result :' . $result); + } + + // Si demandé, ajouter le contact aux tâches + if ($affect_to_tasks !== null) { + $this->project->getLinesArray(DolibarrApiAccess::$user); + + foreach ($this->project->lines as $task) { + // Si $affect_to_tasks est vide, on affecte à toutes les tâches + // Sinon, on vérifie si la tâche est dans la liste + if (empty($affect_to_tasks) || in_array($task->id, $affect_to_tasks)) { + $task->add_contact($fk_socpeople, $type_contact, $source, $notrigger); + } + } + } + + $result = $this->project->fetch($id); + if (!$result) { + throw new RestException(404, 'Project not found'); + } + + return $this->_cleanObjectDatas($this->project); + } + /** + * Delete a contact type of given project + * + * @param int $id Id of project to update + * @param int $contactid Row key of the contact in the array contact_ids. + * @param string $type Type of the contact (BILLING, SHIPPING, CUSTOMER). + * @return Object Object with cleaned properties + * + * @url DELETE {id}/contact/{contactid}/{type} + * + * @throws RestException 401 + * @throws RestException 404 + * @throws RestException 500 System error + */ + public function deleteToContact($id, $contactid, $type) + { + if (!DolibarrApiAccess::$user->hasRight('projet', 'creer')) { + throw new RestException(403); + } + + $result = $this->project->fetch($id); + if (!$result) { + throw new RestException(404, 'Project not found'); + } + + if (!DolibarrApi::_checkAccessToResource('project', $this->project->id)) { + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); + } + + foreach (array('internal', 'external') as $source) { + $contacts = $this->project->liste_contact(-1, $source); + + foreach ($contacts as $contact) { + if ($contact['id'] == $contactid && $contact['code'] == $type) { + $result = $this->project->delete_contact($contact['rowid']); + if (!$result) { + throw new RestException(500, 'Error when deleted the contact'); + } + break 2; + } + } + } + + return $this->_cleanObjectDatas($this->project); + } + + /** + * Get timespent of a project (from all its tasks) + * + * @param int $id ID of project + * @return array Array of timespent objects + * + * @url GET {id}/timespent + * + * @throws RestException + */ + public function getTimespent($id) + { + if (!DolibarrApiAccess::$user->hasRight('projet', 'lire')) { + throw new RestException(403); + } + + $result = $this->project->fetch($id); + if (!$result) { + throw new RestException(404, 'Project not found'); + } + + if (!DolibarrApi::_checkAccessToResource('project', $this->project->id)) { + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); + } + + + $this->project->getLinesArray(DolibarrApiAccess::$user); + $allTimespent = array(); + foreach ($this->project->lines as $task) { + $allTimespent[] = $task->getSummaryOfTimeSpent(); + //var_dump($taskTimespent); + //foreach ($taskTimespent as $time) { + // $this->_cleanObjectDatas($time); + + //} + } + + return $allTimespent; + } // TODO // getSummaryOfTimeSpent } diff --git a/htdocs/projet/class/api_tasks.class.php b/htdocs/projet/class/api_tasks.class.php index 6b0f8fd6ccb..03d8f1f4028 100644 --- a/htdocs/projet/class/api_tasks.class.php +++ b/htdocs/projet/class/api_tasks.class.php @@ -3,7 +3,7 @@ * Copyright (C) 2016 Laurent Destailleur * Copyright (C) 2024-2025 Frédéric France * Copyright (C) 2025 MDW - * Copyright (C) 2025 Charlene Benke + * Copyright (C) 2025 Jessica Kowal * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,8 +21,8 @@ use Luracast\Restler\RestException; -require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/projet/class/task.class.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php'; /** @@ -80,7 +80,7 @@ class Tasks extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('task', $this->task->id)) { - throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); } if ($includetimespent == 1) { @@ -130,19 +130,19 @@ class Tasks extends DolibarrApi } $sql = "SELECT t.rowid"; - $sql .= " FROM ".MAIN_DB_PREFIX."projet_task AS t"; - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields - $sql .= " INNER JOIN ".MAIN_DB_PREFIX."projet AS p ON p.rowid = t.fk_projet"; - $sql .= ' WHERE t.entity IN ('.getEntity('project').')'; + $sql .= " FROM " . MAIN_DB_PREFIX . "projet_task AS t"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "projet_task_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields + $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "projet AS p ON p.rowid = t.fk_projet"; + $sql .= ' WHERE t.entity IN (' . getEntity('project') . ')'; if ($socids) { - $sql .= " AND t.fk_soc IN (".$this->db->sanitize((string) $socids).")"; + $sql .= " AND t.fk_soc IN (" . $this->db->sanitize((string) $socids) . ")"; } // Search on sale representative if ($search_sale && $search_sale != '-1') { if ($search_sale == -2) { - $sql .= " AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc)"; + $sql .= " AND NOT EXISTS (SELECT sc.fk_soc FROM " . MAIN_DB_PREFIX . "societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc)"; } elseif ($search_sale > 0) { - $sql .= " AND EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc AND sc.fk_user = ".((int) $search_sale).")"; + $sql .= " AND EXISTS (SELECT sc.fk_soc FROM " . MAIN_DB_PREFIX . "societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc AND sc.fk_user = " . ((int) $search_sale) . ")"; } } // Add sql filters @@ -150,7 +150,7 @@ class Tasks extends DolibarrApi $errormessage = ''; $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage); if ($errormessage) { - throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); + throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage); } } @@ -180,7 +180,7 @@ class Tasks extends DolibarrApi $i++; } } else { - throw new RestException(503, 'Error when retrieve task list : '.$this->db->lasterror()); + throw new RestException(503, 'Error when retrieve task list : ' . $this->db->lasterror()); } return $obj_ret; @@ -289,7 +289,7 @@ class Tasks extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('tasks', $this->task->id)) { - throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); } $this->task->fetchTimeSpentOnTask(); $result = array(); @@ -324,7 +324,7 @@ class Tasks extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('tasks', $this->task->id)) { - throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); } $usert = DolibarrApiAccess::$user; @@ -497,7 +497,7 @@ class Tasks extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('task', $this->task->id)) { - throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); } foreach ($request_data as $field => $value) { if ($field == 'id') { @@ -546,11 +546,11 @@ class Tasks extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('task', $this->task->id)) { - throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); } if ($this->task->delete(DolibarrApiAccess::$user) <= 0) { - throw new RestException(500, 'Error when delete task : '.$this->task->error); + throw new RestException(500, 'Error when delete task : ' . $this->task->error); } return array( @@ -593,7 +593,7 @@ class Tasks extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('project', $this->task->fk_project)) { - throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); } $uid = $user_id; @@ -616,7 +616,7 @@ class Tasks extends DolibarrApi throw new RestException(304, 'Error nothing done. May be object is already validated'); } if ($result < 0) { - throw new RestException(500, 'Error when adding time: '.$this->task->error); + throw new RestException(500, 'Error when adding time: ' . $this->task->error); } return array( @@ -654,7 +654,7 @@ class Tasks extends DolibarrApi $this->timespentRecordChecks($id, $timespent_id); if (!DolibarrApi::_checkAccessToResource('task', $this->task->id)) { - throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); } $newdate = dol_stringtotime($date, 1); @@ -670,7 +670,7 @@ class Tasks extends DolibarrApi throw new RestException(304, 'Error nothing done.'); } if ($result < 0) { - throw new RestException(500, 'Error when updating time spent: '.$this->task->error); + throw new RestException(500, 'Error when updating time spent: ' . $this->task->error); } return array( @@ -701,11 +701,11 @@ class Tasks extends DolibarrApi $this->timespentRecordChecks($id, $timespent_id); if (!DolibarrApi::_checkAccessToResource('task', $this->task->id)) { - throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); } if ($this->task->delTimeSpent(DolibarrApiAccess::$user, 0) < 0) { - throw new RestException(500, 'Error when deleting time spent: '.$this->task->error); + throw new RestException(500, 'Error when deleting time spent: ' . $this->task->error); } return array( @@ -813,6 +813,134 @@ class Tasks extends DolibarrApi return $object; } + /** + * Get contacts of given task + * + * Return an array with contact information + * + * @param int $id ID of task + * @param string $type Type of the contact + * @return array Array with cleaned properties + * + * @url GET {id}/contacts + * + * @throws RestException + */ + public function getContacts($id, $type = '') + { + if (!DolibarrApiAccess::$user->hasRight('projet', 'lire')) { + throw new RestException(403); + } + + $result = $this->task->fetch($id); + if (!$result) { + throw new RestException(404, 'Task not found'); + } + + if (!DolibarrApi::_checkAccessToResource('task', $this->task->id)) { + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); + } + + $contacts = $this->task->liste_contact(-1, 'external', 0, $type); + $socpeoples = $this->task->liste_contact(-1, 'internal', 0, $type); + + $contacts = array_merge($contacts, $socpeoples); + + return $contacts; // Return array + } + + /** + * Adds a contact to a task + * + * @param int $id Task ID + * @param int $fk_socpeople Id of thirdparty contact (if source = 'external') or id of user (if source = 'internal') to link + * @param string $type_contact Type of contact (code). Must a code found into table llx_c_type_contact. For example: BILLING + * @param string $source external=Contact extern (llx_socpeople), internal=Contact intern (llx_user) + * @param int $notrigger Disable all triggers + * + * @url POST {id}/contacts + * + * @return object + * + * @throws RestException 304 + * @throws RestException 401 + * @throws RestException 404 + * @throws RestException 500 System error + */ + public function addContact($id, $fk_socpeople, $type_contact, $source, $notrigger = 0) + { + if (!DolibarrApiAccess::$user->hasRight('projet', 'creer')) { + throw new RestException(403); + } + + $result = $this->task->fetch($id); + if (!$result) { + throw new RestException(404, 'Task not found'); + } + + if (!DolibarrApi::_checkAccessToResource('task', $this->task->id)) { + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); + } + + $result = $this->task->add_contact($fk_socpeople, $type_contact, $source, $notrigger); + if ($result <= 0) { + throw new RestException(500, 'Error : ' . $this->task->error); + } + + $result = $this->task->fetch($id); + if (!$result) { + throw new RestException(404, 'Task not found'); + } + + return $this->_cleanObjectDatas($this->task); + } + + + /** + * Delete a contact type of given task + * + * @param int $id Id of task to update + * @param int $contactid Row key of the contact in the array contact_ids. + * @param string $type Type of the contact (BILLING, SHIPPING, CUSTOMER). + * @return Object Object with cleaned properties + * + * @url DELETE {id}/contacts/{contactid}/{type} + * + * @throws RestException 401 + * @throws RestException 404 + * @throws RestException 500 System error + */ + public function deleteContact($id, $contactid, $type) + { + if (!DolibarrApiAccess::$user->hasRight('projet', 'creer')) { + throw new RestException(403); + } + + $result = $this->task->fetch($id); + if (!$result) { + throw new RestException(404, 'Task not found'); + } + + if (!DolibarrApi::_checkAccessToResource('task', $this->task->id)) { + throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); + } + + foreach (array('internal', 'external') as $source) { + $contacts = $this->task->liste_contact(-1, $source); + + foreach ($contacts as $contact) { + if ($contact['id'] == $contactid && $contact['code'] == $type) { + $result = $this->task->delete_contact($contact['rowid']); + if (!$result) { + throw new RestException(500, 'Error when deleted the contact'); + } + break 2; + } + } + } + + return $this->_cleanObjectDatas($this->task); + } // \todo // getSummaryOfTimeSpent