21use Luracast\Restler\RestException;
23require_once DOL_DOCUMENT_ROOT.
'/ticket/class/ticket.class.php';
24require_once DOL_DOCUMENT_ROOT.
'/core/lib/ticket.lib.php';
25require_once DOL_DOCUMENT_ROOT.
'/core/lib/company.lib.php';
39 public static $FIELDS = array(
47 public static $FIELDS_MESSAGES = array(
64 $this->ticket =
new Ticket($this->db);
80 public function get(
$id, $contact_list = 1)
102 return $this->
getCommon(0, $track_id,
'', $contact_list);
122 return $this->
getCommon(0,
'', $ref, $contact_list);
135 private function getCommon(
$id = 0, $track_id =
'', $ref =
'', $contact_list = 1)
139 if (!DolibarrApiAccess::$user->hasRight(
'ticket',
'read')) {
140 throw new RestException(403);
144 if ((
$id < 0) && !$track_id && !$ref) {
145 throw new RestException(400,
'Wrong parameters');
147 if (empty(
$id) && empty($ref) && empty($track_id)) {
148 $result = $this->ticket->initAsSpecimen();
150 $result = $this->ticket->fetch(
$id, $ref, $track_id);
153 throw new RestException(404,
'Ticket not found');
159 $this->ticket->loadCacheMsgsTicket();
161 if (is_array($this->ticket->cache_msgs_ticket) && count($this->ticket->cache_msgs_ticket) > 0) {
162 $num = count($this->ticket->cache_msgs_ticket);
165 $iduseraction = $this->ticket->cache_msgs_ticket[$i][
'fk_user_action'];
166 if ($iduseraction > 0) {
167 if (empty(
$conf->cache[
'user'][$iduseraction])) {
168 $user_action =
new User($this->db);
169 $user_action->fetch($iduseraction);
171 $conf->cache[
'user'][$iduseraction] = $user_action;
173 $user_action =
$conf->cache[
'user'][$iduseraction];
181 'id' => $this->ticket->cache_msgs_ticket[$i][
'id'],
182 'fk_user_action' => $this->ticket->cache_msgs_ticket[$i][
'fk_user_action'],
183 'fk_user_action_socid' => $user_action ===
null ?
'' : $user_action->socid,
184 'fk_user_action_string' => $user_action ===
null ?
'' :
dolGetFirstLastname($user_action->firstname, $user_action->lastname),
185 'datec' => $this->ticket->cache_msgs_ticket[$i][
'datec'],
186 'datep' => $this->ticket->cache_msgs_ticket[$i][
'datep'],
187 'subject' => $this->ticket->cache_msgs_ticket[$i][
'subject'],
188 'message' => $this->ticket->cache_msgs_ticket[$i][
'message'],
189 'private' => $this->ticket->cache_msgs_ticket[$i][
'private']
193 $this->ticket->messages = $messages;
197 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
200 if ($contact_list > -1) {
202 $tmparray = $this->ticket->liste_contact(-1,
'external', $contact_list);
203 if (is_array($tmparray)) {
204 $this->ticket->contacts_ids = $tmparray;
206 $tmparray = $this->ticket->liste_contact(-1,
'internal', $contact_list);
207 if (is_array($tmparray)) {
208 $this->ticket->contacts_ids_internal = $tmparray;
234 public function index($socid = 0, $sortfield =
"t.rowid", $sortorder =
"ASC", $limit = 100, $page = 0, $sqlfilters =
'', $properties =
'', $loadcontacts = 0, $pagination_data =
false)
236 if (!DolibarrApiAccess::$user->hasRight(
'ticket',
'read')) {
237 throw new RestException(403);
242 $socid = DolibarrApiAccess::$user->socid ?: $socid;
247 if (!DolibarrApiAccess::$user->hasRight(
'societe',
'client',
'voir') && !$socid) {
248 $search_sale = DolibarrApiAccess::$user->id;
251 $sql =
"SELECT t.rowid";
252 $sql .=
" FROM ".MAIN_DB_PREFIX.
"ticket AS t";
253 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe AS s ON (s.rowid = t.fk_soc)";
254 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"ticket_extrafields AS ef ON (ef.fk_object = t.rowid)";
255 $sql .=
' WHERE t.entity IN ('.getEntity(
'ticket', 1).
')';
257 $sql .=
" AND t.fk_soc = ".((int) $socid);
260 if ($search_sale && $search_sale !=
'-1') {
261 if ($search_sale == -2) {
262 $sql .=
" AND ".getSalesRepresentativeSqlFilter(
't.fk_soc', 0, 1);
263 } elseif ($search_sale > 0) {
264 $sql .=
" AND ".getSalesRepresentativeSqlFilter(
't.fk_soc', (
int) $search_sale);
272 throw new RestException(400,
'Error when validating parameter sqlfilters -> '.$errormessage);
277 $sqlTotals = str_replace(
'SELECT t.rowid',
'SELECT count(t.rowid) as total', $sql);
279 $sql .= $this->db->order($sortfield, $sortorder);
285 $offset = $limit * $page;
287 $sql .= $this->db->plimit($limit, $offset);
290 $result = $this->db->query($sql);
293 $num = $this->db->num_rows($result);
294 $min = min($num, ($limit <= 0 ? $num : $limit));
296 $obj = $this->db->fetch_object($result);
297 $ticket_static =
new Ticket($this->db);
298 if ($ticket_static->fetch($obj->rowid)) {
299 if ($ticket_static->fk_user_assign > 0) {
300 $userStatic =
new User($this->db);
301 $userStatic->fetch($ticket_static->fk_user_assign);
307 $tmparray = $ticket_static->liste_contact(-1,
'external', 1);
308 if (is_array($tmparray)) {
309 $ticket_static->contacts_ids = $tmparray;
311 $tmparray = $ticket_static->liste_contact(-1,
'internal', 1);
312 if (is_array($tmparray)) {
313 $ticket_static->contacts_ids_internal = $tmparray;
322 throw new RestException(503,
'Error when retrieve ticket list');
326 if ($pagination_data) {
327 $totalsResult = $this->db->query($sqlTotals);
328 $total = $this->db->fetch_object($totalsResult)->total;
333 $obj_ret[
'data'] = $tmp;
334 $obj_ret[
'pagination'] = [
335 'total' => (int) $total,
337 'page_count' => ceil((
int) $total / $limit),
353 public function post($request_data =
null)
355 $ticketstatic =
new Ticket($this->db);
356 if (!DolibarrApiAccess::$user->hasRight(
'ticket',
'write')) {
357 throw new RestException(403);
364 $socid = (int) $request_data[
'socid'];
366 $thirdpartytmp =
new Societe($this->db);
367 $thirdparty_result = $thirdpartytmp->fetch($socid);
368 if ($thirdparty_result < 1) {
369 throw new RestException(404,
'Thirdparty with id='.$socid.
' not found or not allowed');
372 throw new RestException(404,
'Thirdparty with id='.$thirdpartytmp->id.
' not found or not allowed');
376 foreach ($request_data as $field => $value) {
377 if ($field ===
'caller') {
379 $this->ticket->context[
'caller'] =
sanitizeVal($request_data[
'caller'],
'aZ09');
383 $this->ticket->$field = $this->
_checkValForAPI($field, $value, $this->ticket);
385 if (empty($this->ticket->ref)) {
386 $this->ticket->ref = $ticketstatic->getDefaultRef();
388 if (empty($this->ticket->track_id)) {
392 if ($this->ticket->create(DolibarrApiAccess::$user) < 0) {
393 throw new RestException(500,
"Error creating ticket", array_merge(array($this->ticket->error), $this->ticket->errors));
396 return $this->ticket->id;
411 if (!DolibarrApiAccess::$user->hasRight(
'ticket',
'write')) {
412 throw new RestException(403);
418 $return_action_id =
false;
419 if (isset($request_data[
'return_action_id'])) {
420 $return_action_id = !empty($request_data[
'return_action_id']);
421 unset($request_data[
'return_action_id']);
424 $attachments = array();
425 if (isset($request_data[
'attachments']) && is_array($request_data[
'attachments'])) {
426 $attachments = $request_data[
'attachments'];
427 unset($request_data[
'attachments']);
430 foreach ($request_data as $field => $value) {
431 if ($field ===
'caller') {
433 $this->ticket->context[
'caller'] =
sanitizeVal($request_data[
'caller'],
'aZ09');
437 $this->ticket->$field = $this->
_checkValForAPI($field, $value, $this->ticket);
439 $ticketMessageText = $this->ticket->message;
441 if (!empty($this->ticket->id)) {
442 $result = $this->ticket->fetch($this->ticket->id);
443 } elseif (!empty($this->ticket->ref)) {
444 $result = $this->ticket->fetch(0, $this->ticket->ref);
446 $result = $this->ticket->fetch(0,
'', $this->ticket->track_id);
449 throw new RestException(404,
'Ticket not found');
453 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
456 $this->ticket->message = $ticketMessageText;
458 $filename_list = array();
459 $mimetype_list = array();
460 $mimefilename_list = array();
461 if (!empty($attachments)) {
463 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
465 $destdir =
$conf->ticket->dir_output.
'/'.$this->ticket->ref;
467 throw new RestException(500,
'Error while trying to create directory '.$destdir);
470 foreach ($attachments as $attachment) {
471 if (!is_array($attachment) || empty($attachment[
'filename'])) {
476 if (empty($filename)) {
480 $filecontent = isset($attachment[
'filecontent']) ? $attachment[
'filecontent'] :
'';
481 $fileencoding = isset($attachment[
'fileencoding']) ? $attachment[
'fileencoding'] :
'';
482 $content = ($fileencoding ===
'base64') ? base64_decode($filecontent) : $filecontent;
483 if ($content ===
false) {
484 throw new RestException(400,
'Failed to decode attachment '.$filename);
487 $destfile = $destdir.
'/'.$filename;
488 if (is_file($destfile)) {
489 $pathinfo = pathinfo($filename);
490 $suffix =
' - '.dol_print_date(
dol_now(),
'dayhourlog');
491 $extension = !empty($pathinfo[
'extension']) ?
'.'.$pathinfo[
'extension'] :
'';
492 $basename = !empty($pathinfo[
'filename']) ? $pathinfo[
'filename'] : preg_replace(
'/\.[^.]+$/',
'', $filename);
493 $destfile = $destdir.
'/'.$basename.$suffix.$extension;
496 $destfiletmp = DOL_DATA_ROOT.
'/admin/temp/'.basename($destfile);
501 $fhandle = @fopen($destfiletmp,
'w');
503 throw new RestException(500,
"Failed to open file '".$destfiletmp.
"' for write");
505 $nbofbyteswrote = fwrite($fhandle, $content);
507 if ($nbofbyteswrote ===
false) {
508 throw new RestException(500,
"Failed to write file '".$destfiletmp.
"'");
512 'description' =>
'File uploaded using ticket API',
513 'src_object_type' => $this->ticket->element,
514 'src_object_id' => $this->ticket->id,
515 'gen_or_uploaded' =>
'uploaded'
517 $resultmove =
dol_move($destfiletmp, $destfile,
'0', 1, 0, 1, $moreinfo);
519 throw new RestException(500,
"Failed to move file into '".$destfile.
"'");
522 $filename_list[] = $destfile;
523 $mimefilename_list[] = basename($destfile);
524 $mimetype_list[] = !empty($attachment[
'mimetype']) ? $attachment[
'mimetype'] :
'';
528 $actionid = $this->ticket->createTicketMessage(DolibarrApiAccess::$user, 0, $filename_list, $mimetype_list, $mimefilename_list);
529 if ($actionid <= 0) {
530 throw new RestException(500,
'Error when creating ticket');
532 if ($return_action_id) {
533 return array(
'ticket_id' => $this->ticket->id,
'action_id' => $actionid);
535 return $this->ticket->id;
547 public function put(
$id, $request_data =
null)
549 if (!DolibarrApiAccess::$user->hasRight(
'ticket',
'write')) {
550 throw new RestException(403);
553 $result = $this->ticket->fetch(
$id);
555 throw new RestException(404,
'Ticket not found');
559 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
563 $socid = (int) $request_data[
'socid'];
565 $thirdpartytmp =
new Societe($this->db);
566 $thirdparty_result = $thirdpartytmp->fetch($socid);
567 if ($thirdparty_result < 1) {
568 throw new RestException(404,
'Thirdparty with id='.$socid.
' not found or not allowed');
571 throw new RestException(404,
'Thirdparty with id='.$thirdpartytmp->id.
' not found or not allowed');
575 foreach ($request_data as $field => $value) {
576 if ($field ===
'caller') {
578 $this->ticket->context[
'caller'] =
sanitizeVal($request_data[
'caller'],
'aZ09');
582 if ($field ==
'id') {
585 if ($field ==
'array_options' && is_array($value)) {
586 foreach ($value as $index => $val) {
592 $this->ticket->$field = $this->
_checkValForAPI($field, $value, $this->ticket);
595 if ($this->ticket->update(DolibarrApiAccess::$user) > 0) {
596 return $this->
get(
$id);
598 throw new RestException(500, $this->ticket->error);
610 public function delete(
$id)
612 if (!DolibarrApiAccess::$user->hasRight(
'ticket',
'delete')) {
613 throw new RestException(403);
615 $result = $this->ticket->fetch(
$id);
617 throw new RestException(404,
'Ticket not found');
621 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
624 if (!$this->ticket->delete(DolibarrApiAccess::$user)) {
625 throw new RestException(500,
'Error when deleting ticket');
631 'message' =>
'Ticket deleted'
646 if ($data ===
null) {
650 foreach (Tickets::$FIELDS as $field) {
651 if (!isset($data[$field])) {
652 throw new RestException(400,
"$field field missing");
654 $ticket[$field] = $data[$field];
669 if ($data ===
null) {
673 foreach (Tickets::$FIELDS_MESSAGES as $field) {
674 if (!isset($data[$field])) {
675 throw new RestException(400,
"$field field missing");
677 $ticket[$field] = $data[$field];
706 "table_element_line",
713 "barcode_type_label",
714 "barcode_type_coder",
718 "fk_delivery_address",
719 "shipping_method_id",
732 "location_incoterms",
740 "cache_types_tickets",
744 "multicurrency_code",
746 "multicurrency_total_ht",
747 "multicurrency_total_ttc",
748 "multicurrency_total_tva",
749 "multicurrency_total_localtax1",
750 "multicurrency_total_localtax2"
752 foreach ($attr2clean as $toclean) {
758 $nboflines = count(
$object->lines);
759 for ($i = 0; $i < $nboflines; $i++) {
765 if (isset(
$object->linkedObjects) && count(
$object->linkedObjects) > 0) {
766 foreach (
$object->linkedObjects as $type_object => $linked_object) {
767 foreach ($linked_object as $object2clean) {
795 public function postContact(
int $id,
int $contactid,
string $type,
string $source =
"external",
int $notrigger = 0): array
798 if (!DolibarrApiAccess::$user->hasRight(
'ticket',
'write')) {
799 throw new RestException(403);
803 if (empty($source)) {
804 throw new RestException(400,
'Source can not be empty');
808 throw new RestException(400,
'type can not be empty');
812 $sqlCheckTypeSource =
"SELECT tc.rowid";
813 $sqlCheckTypeSource .=
" FROM ".$this->db->prefix().
"c_type_contact as tc";
814 $sqlCheckTypeSource .=
" WHERE tc.element LIKE 'ticket'";
815 $sqlCheckTypeSource .=
" AND tc.source = '".$this->db->escape($source).
"'";
816 $sqlCheckTypeSource .=
" AND tc.code = '".$this->db->escape($type).
"'";
817 $sqlCheckTypeSource .=
" AND tc.active = 1";
818 $result = $this->db->query($sqlCheckTypeSource);
820 if ($result && $this->db->num_rows($result) == 0) {
821 throw new RestException(400,
'Contact type not found');
825 if ($source ==
"external") {
827 $sqlCheckExternalContact =
"SELECT 1 as exist";
828 $sqlCheckExternalContact .=
" FROM ".MAIN_DB_PREFIX.
"socpeople";
829 $sqlCheckExternalContact .=
" WHERE rowid = " . intval($contactid);
830 $result = $this->db->query($sqlCheckExternalContact);
832 if ($result && $this->db->num_rows($result) == 0) {
833 throw new RestException(404,
'External contact not found');
837 $sqlCheckInternalContact =
"SELECT 1 as exist";
838 $sqlCheckInternalContact .=
" FROM ".MAIN_DB_PREFIX.
"user";
839 $sqlCheckInternalContact .=
" WHERE rowid = " . intval($contactid);
840 $result = $this->db->query($sqlCheckInternalContact);
842 if ($result && $this->db->num_rows($result) == 0) {
843 throw new RestException(404,
'Internal contact not found');
848 $result = $this->ticket->fetch(
$id);
850 throw new RestException(404,
'Ticket not found');
853 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
856 $result = $this->ticket->add_contact($contactid, $type, $source, $notrigger);
859 throw new RestException(400,
'Already exists: Contact='.$contactid.
' is already linked to the ticket='.
$id.
' as source='.$source.
' and type='.$type);
860 } elseif ($result == -1) {
861 throw new RestException(400,
'Wrong contact='.$contactid);
862 } elseif ($result == -2) {
863 throw new RestException(400,
'Wrong type='.$type);
864 } elseif ($result == -3) {
865 throw new RestException(400,
'Not allowed contacts');
866 } elseif ($result == -4) {
867 throw new RestException(400,
'ErrorCommercialNotAllowedForThirdparty');
868 } elseif ($result == -5) {
869 throw new RestException(400,
'Trigger failed');
870 } elseif ($result == -6) {
871 throw new RestException(400,
'DB_ERROR_RECORD_ALREADY_EXISTS');
872 } elseif ($result == -7) {
873 throw new RestException(400,
'Some other error');
874 } elseif ($result <= -8) {
875 throw new RestException(400,
'Unknown error occurred');
881 'message' =>
'Contact='.$contactid.
' linked to the ticket='.
$id.
' as '.$source.
' '.$type
905 public function deleteContact(
int $id,
int $contactid,
string $type,
string $source =
"external"): array
908 if (!DolibarrApiAccess::$user->hasRight(
'ticket',
'write')) {
909 throw new RestException(403);
913 if (empty($source)) {
914 throw new RestException(400,
'Source can not be empty');
918 throw new RestException(400,
'type can not be empty');
921 $result = $this->ticket->fetch(
$id);
923 throw new RestException(404,
'Ticket not found');
927 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
930 $contacts = $this->ticket->liste_contact(-1, $source);
931 foreach ($contacts as $contact) {
932 if ($contact[
'id'] == $contactid && $contact[
'code'] == $type) {
933 $result = $this->ticket->delete_contact($contact[
'rowid']);
936 throw new RestException(500,
'Error when deleting the contact '.$contact[
'rowid']);
944 'message' =>
'Contact unlinked from ticket'
$id
Support class for third parties, contacts, members, users or resources.
if(! $sortfield) if(! $sortorder) $object
_checkValExtrafieldsForAPI($field, $value, $object)
Check and convert a string depending on its type/name.
_filterObjectProperties($object, $properties)
Filter properties that will be returned on object.
_checkValForAPI($field, $value, $object)
Check and convert a string depending on its type/name.
static _checkAccessToResource($resource, $resource_id=0, $dbtablename='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $parenttableforentity='')
Check access by user to a given resource.
Class to manage third parties objects (customers, suppliers, prospects...)
getByTrackId($track_id, $contact_list=1)
Get properties of a Ticket object from track id.
deleteContact(int $id, int $contactid, string $type, string $source="external")
Unlink a contact type of given ticket.
getCommon($id=0, $track_id='', $ref='', $contact_list=1)
Get properties of a Ticket object Return an array with ticket information.
__construct()
Constructor.
index($socid=0, $sortfield="t.rowid", $sortorder="ASC", $limit=100, $page=0, $sqlfilters='', $properties='', $loadcontacts=0, $pagination_data=false)
List tickets.
_cleanObjectDatas($object)
Clean sensible object datas @phpstan-template T.
postNewMessage($request_data=null)
Add a new message to an existing ticket identified by property ->track_id into request.
post($request_data=null)
Create ticket object.
put($id, $request_data=null)
Update ticket.
_validateMessage($data)
Validate fields before create or update object message.
postContact(int $id, int $contactid, string $type, string $source="external", int $notrigger=0)
Add a contact type of given ticket.
getByRef($ref, $contact_list=1)
Get properties of a Ticket object from ref.
_validate($data)
Validate fields before create or update object.
Class to manage Dolibarr users.
dol_move($srcfile, $destfile, $newmask='0', $overwriteifexists=1, $testvirus=0, $indexdatabase=1, $moreinfo=array(), $entity=null)
Move a file into another name.
dol_is_dir($folder)
Test if filename is a directory.
dol_now($mode='gmt')
Return date for now.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0, $forbiddenfields=array())
forgeSQLFromUniversalSearchCriteria
sanitizeVal($out='', $check='alphanohtml', $filter=null, $options=null)
Return a sanitized or empty value after checking value against a rule.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
Class to generate the form for creating a new ticket.
generate_random_id($car=16)
Generate a random id.