|
1
|
|
|
<?php |
|
2
|
|
|
/* Copyright (C) 2013-2018 Jean-François FERRY <[email protected]> |
|
3
|
|
|
* Copyright (C) 2016 Christophe Battarel <[email protected]> |
|
4
|
|
|
* Copyright (C) 2019-2020 Frédéric France <[email protected]> |
|
5
|
|
|
* |
|
6
|
|
|
* This program is free software: you can redistribute it and/or modify |
|
7
|
|
|
* it under the terms of the GNU General Public License as published by |
|
8
|
|
|
* the Free Software Foundation, either version 3 of the License, or |
|
9
|
|
|
* (at your option) any later version. |
|
10
|
|
|
* |
|
11
|
|
|
* This program is distributed in the hope that it will be useful, |
|
12
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14
|
|
|
* GNU General Public License for more details. |
|
15
|
|
|
* |
|
16
|
|
|
* You should have received a copy of the GNU General Public License |
|
17
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. |
|
18
|
|
|
*/ |
|
19
|
|
|
|
|
20
|
|
|
/** |
|
21
|
|
|
* \file core/lib/ticket.lib.php |
|
22
|
|
|
* \ingroup ticket |
|
23
|
|
|
* \brief This file is a library for Ticket module |
|
24
|
|
|
*/ |
|
25
|
|
|
|
|
26
|
|
|
/** |
|
27
|
|
|
* Build tabs for admin page |
|
28
|
|
|
* |
|
29
|
|
|
* @return array |
|
30
|
|
|
*/ |
|
31
|
|
|
function ticketAdminPrepareHead() |
|
32
|
|
|
{ |
|
33
|
|
|
global $langs, $conf; |
|
34
|
|
|
|
|
35
|
|
|
$langs->load("ticket"); |
|
36
|
|
|
|
|
37
|
|
|
$h = 0; |
|
38
|
|
|
$head = array(); |
|
39
|
|
|
|
|
40
|
|
|
$head[$h][0] = DOL_URL_ROOT.'/admin/ticket.php'; |
|
41
|
|
|
$head[$h][1] = $langs->trans("TicketSettings"); |
|
42
|
|
|
$head[$h][2] = 'settings'; |
|
43
|
|
|
$h++; |
|
44
|
|
|
|
|
45
|
|
|
$head[$h][0] = DOL_URL_ROOT.'/admin/ticket_extrafields.php'; |
|
46
|
|
|
$head[$h][1] = $langs->trans("ExtraFieldsTicket"); |
|
47
|
|
|
$head[$h][2] = 'attributes'; |
|
48
|
|
|
$h++; |
|
49
|
|
|
|
|
50
|
|
|
$head[$h][0] = DOL_URL_ROOT.'/admin/ticket_public.php'; |
|
51
|
|
|
$head[$h][1] = $langs->trans("PublicInterface"); |
|
52
|
|
|
$head[$h][2] = 'public'; |
|
53
|
|
|
$h++; |
|
54
|
|
|
|
|
55
|
|
|
// Show more tabs from modules |
|
56
|
|
|
// Entries must be declared in modules descriptor with line |
|
57
|
|
|
//$this->tabs = array( |
|
58
|
|
|
// 'entity:+tabname:Title:@ticket:/ticket/mypage.php?id=__ID__' |
|
59
|
|
|
//); // to add new tab |
|
60
|
|
|
//$this->tabs = array( |
|
61
|
|
|
// 'entity:-tabname:Title:@ticket:/ticket/mypage.php?id=__ID__' |
|
62
|
|
|
//); // to remove a tab |
|
63
|
|
|
complete_head_from_modules($conf, $langs, null, $head, $h, 'ticketadmin'); |
|
64
|
|
|
|
|
65
|
|
|
complete_head_from_modules($conf, $langs, null, $head, $h, 'ticketadmin', 'remove'); |
|
66
|
|
|
|
|
67
|
|
|
return $head; |
|
68
|
|
|
} |
|
69
|
|
|
|
|
70
|
|
|
/** |
|
71
|
|
|
* Build tabs for a Ticket object |
|
72
|
|
|
* |
|
73
|
|
|
* @param Ticket $object Object Ticket |
|
74
|
|
|
* @return array Array of tabs |
|
75
|
|
|
*/ |
|
76
|
|
|
function ticket_prepare_head($object) |
|
77
|
|
|
{ |
|
78
|
|
|
global $db, $langs, $conf, $user; |
|
79
|
|
|
|
|
80
|
|
|
$h = 0; |
|
81
|
|
|
$head = array(); |
|
82
|
|
|
$head[$h][0] = DOL_URL_ROOT.'/ticket/card.php?action=view&track_id='.$object->track_id; |
|
83
|
|
|
$head[$h][1] = $langs->trans("Ticket"); |
|
84
|
|
|
$head[$h][2] = 'tabTicket'; |
|
85
|
|
|
$h++; |
|
86
|
|
|
|
|
87
|
|
|
if (empty($conf->global->MAIN_DISABLE_CONTACTS_TAB) && empty($user->socid) && $conf->societe->enabled) { |
|
88
|
|
|
$nbContact = count($object->liste_contact(-1, 'internal')) + count($object->liste_contact(-1, 'external')); |
|
89
|
|
|
$head[$h][0] = DOL_URL_ROOT.'/ticket/contact.php?track_id='.$object->track_id; |
|
90
|
|
|
$head[$h][1] = $langs->trans('ContactsAddresses'); |
|
91
|
|
|
if ($nbContact > 0) { |
|
92
|
|
|
$head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbContact.'</span>'; |
|
93
|
|
|
} |
|
94
|
|
|
$head[$h][2] = 'contact'; |
|
95
|
|
|
$h++; |
|
96
|
|
|
} |
|
97
|
|
|
|
|
98
|
|
|
complete_head_from_modules($conf, $langs, $object, $head, $h, 'ticket'); |
|
99
|
|
|
|
|
100
|
|
|
// Attached files |
|
101
|
|
|
include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; |
|
102
|
|
|
$upload_dir = $conf->ticket->dir_output."/".$object->ref; |
|
103
|
|
|
$nbFiles = count(dol_dir_list($upload_dir, 'files')); |
|
104
|
|
|
$head[$h][0] = dol_buildpath('/ticket/document.php', 1).'?id='.$object->id; |
|
105
|
|
|
$head[$h][1] = $langs->trans("Documents"); |
|
106
|
|
|
if ($nbFiles > 0) { |
|
107
|
|
|
$head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbFiles.'</span>'; |
|
108
|
|
|
} |
|
109
|
|
|
|
|
110
|
|
|
$head[$h][2] = 'tabTicketDocument'; |
|
111
|
|
|
$h++; |
|
112
|
|
|
|
|
113
|
|
|
|
|
114
|
|
|
// History |
|
115
|
|
|
$ticketViewType = "messaging"; |
|
116
|
|
|
if (empty($_SESSION['ticket-view-type'])) { |
|
117
|
|
|
$_SESSION['ticket-view-type'] = $ticketViewType; |
|
118
|
|
|
} else { |
|
119
|
|
|
$ticketViewType = $_SESSION['ticket-view-type']; |
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
|
|
if ($ticketViewType == "messaging") { |
|
123
|
|
|
$head[$h][0] = DOL_URL_ROOT.'/ticket/messaging.php?track_id='.$object->track_id; |
|
124
|
|
|
} else { |
|
125
|
|
|
// $ticketViewType == "list" |
|
126
|
|
|
$head[$h][0] = DOL_URL_ROOT.'/ticket/agenda.php?track_id='.$object->track_id; |
|
127
|
|
|
} |
|
128
|
|
|
$head[$h][1] = $langs->trans('Events'); |
|
129
|
|
|
if (!empty($conf->agenda->enabled) && (!empty($user->rights->agenda->myactions->read) || !empty($user->rights->agenda->allactions->read))) { |
|
130
|
|
|
$head[$h][1] .= '/'; |
|
131
|
|
|
$head[$h][1] .= $langs->trans("Agenda"); |
|
132
|
|
|
} |
|
133
|
|
|
$head[$h][2] = 'tabTicketLogs'; |
|
134
|
|
|
$h++; |
|
135
|
|
|
|
|
136
|
|
|
complete_head_from_modules($conf, $langs, $object, $head, $h, 'ticket', 'remove'); |
|
137
|
|
|
|
|
138
|
|
|
return $head; |
|
139
|
|
|
} |
|
140
|
|
|
|
|
141
|
|
|
/** |
|
142
|
|
|
* Return string with full Url. The file qualified is the one defined by relative path in $object->last_main_doc |
|
143
|
|
|
* |
|
144
|
|
|
* @param Object $object Object |
|
145
|
|
|
* @return string Url string |
|
146
|
|
|
*/ |
|
147
|
|
|
function showDirectPublicLink($object) |
|
148
|
|
|
{ |
|
149
|
|
|
global $conf, $langs; |
|
150
|
|
|
|
|
151
|
|
|
require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; |
|
152
|
|
|
$email = CMailFile::getValidAddress($object->origin_email, 2); |
|
153
|
|
|
$url = ''; |
|
154
|
|
|
if ($email) { |
|
155
|
|
|
$url = dol_buildpath('/public/ticket/view.php', 3).'?track_id='.$object->track_id.'&email='.$email; |
|
156
|
|
|
} |
|
157
|
|
|
|
|
158
|
|
|
$out = ''; |
|
159
|
|
|
if (empty($conf->global->TICKET_ENABLE_PUBLIC_INTERFACE)) { |
|
160
|
|
|
$langs->load('errors'); |
|
161
|
|
|
$out .= '<span class="opacitymedium">'.$langs->trans("ErrorPublicInterfaceNotEnabled").'</span>'; |
|
162
|
|
|
} else { |
|
163
|
|
|
$out .= img_picto('', 'object_globe.png').' <span class="opacitymedium">'.$langs->trans("TicketPublicAccess").'</span><br>'; |
|
164
|
|
|
if ($url) { |
|
165
|
|
|
$out .= '<div class="urllink">'; |
|
166
|
|
|
$out .= '<input type="text" id="directpubliclink" class="quatrevingtpercent" value="'.$url.'">'; |
|
167
|
|
|
$out .= '<a href="'.$url.'" target="_blank" rel="noopener">'.img_picto('', 'object_globe.png', 'class="paddingleft"').'</a>'; |
|
168
|
|
|
$out .= '</div>'; |
|
169
|
|
|
$out .= ajax_autoselect("directpubliclink", 0); |
|
170
|
|
|
} else { |
|
171
|
|
|
$out .= '<span class="opacitymedium">'.$langs->trans("TicketNotCreatedFromPublicInterface").'</span>'; |
|
172
|
|
|
} |
|
173
|
|
|
} |
|
174
|
|
|
|
|
175
|
|
|
return $out; |
|
176
|
|
|
} |
|
177
|
|
|
|
|
178
|
|
|
/** |
|
179
|
|
|
* Generate a random id |
|
180
|
|
|
* |
|
181
|
|
|
* @param int $car Length of string to generate key |
|
182
|
|
|
* @return string |
|
183
|
|
|
*/ |
|
184
|
|
|
function generate_random_id($car = 16) |
|
185
|
|
|
{ |
|
186
|
|
|
$string = ""; |
|
187
|
|
|
$chaine = "abcdefghijklmnopqrstuvwxyz123456789"; |
|
188
|
|
|
srand((double) microtime() * 1000000); |
|
189
|
|
|
for ($i = 0; $i < $car; $i++) { |
|
190
|
|
|
$string .= $chaine[rand() % strlen($chaine)]; |
|
191
|
|
|
} |
|
192
|
|
|
return $string; |
|
193
|
|
|
} |
|
194
|
|
|
|
|
195
|
|
|
/** |
|
196
|
|
|
* Show header for public pages |
|
197
|
|
|
* |
|
198
|
|
|
* @param string $title Title |
|
199
|
|
|
* @param string $head Head array |
|
200
|
|
|
* @param int $disablejs More content into html header |
|
201
|
|
|
* @param int $disablehead More content into html header |
|
202
|
|
|
* @param array $arrayofjs Array of complementary js files |
|
203
|
|
|
* @param array $arrayofcss Array of complementary css files |
|
204
|
|
|
* @return void |
|
205
|
|
|
*/ |
|
206
|
|
|
function llxHeaderTicket($title, $head = "", $disablejs = 0, $disablehead = 0, $arrayofjs = '', $arrayofcss = '') |
|
207
|
|
|
{ |
|
208
|
|
|
global $user, $conf, $langs, $mysoc; |
|
209
|
|
|
|
|
210
|
|
|
top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss, 0, 1); // Show html headers |
|
211
|
|
|
|
|
212
|
|
|
print '<body id="mainbody" class="publicnewticketform">'; |
|
213
|
|
|
print '<div class="center">'; |
|
214
|
|
|
|
|
215
|
|
|
// Define urllogo |
|
216
|
|
|
if (!empty($conf->global->TICKET_SHOW_COMPANY_LOGO) || !empty($conf->global->TICKET_PUBLIC_INTERFACE_TOPIC)) { |
|
217
|
|
|
// Print logo |
|
218
|
|
|
if (!empty($conf->global->TICKET_SHOW_COMPANY_LOGO)) { |
|
219
|
|
|
$urllogo = DOL_URL_ROOT.'/theme/common/login_logo.png'; |
|
220
|
|
|
|
|
221
|
|
|
if (!empty($mysoc->logo_small) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$mysoc->logo_small)) { |
|
222
|
|
|
$urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/thumbs/'.$mysoc->logo_small); |
|
223
|
|
|
} elseif (!empty($mysoc->logo) && is_readable($conf->mycompany->dir_output.'/logos/'.$mysoc->logo)) { |
|
224
|
|
|
$urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/'.$mysoc->logo); |
|
225
|
|
|
} elseif (is_readable(DOL_DOCUMENT_ROOT.'/theme/dolibarr_logo.svg')) { |
|
226
|
|
|
$urllogo = DOL_URL_ROOT.'/theme/dolibarr_logo.svg'; |
|
227
|
|
|
} |
|
228
|
|
|
} |
|
229
|
|
|
} |
|
230
|
|
|
|
|
231
|
|
|
// Output html code for logo |
|
232
|
|
|
if ($urllogo || !empty($conf->global->TICKET_PUBLIC_INTERFACE_TOPIC)) { |
|
|
|
|
|
|
233
|
|
|
print '<div class="backgreypublicpayment">'; |
|
234
|
|
|
print '<div class="logopublicpayment">'; |
|
235
|
|
|
if ($urllogo) { |
|
236
|
|
|
print '<a href="'.($conf->global->TICKET_URL_PUBLIC_INTERFACE ? $conf->global->TICKET_URL_PUBLIC_INTERFACE : dol_buildpath('/public/ticket/index.php', 1)).'">'; |
|
237
|
|
|
print '<img id="dolpaymentlogo" src="'.$urllogo.'"'; |
|
238
|
|
|
print '>'; |
|
239
|
|
|
print '</a>'; |
|
240
|
|
|
} |
|
241
|
|
|
if (!empty($conf->global->TICKET_PUBLIC_INTERFACE_TOPIC)) { |
|
242
|
|
|
print '<div class="clearboth"></div><strong>'.($conf->global->TICKET_PUBLIC_INTERFACE_TOPIC ? $conf->global->TICKET_PUBLIC_INTERFACE_TOPIC : $langs->trans("TicketSystem")).'</strong>'; |
|
243
|
|
|
} |
|
244
|
|
|
print '</div>'; |
|
245
|
|
|
if (empty($conf->global->MAIN_HIDE_POWERED_BY)) { |
|
246
|
|
|
print '<div class="poweredbypublicpayment opacitymedium right"><a class="poweredbyhref" href="https://www.dolibarr.org?utm_medium=website&utm_source=poweredby" target="dolibarr" rel="noopener">'.$langs->trans("PoweredBy").'<br><img src="'.DOL_URL_ROOT.'/theme/dolibarr_logo.svg" width="80px"></a></div>'; |
|
247
|
|
|
} |
|
248
|
|
|
print '</div>'; |
|
249
|
|
|
} |
|
250
|
|
|
|
|
251
|
|
|
if (!empty($conf->global->TICKET_IMAGE_PUBLIC_INTERFACE)) { |
|
252
|
|
|
print '<div class="backimagepublicticket">'; |
|
253
|
|
|
print '<img id="idRECRUITMENT_IMAGE_PUBLIC_INTERFACE" src="'.$conf->global->MEMBER_IMAGE_PUBLIC_REGISTRATION.'">'; |
|
254
|
|
|
print '</div>'; |
|
255
|
|
|
} |
|
256
|
|
|
|
|
257
|
|
|
print '</div>'; |
|
258
|
|
|
|
|
259
|
|
|
print '<div class="ticketlargemargin">'; |
|
260
|
|
|
} |
|
261
|
|
|
|
|
262
|
|
|
|
|
263
|
|
|
|
|
264
|
|
|
/** |
|
265
|
|
|
* Show html area with actions for ticket messaging. |
|
266
|
|
|
* Note: Global parameter $param must be defined. |
|
267
|
|
|
* |
|
268
|
|
|
* @param Conf $conf Object conf |
|
269
|
|
|
* @param Translate $langs Object langs |
|
270
|
|
|
* @param DoliDB $db Object db |
|
271
|
|
|
* @param mixed $filterobj Filter on object Adherent|Societe|Project|Product|CommandeFournisseur|Dolresource|Ticket|... to list events linked to an object |
|
272
|
|
|
* @param Contact $objcon Filter on object contact to filter events on a contact |
|
273
|
|
|
* @param int $noprint Return string but does not output it |
|
274
|
|
|
* @param string $actioncode Filter on actioncode |
|
275
|
|
|
* @param string $donetodo Filter on event 'done' or 'todo' or ''=nofilter (all). |
|
276
|
|
|
* @param array $filters Filter on other fields |
|
277
|
|
|
* @param string $sortfield Sort field |
|
278
|
|
|
* @param string $sortorder Sort order |
|
279
|
|
|
* @return string|void Return html part or void if noprint is 1 |
|
280
|
|
|
*/ |
|
281
|
|
|
function show_ticket_messaging($conf, $langs, $db, $filterobj, $objcon = '', $noprint = 0, $actioncode = '', $donetodo = 'done', $filters = array(), $sortfield = 'a.datep,a.id', $sortorder = 'DESC') |
|
282
|
|
|
{ |
|
283
|
|
|
global $user, $conf; |
|
284
|
|
|
global $form; |
|
285
|
|
|
|
|
286
|
|
|
global $param, $massactionbutton; |
|
287
|
|
|
|
|
288
|
|
|
dol_include_once('/comm/action/class/actioncomm.class.php'); |
|
289
|
|
|
|
|
290
|
|
|
// Check parameters |
|
291
|
|
|
if (!is_object($filterobj) && !is_object($objcon)) { |
|
292
|
|
|
dol_print_error('', 'BadParameter'); |
|
293
|
|
|
} |
|
294
|
|
|
|
|
295
|
|
|
$histo = array(); |
|
296
|
|
|
$numaction = 0; |
|
297
|
|
|
$now = dol_now(); |
|
298
|
|
|
|
|
299
|
|
|
$sortfield_list = explode(',', $sortfield); |
|
300
|
|
|
$sortfield_label_list = array('a.id' => 'id', 'a.datep' => 'dp', 'a.percent' => 'percent'); |
|
301
|
|
|
$sortfield_new_list = array(); |
|
302
|
|
|
foreach ($sortfield_list as $sortfield_value) { |
|
303
|
|
|
$sortfield_new_list[] = $sortfield_label_list[trim($sortfield_value)]; |
|
304
|
|
|
} |
|
305
|
|
|
$sortfield_new = implode(',', $sortfield_new_list); |
|
306
|
|
|
|
|
307
|
|
|
if (!empty($conf->agenda->enabled)) { |
|
308
|
|
|
// Search histo on actioncomm |
|
309
|
|
|
if (is_object($objcon) && $objcon->id > 0) { |
|
310
|
|
|
$sql = "SELECT DISTINCT a.id, a.label as label,"; |
|
311
|
|
|
} else { |
|
312
|
|
|
$sql = "SELECT a.id, a.label as label,"; |
|
313
|
|
|
} |
|
314
|
|
|
$sql .= " a.datep as dp,"; |
|
315
|
|
|
$sql .= " a.note as message,"; |
|
316
|
|
|
$sql .= " a.datep2 as dp2,"; |
|
317
|
|
|
$sql .= " a.percent as percent, 'action' as type,"; |
|
318
|
|
|
$sql .= " a.fk_element, a.elementtype,"; |
|
319
|
|
|
$sql .= " a.fk_contact,"; |
|
320
|
|
|
$sql .= " c.code as acode, c.libelle as alabel, c.picto as apicto,"; |
|
321
|
|
|
$sql .= " u.rowid as user_id, u.login as user_login, u.photo as user_photo, u.firstname as user_firstname, u.lastname as user_lastname"; |
|
322
|
|
|
if (is_object($filterobj) && get_class($filterobj) == 'Societe') { |
|
323
|
|
|
$sql .= ", sp.lastname, sp.firstname"; |
|
324
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'Adherent') { |
|
325
|
|
|
$sql .= ", m.lastname, m.firstname"; |
|
326
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'CommandeFournisseur') { |
|
327
|
|
|
$sql .= ", o.ref"; |
|
328
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'Product') { |
|
329
|
|
|
$sql .= ", o.ref"; |
|
330
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'Ticket') { |
|
331
|
|
|
$sql .= ", o.ref"; |
|
332
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'BOM') { |
|
333
|
|
|
$sql .= ", o.ref"; |
|
334
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'Contrat') { |
|
335
|
|
|
$sql .= ", o.ref"; |
|
336
|
|
|
} |
|
337
|
|
|
$sql .= " FROM ".MAIN_DB_PREFIX."actioncomm as a"; |
|
338
|
|
|
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on u.rowid = a.fk_user_action"; |
|
339
|
|
|
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_actioncomm as c ON a.fk_action = c.id"; |
|
340
|
|
|
|
|
341
|
|
|
$force_filter_contact = false; |
|
342
|
|
|
if (is_object($objcon) && $objcon->id > 0) { |
|
343
|
|
|
$force_filter_contact = true; |
|
344
|
|
|
$sql .= " INNER JOIN ".MAIN_DB_PREFIX."actioncomm_resources as r ON a.id = r.fk_actioncomm"; |
|
345
|
|
|
$sql .= " AND r.element_type = '".$db->escape($objcon->table_element)."' AND r.fk_element = ".((int) $objcon->id); |
|
346
|
|
|
} |
|
347
|
|
|
|
|
348
|
|
|
if (is_object($filterobj) && get_class($filterobj) == 'Societe') { |
|
349
|
|
|
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."socpeople as sp ON a.fk_contact = sp.rowid"; |
|
350
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'Dolresource') { |
|
351
|
|
|
$sql .= " INNER JOIN ".MAIN_DB_PREFIX."element_resources as er"; |
|
352
|
|
|
$sql .= " ON er.resource_type = 'dolresource'"; |
|
353
|
|
|
$sql .= " AND er.element_id = a.id"; |
|
354
|
|
|
$sql .= " AND er.resource_id = ".$filterobj->id; |
|
355
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'Adherent') { |
|
356
|
|
|
$sql .= ", ".MAIN_DB_PREFIX."adherent as m"; |
|
357
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'CommandeFournisseur') { |
|
358
|
|
|
$sql .= ", ".MAIN_DB_PREFIX."commande_fournisseur as o"; |
|
359
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'Product') { |
|
360
|
|
|
$sql .= ", ".MAIN_DB_PREFIX."product as o"; |
|
361
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'Ticket') { |
|
362
|
|
|
$sql .= ", ".MAIN_DB_PREFIX."ticket as o"; |
|
363
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'BOM') { |
|
364
|
|
|
$sql .= ", ".MAIN_DB_PREFIX."bom_bom as o"; |
|
365
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'Contrat') { |
|
366
|
|
|
$sql .= ", ".MAIN_DB_PREFIX."contrat as o"; |
|
367
|
|
|
} |
|
368
|
|
|
|
|
369
|
|
|
$sql .= " WHERE a.entity IN (".getEntity('agenda').")"; |
|
370
|
|
|
if ($force_filter_contact === false) { |
|
371
|
|
|
if (is_object($filterobj) && in_array(get_class($filterobj), array('Societe', 'Client', 'Fournisseur')) && $filterobj->id) { |
|
372
|
|
|
$sql .= " AND a.fk_soc = ".$filterobj->id; |
|
373
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'Project' && $filterobj->id) { |
|
374
|
|
|
$sql .= " AND a.fk_project = ".$filterobj->id; |
|
375
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'Adherent') { |
|
376
|
|
|
$sql .= " AND a.fk_element = m.rowid AND a.elementtype = 'member'"; |
|
377
|
|
|
if ($filterobj->id) { |
|
378
|
|
|
$sql .= " AND a.fk_element = ".$filterobj->id; |
|
379
|
|
|
} |
|
380
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'CommandeFournisseur') { |
|
381
|
|
|
$sql .= " AND a.fk_element = o.rowid AND a.elementtype = 'order_supplier'"; |
|
382
|
|
|
if ($filterobj->id) { |
|
383
|
|
|
$sql .= " AND a.fk_element = ".$filterobj->id; |
|
384
|
|
|
} |
|
385
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'Product') { |
|
386
|
|
|
$sql .= " AND a.fk_element = o.rowid AND a.elementtype = 'product'"; |
|
387
|
|
|
if ($filterobj->id) { |
|
388
|
|
|
$sql .= " AND a.fk_element = ".$filterobj->id; |
|
389
|
|
|
} |
|
390
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'Ticket') { |
|
391
|
|
|
$sql .= " AND a.fk_element = o.rowid AND a.elementtype = 'ticket'"; |
|
392
|
|
|
if ($filterobj->id) { |
|
393
|
|
|
$sql .= " AND a.fk_element = ".$filterobj->id; |
|
394
|
|
|
} |
|
395
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'BOM') { |
|
396
|
|
|
$sql .= " AND a.fk_element = o.rowid AND a.elementtype = 'bom'"; |
|
397
|
|
|
if ($filterobj->id) { |
|
398
|
|
|
$sql .= " AND a.fk_element = ".$filterobj->id; |
|
399
|
|
|
} |
|
400
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'Contrat') { |
|
401
|
|
|
$sql .= " AND a.fk_element = o.rowid AND a.elementtype = 'contract'"; |
|
402
|
|
|
if ($filterobj->id) { |
|
403
|
|
|
$sql .= " AND a.fk_element = ".$filterobj->id; |
|
404
|
|
|
} |
|
405
|
|
|
} |
|
406
|
|
|
} |
|
407
|
|
|
|
|
408
|
|
|
// Condition on actioncode |
|
409
|
|
|
if (!empty($actioncode)) { |
|
410
|
|
|
if (empty($conf->global->AGENDA_USE_EVENT_TYPE)) { |
|
411
|
|
|
if ($actioncode == 'AC_NON_AUTO') { |
|
412
|
|
|
$sql .= " AND c.type != 'systemauto'"; |
|
413
|
|
|
} elseif ($actioncode == 'AC_ALL_AUTO') { |
|
414
|
|
|
$sql .= " AND c.type = 'systemauto'"; |
|
415
|
|
|
} else { |
|
416
|
|
|
if ($actioncode == 'AC_OTH') { |
|
417
|
|
|
$sql .= " AND c.type != 'systemauto'"; |
|
418
|
|
|
} elseif ($actioncode == 'AC_OTH_AUTO') { |
|
419
|
|
|
$sql .= " AND c.type = 'systemauto'"; |
|
420
|
|
|
} |
|
421
|
|
|
} |
|
422
|
|
|
} else { |
|
423
|
|
|
if ($actioncode == 'AC_NON_AUTO') { |
|
424
|
|
|
$sql .= " AND c.type != 'systemauto'"; |
|
425
|
|
|
} elseif ($actioncode == 'AC_ALL_AUTO') { |
|
426
|
|
|
$sql .= " AND c.type = 'systemauto'"; |
|
427
|
|
|
} else { |
|
428
|
|
|
$sql .= " AND c.code = '".$db->escape($actioncode)."'"; |
|
429
|
|
|
} |
|
430
|
|
|
} |
|
431
|
|
|
} |
|
432
|
|
|
if ($donetodo == 'todo') { |
|
433
|
|
|
$sql .= " AND ((a.percent >= 0 AND a.percent < 100) OR (a.percent = -1 AND a.datep > '".$db->idate($now)."'))"; |
|
434
|
|
|
} elseif ($donetodo == 'done') { |
|
435
|
|
|
$sql .= " AND (a.percent = 100 OR (a.percent = -1 AND a.datep <= '".$db->idate($now)."'))"; |
|
436
|
|
|
} |
|
437
|
|
|
if (is_array($filters) && $filters['search_agenda_label']) { |
|
438
|
|
|
$sql .= natural_search('a.label', $filters['search_agenda_label']); |
|
439
|
|
|
} |
|
440
|
|
|
} |
|
441
|
|
|
|
|
442
|
|
|
// Add also event from emailings. TODO This should be replaced by an automatic event ? May be it's too much for very large emailing. |
|
443
|
|
|
if (!empty($conf->mailing->enabled) && !empty($objcon->email) |
|
444
|
|
|
&& (empty($actioncode) || $actioncode == 'AC_OTH_AUTO' || $actioncode == 'AC_EMAILING')) { |
|
445
|
|
|
$langs->load("mails"); |
|
446
|
|
|
|
|
447
|
|
|
$sql2 = "SELECT m.rowid as id, m.titre as label, mc.date_envoi as dp, mc.date_envoi as dp2, '100' as percent, 'mailing' as type"; |
|
448
|
|
|
$sql2 .= ", null as fk_element, '' as elementtype, null as contact_id"; |
|
449
|
|
|
$sql2 .= ", 'AC_EMAILING' as acode, '' as alabel, '' as apicto"; |
|
450
|
|
|
$sql2 .= ", u.rowid as user_id, u.login as user_login, u.photo as user_photo, u.firstname as user_firstname, u.lastname as user_lastname"; // User that valid action |
|
451
|
|
|
if (is_object($filterobj) && get_class($filterobj) == 'Societe') { |
|
452
|
|
|
$sql2 .= ", '' as lastname, '' as firstname"; |
|
453
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'Adherent') { |
|
454
|
|
|
$sql2 .= ", '' as lastname, '' as firstname"; |
|
455
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'CommandeFournisseur') { |
|
456
|
|
|
$sql2 .= ", '' as ref"; |
|
457
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'Product') { |
|
458
|
|
|
$sql2 .= ", '' as ref"; |
|
459
|
|
|
} elseif (is_object($filterobj) && get_class($filterobj) == 'Ticket') { |
|
460
|
|
|
$sql2 .= ", '' as ref"; |
|
461
|
|
|
} |
|
462
|
|
|
$sql2 .= " FROM ".MAIN_DB_PREFIX."mailing as m, ".MAIN_DB_PREFIX."mailing_cibles as mc, ".MAIN_DB_PREFIX."user as u"; |
|
463
|
|
|
$sql2 .= " WHERE mc.email = '".$db->escape($objcon->email)."'"; // Search is done on email. |
|
464
|
|
|
$sql2 .= " AND mc.statut = 1"; |
|
465
|
|
|
$sql2 .= " AND u.rowid = m.fk_user_valid"; |
|
466
|
|
|
$sql2 .= " AND mc.fk_mailing=m.rowid"; |
|
467
|
|
|
} |
|
468
|
|
|
|
|
469
|
|
|
if (!empty($sql) && !empty($sql2)) { |
|
470
|
|
|
$sql = $sql." UNION ".$sql2; |
|
471
|
|
|
} elseif (empty($sql) && !empty($sql2)) { |
|
472
|
|
|
$sql = $sql2; |
|
473
|
|
|
} |
|
474
|
|
|
|
|
475
|
|
|
// TODO Add limit in nb of results |
|
476
|
|
|
if ($sql) { // May not be defined if module Agenda is not enabled and mailing module disabled too |
|
|
|
|
|
|
477
|
|
|
$sql .= $db->order($sortfield_new, $sortorder); |
|
478
|
|
|
|
|
479
|
|
|
dol_syslog("company.lib::show_actions_done", LOG_DEBUG); |
|
480
|
|
|
$resql = $db->query($sql); |
|
481
|
|
|
if ($resql) { |
|
482
|
|
|
$i = 0; |
|
483
|
|
|
$num = $db->num_rows($resql); |
|
484
|
|
|
|
|
485
|
|
|
while ($i < $num) { |
|
486
|
|
|
$obj = $db->fetch_object($resql); |
|
487
|
|
|
|
|
488
|
|
|
if ($obj->type == 'action') { |
|
489
|
|
|
$contactaction = new ActionComm($db); |
|
490
|
|
|
$contactaction->id = $obj->id; |
|
491
|
|
|
$result = $contactaction->fetchResources(); |
|
492
|
|
|
if ($result < 0) { |
|
493
|
|
|
dol_print_error($db); |
|
494
|
|
|
setEventMessage("company.lib::show_actions_done Error fetch ressource", 'errors'); |
|
495
|
|
|
} |
|
496
|
|
|
|
|
497
|
|
|
//if ($donetodo == 'todo') $sql.= " AND ((a.percent >= 0 AND a.percent < 100) OR (a.percent = -1 AND a.datep > '".$db->idate($now)."'))"; |
|
498
|
|
|
//elseif ($donetodo == 'done') $sql.= " AND (a.percent = 100 OR (a.percent = -1 AND a.datep <= '".$db->idate($now)."'))"; |
|
499
|
|
|
$tododone = ''; |
|
500
|
|
|
if (($obj->percent >= 0 and $obj->percent < 100) || ($obj->percent == -1 && $obj->datep > $now)) { |
|
501
|
|
|
$tododone = 'todo'; |
|
502
|
|
|
} |
|
503
|
|
|
|
|
504
|
|
|
$histo[$numaction] = array( |
|
505
|
|
|
'type'=>$obj->type, |
|
506
|
|
|
'tododone'=>$tododone, |
|
507
|
|
|
'id'=>$obj->id, |
|
508
|
|
|
'datestart'=>$db->jdate($obj->dp), |
|
509
|
|
|
'dateend'=>$db->jdate($obj->dp2), |
|
510
|
|
|
'note'=>$obj->label, |
|
511
|
|
|
'message'=>$obj->message, |
|
512
|
|
|
'percent'=>$obj->percent, |
|
513
|
|
|
|
|
514
|
|
|
'userid'=>$obj->user_id, |
|
515
|
|
|
'login'=>$obj->user_login, |
|
516
|
|
|
'userfirstname'=>$obj->user_firstname, |
|
517
|
|
|
'userlastname'=>$obj->user_lastname, |
|
518
|
|
|
'userphoto'=>$obj->user_photo, |
|
519
|
|
|
|
|
520
|
|
|
'contact_id'=>$obj->fk_contact, |
|
521
|
|
|
'socpeopleassigned' => $contactaction->socpeopleassigned, |
|
522
|
|
|
'lastname'=>$obj->lastname, |
|
523
|
|
|
'firstname'=>$obj->firstname, |
|
524
|
|
|
'fk_element'=>$obj->fk_element, |
|
525
|
|
|
'elementtype'=>$obj->elementtype, |
|
526
|
|
|
// Type of event |
|
527
|
|
|
'acode'=>$obj->acode, |
|
528
|
|
|
'alabel'=>$obj->alabel, |
|
529
|
|
|
'libelle'=>$obj->alabel, // deprecated |
|
530
|
|
|
'apicto'=>$obj->apicto |
|
531
|
|
|
); |
|
532
|
|
|
} else { |
|
533
|
|
|
$histo[$numaction] = array( |
|
534
|
|
|
'type'=>$obj->type, |
|
535
|
|
|
'tododone'=>'done', |
|
536
|
|
|
'id'=>$obj->id, |
|
537
|
|
|
'datestart'=>$db->jdate($obj->dp), |
|
538
|
|
|
'dateend'=>$db->jdate($obj->dp2), |
|
539
|
|
|
'note'=>$obj->label, |
|
540
|
|
|
'message'=>$obj->message, |
|
541
|
|
|
'percent'=>$obj->percent, |
|
542
|
|
|
'acode'=>$obj->acode, |
|
543
|
|
|
|
|
544
|
|
|
'userid'=>$obj->user_id, |
|
545
|
|
|
'login'=>$obj->user_login, |
|
546
|
|
|
'userfirstname'=>$obj->user_firstname, |
|
547
|
|
|
'userlastname'=>$obj->user_lastname, |
|
548
|
|
|
'userphoto'=>$obj->user_photo |
|
549
|
|
|
); |
|
550
|
|
|
} |
|
551
|
|
|
|
|
552
|
|
|
$numaction++; |
|
553
|
|
|
$i++; |
|
554
|
|
|
} |
|
555
|
|
|
} else { |
|
556
|
|
|
dol_print_error($db); |
|
557
|
|
|
} |
|
558
|
|
|
} |
|
559
|
|
|
|
|
560
|
|
|
// Set $out to sow events |
|
561
|
|
|
$out = ''; |
|
562
|
|
|
|
|
563
|
|
|
if (empty($conf->agenda->enabled)) { |
|
564
|
|
|
$langs->loadLangs(array("admin", "errors")); |
|
565
|
|
|
$out = info_admin($langs->trans("WarningModuleXDisabledSoYouMayMissEventHere", $langs->transnoentitiesnoconv("Module2400Name")), 0, 0, 'warning'); |
|
566
|
|
|
} |
|
567
|
|
|
|
|
568
|
|
|
if (!empty($conf->agenda->enabled) || (!empty($conf->mailing->enabled) && !empty($objcon->email))) { |
|
569
|
|
|
$delay_warning = $conf->global->MAIN_DELAY_ACTIONS_TODO * 24 * 60 * 60; |
|
570
|
|
|
|
|
571
|
|
|
require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; |
|
572
|
|
|
include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; |
|
573
|
|
|
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php'; |
|
574
|
|
|
require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; |
|
575
|
|
|
|
|
576
|
|
|
$formactions = new FormActions($db); |
|
577
|
|
|
|
|
578
|
|
|
$actionstatic = new ActionComm($db); |
|
579
|
|
|
$userstatic = new User($db); |
|
580
|
|
|
$contactstatic = new Contact($db); |
|
581
|
|
|
$userGetNomUrlCache = array(); |
|
582
|
|
|
|
|
583
|
|
|
$out .= '<div class="filters-container" >'; |
|
584
|
|
|
$out .= '<form name="listactionsfilter" class="listactionsfilter" action="'.$_SERVER["PHP_SELF"].'" method="POST">'; |
|
585
|
|
|
$out .= '<input type="hidden" name="token" value="'.newToken().'">'; |
|
586
|
|
|
|
|
587
|
|
|
if ($objcon && get_class($objcon) == 'Contact' && |
|
588
|
|
|
(is_null($filterobj) || get_class($filterobj) == 'Societe')) { |
|
589
|
|
|
$out .= '<input type="hidden" name="id" value="'.$objcon->id.'" />'; |
|
590
|
|
|
} else { |
|
591
|
|
|
$out .= '<input type="hidden" name="id" value="'.$filterobj->id.'" />'; |
|
592
|
|
|
} |
|
593
|
|
|
if ($filterobj && get_class($filterobj) == 'Societe') { |
|
594
|
|
|
$out .= '<input type="hidden" name="socid" value="'.$filterobj->id.'" />'; |
|
595
|
|
|
} |
|
596
|
|
|
|
|
597
|
|
|
$out .= "\n"; |
|
598
|
|
|
|
|
599
|
|
|
$out .= '<div class="div-table-responsive-no-min">'; |
|
600
|
|
|
$out .= '<table class="noborder borderbottom centpercent">'; |
|
601
|
|
|
|
|
602
|
|
|
$out .= '<tr class="liste_titre">'; |
|
603
|
|
|
|
|
604
|
|
|
//$out.='<td class="liste_titre">'; |
|
605
|
|
|
$out .= getTitleFieldOfList('Date', 0, $_SERVER["PHP_SELF"], 'a.datep', '', $param, '', $sortfield, $sortorder, '')."\n"; |
|
606
|
|
|
//$out.='</td>'; |
|
607
|
|
|
|
|
608
|
|
|
$out .= '<th class="liste_titre"><strong class="hideonsmartphone">'.$langs->trans("Search").' : </strong></th>'; |
|
609
|
|
|
if ($donetodo) { |
|
610
|
|
|
$out .= '<th class="liste_titre"></th>'; |
|
611
|
|
|
} |
|
612
|
|
|
$out .= '<th class="liste_titre">'.$langs->trans("Type").' '; |
|
613
|
|
|
$out .= $formactions->select_type_actions($actioncode, "actioncode", '', empty($conf->global->AGENDA_USE_EVENT_TYPE) ? 1 : -1, 0, 0, 1, 'minwidth200imp'); |
|
614
|
|
|
$out .= '</th>'; |
|
615
|
|
|
$out .= '<th class="liste_titre maxwidth100onsmartphone">'; |
|
616
|
|
|
$out .= '<input type="text" class="maxwidth100onsmartphone" name="search_agenda_label" value="'.$filters['search_agenda_label'].'" placeholder="'.$langs->trans("Label").'">'; |
|
617
|
|
|
$out .= '</th>'; |
|
618
|
|
|
|
|
619
|
|
|
$out .= '<th class="liste_titre width50 middle">'; |
|
620
|
|
|
$searchpicto = $form->showFilterAndCheckAddButtons($massactionbutton ? 1 : 0, 'checkforselect', 1); |
|
621
|
|
|
$out .= $searchpicto; |
|
622
|
|
|
$out .= '</th>'; |
|
623
|
|
|
$out .= '</tr>'; |
|
624
|
|
|
|
|
625
|
|
|
|
|
626
|
|
|
$out .= '</table>'; |
|
627
|
|
|
|
|
628
|
|
|
$out .= '</form>'; |
|
629
|
|
|
$out .= '</div>'; |
|
630
|
|
|
|
|
631
|
|
|
$out .= "\n"; |
|
632
|
|
|
|
|
633
|
|
|
$out .= '<ul class="timeline">'; |
|
634
|
|
|
|
|
635
|
|
|
if ($donetodo) { |
|
636
|
|
|
$tmp = ''; |
|
637
|
|
|
if (get_class($filterobj) == 'Societe') { |
|
638
|
|
|
$tmp .= '<a href="'.DOL_URL_ROOT.'/comm/action/list.php?action=show_list&socid='.$filterobj->id.'&status=done">'; |
|
639
|
|
|
} |
|
640
|
|
|
$tmp .= ($donetodo != 'done' ? $langs->trans("ActionsToDoShort") : ''); |
|
641
|
|
|
$tmp .= ($donetodo != 'done' && $donetodo != 'todo' ? ' / ' : ''); |
|
642
|
|
|
$tmp .= ($donetodo != 'todo' ? $langs->trans("ActionsDoneShort") : ''); |
|
643
|
|
|
//$out.=$langs->trans("ActionsToDoShort").' / '.$langs->trans("ActionsDoneShort"); |
|
644
|
|
|
if (get_class($filterobj) == 'Societe') { |
|
645
|
|
|
$tmp .= '</a>'; |
|
646
|
|
|
} |
|
647
|
|
|
$out .= getTitleFieldOfList($tmp); |
|
648
|
|
|
} |
|
649
|
|
|
|
|
650
|
|
|
|
|
651
|
|
|
//require_once DOL_DOCUMENT_ROOT.'/comm/action/class/cactioncomm.class.php'; |
|
652
|
|
|
//$caction=new CActionComm($db); |
|
653
|
|
|
//$arraylist=$caction->liste_array(1, 'code', '', (empty($conf->global->AGENDA_USE_EVENT_TYPE)?1:0), '', 1); |
|
654
|
|
|
|
|
655
|
|
|
$actualCycleDate = false; |
|
656
|
|
|
|
|
657
|
|
|
foreach ($histo as $key => $value) { |
|
658
|
|
|
$actionstatic->fetch($histo[$key]['id']); // TODO Do we need this, we already have a lot of data of line into $histo |
|
659
|
|
|
|
|
660
|
|
|
$actionstatic->type_picto = $histo[$key]['apicto']; |
|
661
|
|
|
$actionstatic->type_code = $histo[$key]['acode']; |
|
662
|
|
|
|
|
663
|
|
|
$url = DOL_URL_ROOT.'/comm/action/card.php?id='.$histo[$key]['id']; |
|
664
|
|
|
|
|
665
|
|
|
$tmpa = dol_getdate($histo[$key]['datestart'], false); |
|
666
|
|
|
if ($actualCycleDate !== $tmpa['year'].'-'.$tmpa['yday']) { |
|
667
|
|
|
$actualCycleDate = $tmpa['year'].'-'.$tmpa['yday']; |
|
668
|
|
|
$out .= '<!-- timeline time label -->'; |
|
669
|
|
|
$out .= '<li class="time-label">'; |
|
670
|
|
|
$out .= '<span class="timeline-badge-date">'; |
|
671
|
|
|
$out .= dol_print_date($histo[$key]['datestart'], 'daytext', 'tzuserrel', $langs); |
|
672
|
|
|
$out .= '</span>'; |
|
673
|
|
|
$out .= '</li>'; |
|
674
|
|
|
$out .= '<!-- /.timeline-label -->'; |
|
675
|
|
|
} |
|
676
|
|
|
|
|
677
|
|
|
|
|
678
|
|
|
$out .= '<!-- timeline item -->'."\n"; |
|
679
|
|
|
$out .= '<li class="timeline-code-'.strtolower($actionstatic->code).'">'; |
|
680
|
|
|
|
|
681
|
|
|
$out .= getTicketTimelineIcon($actionstatic, $histo, $key); |
|
682
|
|
|
|
|
683
|
|
|
$out .= '<div class="timeline-item">'."\n"; |
|
684
|
|
|
|
|
685
|
|
|
$out .= '<span class="timeline-header-action">'; |
|
686
|
|
|
|
|
687
|
|
|
if (isset($histo[$key]['type']) && $histo[$key]['type'] == 'mailing') { |
|
688
|
|
|
$out .= '<a class="timeline-btn" href="'.DOL_URL_ROOT.'/comm/mailing/card.php?id='.$histo[$key]['id'].'">'.img_object($langs->trans("ShowEMailing"), "email").' '; |
|
689
|
|
|
$out .= $histo[$key]['id']; |
|
690
|
|
|
$out .= '</a> '; |
|
691
|
|
|
} else { |
|
692
|
|
|
$out .= $actionstatic->getNomUrl(1, -1, 'valignmiddle').' '; |
|
693
|
|
|
} |
|
694
|
|
|
|
|
695
|
|
|
//if ($user->rights->agenda->allactions->read || $actionstatic->authorid == $user->id) |
|
696
|
|
|
//{ |
|
697
|
|
|
// $out.='<a href="'.$url.'" class="timeline-btn" title="'.$langs->trans('Show').'" ><i class="fa fa-calendar" ></i>'.$langs->trans('Show').'</a>'; |
|
698
|
|
|
//} |
|
699
|
|
|
|
|
700
|
|
|
if ($user->rights->agenda->allactions->create || |
|
701
|
|
|
(($actionstatic->authorid == $user->id || $actionstatic->userownerid == $user->id) && $user->rights->agenda->myactions->create)) { |
|
702
|
|
|
$out .= '<a class="timeline-btn" href="'.DOL_MAIN_URL_ROOT.'/comm/action/card.php?action=edit&id='.$actionstatic->id.'"><i class="fa fa-pencil" title="'.$langs->trans("Modify").'" ></i></a>'; |
|
703
|
|
|
} |
|
704
|
|
|
|
|
705
|
|
|
$out .= '</span>'; |
|
706
|
|
|
// Date |
|
707
|
|
|
$out .= '<span class="time"><i class="fa fa-clock-o"></i> '; |
|
708
|
|
|
$out .= dol_print_date($histo[$key]['datestart'], 'dayhour', 'tzuserrel'); |
|
709
|
|
|
if ($histo[$key]['dateend'] && $histo[$key]['dateend'] != $histo[$key]['datestart']) { |
|
710
|
|
|
$tmpa = dol_getdate($histo[$key]['datestart'], true); |
|
711
|
|
|
$tmpb = dol_getdate($histo[$key]['dateend'], true); |
|
712
|
|
|
if ($tmpa['mday'] == $tmpb['mday'] && $tmpa['mon'] == $tmpb['mon'] && $tmpa['year'] == $tmpb['year']) { |
|
713
|
|
|
$out .= '-'.dol_print_date($histo[$key]['dateend'], 'hour', 'tzuserrel'); |
|
714
|
|
|
} else { |
|
715
|
|
|
$out .= '-'.dol_print_date($histo[$key]['dateend'], 'dayhour', 'tzuserrel'); |
|
716
|
|
|
} |
|
717
|
|
|
} |
|
718
|
|
|
$late = 0; |
|
719
|
|
|
if ($histo[$key]['percent'] == 0 && $histo[$key]['datestart'] && $histo[$key]['datestart'] < ($now - $delay_warning)) { |
|
720
|
|
|
$late = 1; |
|
721
|
|
|
} |
|
722
|
|
|
if ($histo[$key]['percent'] == 0 && !$histo[$key]['datestart'] && $histo[$key]['dateend'] && $histo[$key]['datestart'] < ($now - $delay_warning)) { |
|
723
|
|
|
$late = 1; |
|
724
|
|
|
} |
|
725
|
|
|
if ($histo[$key]['percent'] > 0 && $histo[$key]['percent'] < 100 && $histo[$key]['dateend'] && $histo[$key]['dateend'] < ($now - $delay_warning)) { |
|
726
|
|
|
$late = 1; |
|
727
|
|
|
} |
|
728
|
|
|
if ($histo[$key]['percent'] > 0 && $histo[$key]['percent'] < 100 && !$histo[$key]['dateend'] && $histo[$key]['datestart'] && $histo[$key]['datestart'] < ($now - $delay_warning)) { |
|
729
|
|
|
$late = 1; |
|
730
|
|
|
} |
|
731
|
|
|
if ($late) { |
|
732
|
|
|
$out .= img_warning($langs->trans("Late")).' '; |
|
733
|
|
|
} |
|
734
|
|
|
$out .= "</span>\n"; |
|
735
|
|
|
|
|
736
|
|
|
// Ref |
|
737
|
|
|
$out .= '<h3 class="timeline-header">'; |
|
738
|
|
|
|
|
739
|
|
|
// Author of event |
|
740
|
|
|
$out .= '<span class="messaging-author">'; |
|
741
|
|
|
if ($histo[$key]['userid'] > 0) { |
|
742
|
|
|
if (!isset($userGetNomUrlCache[$histo[$key]['userid']])) { // is in cache ? |
|
743
|
|
|
$userstatic->fetch($histo[$key]['userid']); |
|
744
|
|
|
$userGetNomUrlCache[$histo[$key]['userid']] = $userstatic->getNomUrl(-1, '', 0, 0, 16, 0, 'firstelselast', ''); |
|
745
|
|
|
} |
|
746
|
|
|
$out .= $userGetNomUrlCache[$histo[$key]['userid']]; |
|
747
|
|
|
} |
|
748
|
|
|
$out .= '</span>'; |
|
749
|
|
|
|
|
750
|
|
|
// Title |
|
751
|
|
|
$out .= ' <span class="messaging-title">'; |
|
752
|
|
|
|
|
753
|
|
|
if ($actionstatic->code == 'TICKET_MSG') { |
|
754
|
|
|
$out .= $langs->trans('TicketNewMessage'); |
|
755
|
|
|
} elseif ($actionstatic->code == 'TICKET_MSG_PRIVATE') { |
|
756
|
|
|
$out .= $langs->trans('TicketNewMessage').' <em>('.$langs->trans('Private').')</em>'; |
|
757
|
|
|
} else { |
|
758
|
|
|
if (isset($histo[$key]['type']) && $histo[$key]['type'] == 'action') { |
|
759
|
|
|
$transcode = $langs->trans("Action".$histo[$key]['acode']); |
|
760
|
|
|
$libelle = ($transcode != "Action".$histo[$key]['acode'] ? $transcode : $histo[$key]['alabel']); |
|
761
|
|
|
$libelle = $histo[$key]['note']; |
|
762
|
|
|
$actionstatic->id = $histo[$key]['id']; |
|
763
|
|
|
$out .= dol_trunc($libelle, 120); |
|
764
|
|
|
} |
|
765
|
|
|
if (isset($histo[$key]['type']) && $histo[$key]['type'] == 'mailing') { |
|
766
|
|
|
$out .= '<a href="'.DOL_URL_ROOT.'/comm/mailing/card.php?id='.$histo[$key]['id'].'">'.img_object($langs->trans("ShowEMailing"), "email").' '; |
|
767
|
|
|
$transcode = $langs->trans("Action".$histo[$key]['acode']); |
|
768
|
|
|
$libelle = ($transcode != "Action".$histo[$key]['acode'] ? $transcode : 'Send mass mailing'); |
|
769
|
|
|
$out .= dol_trunc($libelle, 120); |
|
770
|
|
|
} |
|
771
|
|
|
} |
|
772
|
|
|
|
|
773
|
|
|
$out .= '</span>'; |
|
774
|
|
|
|
|
775
|
|
|
$out .= '</h3>'; |
|
776
|
|
|
|
|
777
|
|
|
if (!empty($histo[$key]['message']) |
|
778
|
|
|
&& $actionstatic->code != 'AC_TICKET_CREATE' |
|
779
|
|
|
&& $actionstatic->code != 'AC_TICKET_MODIFY' |
|
780
|
|
|
) { |
|
781
|
|
|
$out .= '<div class="timeline-body">'; |
|
782
|
|
|
$out .= $histo[$key]['message']; |
|
783
|
|
|
$out .= '</div>'; |
|
784
|
|
|
} |
|
785
|
|
|
|
|
786
|
|
|
// Timeline footer |
|
787
|
|
|
$footer = ''; |
|
788
|
|
|
|
|
789
|
|
|
// Contact for this action |
|
790
|
|
|
if (isset($histo[$key]['socpeopleassigned']) && is_array($histo[$key]['socpeopleassigned']) && count($histo[$key]['socpeopleassigned']) > 0) { |
|
791
|
|
|
$contactList = ''; |
|
792
|
|
|
foreach ($histo[$key]['socpeopleassigned'] as $cid => $Tab) { |
|
793
|
|
|
$contact = new Contact($db); |
|
794
|
|
|
$result = $contact->fetch($cid); |
|
795
|
|
|
|
|
796
|
|
|
if ($result < 0) { |
|
797
|
|
|
dol_print_error($db, $contact->error); |
|
798
|
|
|
} |
|
799
|
|
|
|
|
800
|
|
|
if ($result > 0) { |
|
801
|
|
|
$contactList .= !empty($contactList) ? ', ' : ''; |
|
802
|
|
|
$contactList .= $contact->getNomUrl(1); |
|
803
|
|
|
if (isset($histo[$key]['acode']) && $histo[$key]['acode'] == 'AC_TEL') { |
|
804
|
|
|
if (!empty($contact->phone_pro)) { |
|
805
|
|
|
$contactList .= '('.dol_print_phone($contact->phone_pro).')'; |
|
806
|
|
|
} |
|
807
|
|
|
} |
|
808
|
|
|
} |
|
809
|
|
|
} |
|
810
|
|
|
|
|
811
|
|
|
$footer .= $langs->trans('ActionOnContact').' : '.$contactList; |
|
812
|
|
|
} elseif (empty($objcon->id) && isset($histo[$key]['contact_id']) && $histo[$key]['contact_id'] > 0) { |
|
813
|
|
|
$contact = new Contact($db); |
|
814
|
|
|
$result = $contact->fetch($histo[$key]['contact_id']); |
|
815
|
|
|
|
|
816
|
|
|
if ($result < 0) { |
|
817
|
|
|
dol_print_error($db, $contact->error); |
|
818
|
|
|
} |
|
819
|
|
|
|
|
820
|
|
|
if ($result > 0) { |
|
821
|
|
|
$footer .= $contact->getNomUrl(1); |
|
822
|
|
|
if (isset($histo[$key]['acode']) && $histo[$key]['acode'] == 'AC_TEL') { |
|
823
|
|
|
if (!empty($contact->phone_pro)) { |
|
824
|
|
|
$footer .= '('.dol_print_phone($contact->phone_pro).')'; |
|
825
|
|
|
} |
|
826
|
|
|
} |
|
827
|
|
|
} |
|
828
|
|
|
} |
|
829
|
|
|
|
|
830
|
|
|
$documents = getTicketActionCommEcmList($actionstatic); |
|
831
|
|
|
if (!empty($documents)) { |
|
832
|
|
|
$footer .= '<div class="timeline-documents-container">'; |
|
833
|
|
|
foreach ($documents as $doc) { |
|
834
|
|
|
$footer .= '<span id="document_'.$doc->id.'" class="timeline-documents" '; |
|
835
|
|
|
$footer .= ' data-id="'.$doc->id.'" '; |
|
836
|
|
|
$footer .= ' data-path="'.$doc->filepath.'"'; |
|
837
|
|
|
$footer .= ' data-filename="'.dol_escape_htmltag($doc->filename).'" '; |
|
838
|
|
|
$footer .= '>'; |
|
839
|
|
|
|
|
840
|
|
|
$filePath = DOL_DATA_ROOT.'/'.$doc->filepath.'/'.$doc->filename; |
|
841
|
|
|
$mime = dol_mimetype($filePath); |
|
842
|
|
|
$file = $actionstatic->id.'/'.$doc->filename; |
|
843
|
|
|
$thumb = $actionstatic->id.'/thumbs/'.substr($doc->filename, 0, strrpos($doc->filename, '.')).'_mini'.substr($doc->filename, strrpos($doc->filename, '.')); |
|
844
|
|
|
$doclink = dol_buildpath('document.php', 1).'?modulepart=actions&attachment=0&file='.urlencode($file).'&entity='.$conf->entity; |
|
845
|
|
|
$viewlink = dol_buildpath('viewimage.php', 1).'?modulepart=actions&file='.urlencode($thumb).'&entity='.$conf->entity; |
|
846
|
|
|
|
|
847
|
|
|
$mimeAttr = ' mime="'.$mime.'" '; |
|
848
|
|
|
$class = ''; |
|
849
|
|
|
if (in_array($mime, array('image/png', 'image/jpeg', 'application/pdf'))) { |
|
850
|
|
|
$class .= ' documentpreview'; |
|
851
|
|
|
} |
|
852
|
|
|
|
|
853
|
|
|
$footer .= '<a href="'.$doclink.'" class="btn-link '.$class.'" target="_blank" '.$mimeAttr.' >'; |
|
854
|
|
|
$footer .= img_mime($filePath).' '.$doc->filename; |
|
855
|
|
|
$footer .= '</a>'; |
|
856
|
|
|
|
|
857
|
|
|
$footer .= '</span>'; |
|
858
|
|
|
} |
|
859
|
|
|
$footer .= '</div>'; |
|
860
|
|
|
} |
|
861
|
|
|
|
|
862
|
|
|
if (!empty($footer)) { |
|
863
|
|
|
$out .= '<div class="timeline-footer">'.$footer.'</div>'; |
|
864
|
|
|
} |
|
865
|
|
|
|
|
866
|
|
|
$out .= '</div>'."\n"; // end timeline-item |
|
867
|
|
|
|
|
868
|
|
|
$out .= '</li>'; |
|
869
|
|
|
$out .= '<!-- END timeline item -->'; |
|
870
|
|
|
|
|
871
|
|
|
$i++; |
|
|
|
|
|
|
872
|
|
|
} |
|
873
|
|
|
$out .= "</ul>\n"; |
|
874
|
|
|
} |
|
875
|
|
|
|
|
876
|
|
|
if ($noprint) { |
|
877
|
|
|
return $out; |
|
878
|
|
|
} else { |
|
879
|
|
|
print $out; |
|
880
|
|
|
} |
|
881
|
|
|
} |
|
882
|
|
|
|
|
883
|
|
|
/** |
|
884
|
|
|
* Get timeline icon |
|
885
|
|
|
* @param ActionComm $actionstatic actioncomm |
|
886
|
|
|
* @param array $histo histo |
|
887
|
|
|
* @param int $key key |
|
888
|
|
|
* @return string |
|
889
|
|
|
*/ |
|
890
|
|
|
function getTicketTimelineIcon($actionstatic, &$histo, $key) |
|
891
|
|
|
{ |
|
892
|
|
|
global $conf, $langs; |
|
893
|
|
|
$out = '<!-- timeline icon -->'."\n"; |
|
894
|
|
|
$iconClass = 'fa fa-comments'; |
|
895
|
|
|
$img_picto = ''; |
|
896
|
|
|
$colorClass = ''; |
|
897
|
|
|
$pictoTitle = ''; |
|
898
|
|
|
|
|
899
|
|
|
if ($histo[$key]['percent'] == -1) { |
|
900
|
|
|
$colorClass = 'timeline-icon-not-applicble'; |
|
901
|
|
|
$pictoTitle = $langs->trans('StatusNotApplicable'); |
|
902
|
|
|
} elseif ($histo[$key]['percent'] == 0) { |
|
903
|
|
|
$colorClass = 'timeline-icon-todo'; |
|
904
|
|
|
$pictoTitle = $langs->trans('StatusActionToDo').' (0%)'; |
|
905
|
|
|
} elseif ($histo[$key]['percent'] > 0 && $histo[$key]['percent'] < 100) { |
|
906
|
|
|
$colorClass = 'timeline-icon-in-progress'; |
|
907
|
|
|
$pictoTitle = $langs->trans('StatusActionInProcess').' ('.$histo[$key]['percent'].'%)'; |
|
908
|
|
|
} elseif ($histo[$key]['percent'] >= 100) { |
|
909
|
|
|
$colorClass = 'timeline-icon-done'; |
|
910
|
|
|
$pictoTitle = $langs->trans('StatusActionDone').' (100%)'; |
|
911
|
|
|
} |
|
912
|
|
|
|
|
913
|
|
|
if ($actionstatic->code == 'AC_TICKET_CREATE') { |
|
914
|
|
|
$iconClass = 'fa fa-ticket'; |
|
915
|
|
|
} elseif ($actionstatic->code == 'AC_TICKET_MODIFY') { |
|
916
|
|
|
$iconClass = 'fa fa-pencilxxx'; |
|
917
|
|
|
} elseif ($actionstatic->code == 'TICKET_MSG') { |
|
918
|
|
|
$iconClass = 'fa fa-comments'; |
|
919
|
|
|
} elseif ($actionstatic->code == 'TICKET_MSG_PRIVATE') { |
|
920
|
|
|
$iconClass = 'fa fa-mask'; |
|
921
|
|
|
} elseif (!empty($conf->global->AGENDA_USE_EVENT_TYPE)) { |
|
922
|
|
|
if ($actionstatic->type_picto) { |
|
923
|
|
|
$img_picto = img_picto('', $actionstatic->type_picto); |
|
924
|
|
|
} else { |
|
925
|
|
|
if ($actionstatic->type_code == 'AC_RDV') { |
|
926
|
|
|
$iconClass = 'fa fa-handshake'; |
|
927
|
|
|
} elseif ($actionstatic->type_code == 'AC_TEL') { |
|
928
|
|
|
$iconClass = 'fa fa-phone'; |
|
929
|
|
|
} elseif ($actionstatic->type_code == 'AC_FAX') { |
|
930
|
|
|
$iconClass = 'fa fa-fax'; |
|
931
|
|
|
} elseif ($actionstatic->type_code == 'AC_EMAIL') { |
|
932
|
|
|
$iconClass = 'fa fa-envelope'; |
|
933
|
|
|
} elseif ($actionstatic->type_code == 'AC_INT') { |
|
934
|
|
|
$iconClass = 'fa fa-shipping-fast'; |
|
935
|
|
|
} elseif ($actionstatic->type_code == 'AC_OTH_AUTO') { |
|
936
|
|
|
$iconClass = 'fa fa-robot'; |
|
937
|
|
|
} elseif (!preg_match('/_AUTO/', $actionstatic->type_code)) { |
|
938
|
|
|
$iconClass = 'fa fa-robot'; |
|
939
|
|
|
} |
|
940
|
|
|
} |
|
941
|
|
|
} |
|
942
|
|
|
|
|
943
|
|
|
$out .= '<i class="'.$iconClass.' '.$colorClass.'" title="'.$pictoTitle.'">'.$img_picto.'</i>'."\n"; |
|
944
|
|
|
return $out; |
|
945
|
|
|
} |
|
946
|
|
|
|
|
947
|
|
|
/** |
|
948
|
|
|
* getTicketActionCommEcmList |
|
949
|
|
|
* |
|
950
|
|
|
* @param ActionComm $object Object ActionComm |
|
951
|
|
|
* @return array Array of documents in index table |
|
952
|
|
|
*/ |
|
953
|
|
|
function getTicketActionCommEcmList($object) |
|
954
|
|
|
{ |
|
955
|
|
|
global $conf, $db; |
|
956
|
|
|
|
|
957
|
|
|
$documents = array(); |
|
958
|
|
|
|
|
959
|
|
|
$sql = 'SELECT ecm.rowid as id, ecm.src_object_type, ecm.src_object_id, ecm.filepath, ecm.filename'; |
|
960
|
|
|
$sql .= ' FROM '.MAIN_DB_PREFIX.'ecm_files ecm'; |
|
961
|
|
|
$sql .= ' WHERE ecm.filepath = \'agenda/'.$object->id.'\''; |
|
962
|
|
|
//$sql.= ' ecm.src_object_type = \''.$object->element.'\' AND ecm.src_object_id = '.$object->id; // Actually upload file doesn't add type |
|
963
|
|
|
$sql .= ' ORDER BY ecm.position ASC'; |
|
964
|
|
|
|
|
965
|
|
|
$resql = $db->query($sql); |
|
966
|
|
|
if ($resql) { |
|
967
|
|
|
if ($db->num_rows($resql)) { |
|
968
|
|
|
while ($obj = $db->fetch_object($resql)) { |
|
969
|
|
|
$documents[$obj->id] = $obj; |
|
970
|
|
|
} |
|
971
|
|
|
} |
|
972
|
|
|
} |
|
973
|
|
|
|
|
974
|
|
|
return $documents; |
|
975
|
|
|
} |
|
976
|
|
|
|