dolibarr  9.0.0
actions_massactions.inc.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2015-2017 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com>
4  * Copyright (C) 2018 Juanjo Menent <jmenent@2byte.es>
5  * Copyright (C) 2019 Ferran Marcet <fmarcet@2byte.es>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  * or see http://www.gnu.org/
20  */
21 
28 // $massaction must be defined
29 // $objectclass and $objectlabel must be defined
30 // $parameters, $object, $action must be defined for the hook.
31 
32 // $permtoread, $permtocreate and $permtodelete may be defined
33 // $uploaddir may be defined (example to $conf->projet->dir_output."/";)
34 // $toselect may be defined
35 
36 
37 // Protection
38 if (empty($objectclass) || empty($uploaddir))
39 {
40  dol_print_error(null, 'include of actions_massactions.inc.php is done but var $massaction or $objectclass or $uploaddir was not defined');
41  exit;
42 }
43 
44 
45 // Mass actions. Controls on number of lines checked.
46 $maxformassaction=(empty($conf->global->MAIN_LIMIT_FOR_MASS_ACTIONS)?1000:$conf->global->MAIN_LIMIT_FOR_MASS_ACTIONS);
47 if (! empty($massaction) && count($toselect) < 1)
48 {
49  $error++;
50  setEventMessages($langs->trans("NoRecordSelected"), null, "warnings");
51 }
52 if (! $error && is_array($toselect) && count($toselect) > $maxformassaction)
53 {
54  setEventMessages($langs->trans('TooManyRecordForMassAction',$maxformassaction), null, 'errors');
55  $error++;
56 }
57 
58 if (! $error && $massaction == 'confirm_presend' && ! GETPOST('sendmail')) // If we do not choose button send (for example when we change template or limit), we must not send email, but keep on send email form
59 {
60  $massaction='presend';
61 }
62 if (! $error && $massaction == 'confirm_presend')
63 {
64  $resaction = '';
65  $nbsent = 0;
66  $nbignored = 0;
67  $langs->load("mails");
68  include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
69 
70  $listofobjectid=array();
71  $listofobjectthirdparties=array();
72  $listofobjectref=array();
73 
74  if (! $error)
75  {
76  $thirdparty=new Societe($db);
77 
78  $objecttmp=new $objectclass($db);
79  if ($objecttmp->element == 'expensereport') $thirdparty=new User($db);
80  if ($objecttmp->element == 'holiday') $thirdparty=new User($db);
81 
82  foreach($toselect as $toselectid)
83  {
84  $objecttmp=new $objectclass($db); // we must create new instance because instance is saved into $listofobjectref array for future use
85  $result=$objecttmp->fetch($toselectid);
86  if ($result > 0)
87  {
88  $listofobjectid[$toselectid]=$toselectid;
89 
90  $thirdpartyid=($objecttmp->fk_soc?$objecttmp->fk_soc:$objecttmp->socid);
91  if ($objecttmp->element == 'societe') $thirdpartyid=$objecttmp->id;
92  if ($objecttmp->element == 'expensereport') $thirdpartyid=$objecttmp->fk_user_author;
93  if ($objecttmp->element == 'holiday') $thirdpartyid=$objecttmp->fk_user;
94  if (empty($thirdpartyid)) $thirdpartyid=0;
95 
96  $listofobjectthirdparties[$thirdpartyid]=$thirdpartyid;
97  $listofobjectref[$thirdpartyid][$toselectid]=$objecttmp;
98  }
99  }
100  }
101 
102  // Check mandatory parameters
103  if (GETPOST('fromtype','alpha') === 'user' && empty($user->email))
104  {
105  $error++;
106  setEventMessages($langs->trans("NoSenderEmailDefined"), null, 'warnings');
107  $massaction='presend';
108  }
109 
110  $receiver=$_POST['receiver'];
111  if (! is_array($receiver))
112  {
113  if (empty($receiver) || $receiver == '-1') $receiver=array();
114  else $receiver=array($receiver);
115  }
116  if (! trim($_POST['sendto']) && count($receiver) == 0 && count($listofobjectthirdparties) == 1) // if only one recipient, receiver is mandatory
117  {
118  $error++;
119  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Recipient")), null, 'warnings');
120  $massaction='presend';
121  }
122 
123  if (! GETPOST('subject','none'))
124  {
125  $error++;
126  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("MailTopic")), null, 'warnings');
127  $massaction='presend';
128  }
129 
130  // Loop on each recipient/thirdparty
131  if (! $error)
132  {
133  foreach ($listofobjectthirdparties as $thirdpartyid)
134  {
135  $result = $thirdparty->fetch($thirdpartyid);
136  if ($result < 0)
137  {
138  dol_print_error($db);
139  exit;
140  }
141 
142  $sendto='';
143  $sendtocc='';
144  $sendtobcc='';
145  $sendtoid = array();
146 
147  // Define $sendto
148  $tmparray=array();
149  if (trim($_POST['sendto']))
150  {
151  // Recipients are provided into free text
152  $tmparray[] = trim($_POST['sendto']);
153  }
154  if (count($receiver)>0)
155  {
156  foreach($receiver as $key=>$val)
157  {
158  // Recipient was provided from combo list
159  if ($val == 'thirdparty') // Id of third party or user
160  {
161  $tmparray[] = $thirdparty->name.' <'.$thirdparty->email.'>';
162  }
163  elseif ($val && method_exists($thirdparty, 'contact_get_property')) // Id of contact
164  {
165  $tmparray[] = $thirdparty->contact_get_property((int) $val,'email');
166  $sendtoid[] = $val;
167  }
168  }
169  }
170  $sendto=implode(',',$tmparray);
171 
172  // Define $sendtocc
173  $receivercc=$_POST['receivercc'];
174  if (! is_array($receivercc))
175  {
176  if ($receivercc == '-1') $receivercc=array();
177  else $receivercc=array($receivercc);
178  }
179  $tmparray=array();
180  if (trim($_POST['sendtocc']))
181  {
182  $tmparray[] = trim($_POST['sendtocc']);
183  }
184  if (count($receivercc) > 0)
185  {
186  foreach($receivercc as $key=>$val)
187  {
188  // Recipient was provided from combo list
189  if ($val == 'thirdparty') // Id of third party
190  {
191  $tmparray[] = $thirdparty->name.' <'.$thirdparty->email.'>';
192  }
193  elseif ($val) // Id du contact
194  {
195  $tmparray[] = $thirdparty->contact_get_property((int) $val,'email');
196  //$sendtoid[] = $val; TODO Add also id of contact in CC ?
197  }
198  }
199  }
200  $sendtocc=implode(',',$tmparray);
201 
202  //var_dump($listofobjectref);exit;
203  $attachedfiles=array('paths'=>array(), 'names'=>array(), 'mimes'=>array());
204  $listofqualifiedobj=array();
205  $listofqualifiedref=array();
206  $thirdpartywithoutemail=array();
207 
208  foreach($listofobjectref[$thirdpartyid] as $objectid => $objectobj)
209  {
210  //var_dump($thirdpartyid.' - '.$objectid.' - '.$objectobj->statut);
211  if ($objectclass == 'Propal' && $objectobj->statut == Propal::STATUS_DRAFT)
212  {
213  $langs->load("errors");
214  $nbignored++;
215  $resaction.='<div class="error">'.$langs->trans('ErrorOnlyProposalNotDraftCanBeSentInMassAction',$objectobj->ref).'</div><br>';
216  continue; // Payment done or started or canceled
217  }
218  if ($objectclass == 'Commande' && $objectoj->statut == Commande::STATUS_DRAFT)
219  {
220  $langs->load("errors");
221  $nbignored++;
222  $resaction.='<div class="error">'.$langs->trans('ErrorOnlyOrderNotDraftCanBeSentInMassAction',$objectobj->ref).'</div><br>';
223  continue;
224  }
225  if ($objectclass == 'Facture' && $objectobj->statut == Facture::STATUS_DRAFT)
226  {
227  $langs->load("errors");
228  $nbignored++;
229  $resaction.='<div class="error">'.$langs->trans('ErrorOnlyInvoiceValidatedCanBeSentInMassAction',$objectobj->ref).'</div><br>';
230  continue; // Payment done or started or canceled
231  }
232 
233  // Test recipient
234  if (empty($sendto)) // For the case, no recipient were set (multi thirdparties send)
235  {
236  if ($objectobj->element == 'expensereport')
237  {
238  $fuser = new User($db);
239  $fuser->fetch($objectobj->fk_user_author);
240  $sendto = $fuser->email;
241  }
242  elseif ($objectobj->element == 'holiday')
243  {
244  $fuser = new User($db);
245  $fuser->fetch($objectobj->fk_user);
246  $sendto = $fuser->email;
247  }
248  else
249  {
250  $objectobj->fetch_thirdparty();
251  $sendto = $objectobj->thirdparty->email;
252  }
253  }
254 
255  if (empty($sendto))
256  {
257  //print "No recipient for thirdparty ".$objectobj->thirdparty->name;
258  $nbignored++;
259  if (empty($thirdpartywithoutemail[$objectobj->thirdparty->id]))
260  {
261  $resaction.='<div class="error">'.$langs->trans('NoRecipientEmail',$objectobj->thirdparty->name).'</div><br>';
262  }
263  dol_syslog('No recipient for thirdparty: '.$objectobj->thirdparty->name, LOG_WARNING);
264  $thirdpartywithoutemail[$objectobj->thirdparty->id]=1;
265  continue;
266  }
267 
268  if ($_POST['addmaindocfile'])
269  {
270  // TODO Use future field $objectobj->fullpathdoc to know where is stored default file
271  // TODO If not defined, use $objectobj->modelpdf (or defaut invoice config) to know what is template to use to regenerate doc.
272  $filename=dol_sanitizeFileName($objectobj->ref).'.pdf';
273  $filedir=$uploaddir . '/' . dol_sanitizeFileName($objectobj->ref);
274  $file = $filedir . '/' . $filename;
275  $mime = dol_mimetype($file);
276 
277  if (dol_is_file($file))
278  {
279  // Create form object
280  $attachedfiles=array(
281  'paths'=>array_merge($attachedfiles['paths'],array($file)),
282  'names'=>array_merge($attachedfiles['names'],array($filename)),
283  'mimes'=>array_merge($attachedfiles['mimes'],array($mime))
284  );
285  }
286  else
287  {
288  $nbignored++;
289  $langs->load("errors");
290  $resaction.='<div class="error">'.$langs->trans('ErrorCantReadFile',$file).'</div><br>';
291  dol_syslog('Failed to read file: '.$file, LOG_WARNING);
292  continue;
293  }
294  }
295 
296  // Object of thirdparty qualified, we add it
297  $listofqualifiedobj[$objectid]=$objectobj;
298  $listofqualifiedref[$objectid]=$objectobj->ref;
299 
300  //var_dump($listofqualifiedref);
301  }
302 
303  // Send email if there is at least one qualified object for current thirdparty
304  if (count($listofqualifiedobj) > 0)
305  {
306  $langs->load("commercial");
307 
308  $fromtype = GETPOST('fromtype');
309  if ($fromtype === 'user') {
310  $from = $user->getFullName($langs) .' <'.$user->email.'>';
311  }
312  elseif ($fromtype === 'company') {
313  $from = $conf->global->MAIN_INFO_SOCIETE_NOM .' <'.$conf->global->MAIN_INFO_SOCIETE_MAIL.'>';
314  }
315  elseif (preg_match('/user_aliases_(\d+)/', $fromtype, $reg)) {
316  $tmp=explode(',', $user->email_aliases);
317  $from = trim($tmp[($reg[1] - 1)]);
318  }
319  elseif (preg_match('/global_aliases_(\d+)/', $fromtype, $reg)) {
320  $tmp=explode(',', $conf->global->MAIN_INFO_SOCIETE_MAIL_ALIASES);
321  $from = trim($tmp[($reg[1] - 1)]);
322  }
323  elseif (preg_match('/senderprofile_(\d+)_(\d+)/', $fromtype, $reg)) {
324  $sql='SELECT rowid, label, email FROM '.MAIN_DB_PREFIX.'c_email_senderprofile WHERE rowid = '.(int) $reg[1];
325  $resql = $db->query($sql);
326  $obj = $db->fetch_object($resql);
327  if ($obj)
328  {
329  $from = $obj->label.' <'.$obj->email.'>';
330  }
331  }
332  else {
333  $from = $_POST['fromname'] . ' <' . $_POST['frommail'] .'>';
334  }
335 
336  $replyto = $from;
337  $subject = GETPOST('subject','none');
338  $message = GETPOST('message','none');
339 
340  $sendtobcc = GETPOST('sendtoccc');
341  if ($objectclass == 'Propal') $sendtobcc .= (empty($conf->global->MAIN_MAIL_AUTOCOPY_PROPOSAL_TO) ? '' : (($sendtobcc?", ":"").$conf->global->MAIN_MAIL_AUTOCOPY_PROPOSAL_TO));
342  if ($objectclass == 'Commande') $sendtobcc .= (empty($conf->global->MAIN_MAIL_AUTOCOPY_ORDER_TO) ? '' : (($sendtobcc?", ":"").$conf->global->MAIN_MAIL_AUTOCOPY_ORDER_TO));
343  if ($objectclass == 'Facture') $sendtobcc .= (empty($conf->global->MAIN_MAIL_AUTOCOPY_INVOICE_TO) ? '' : (($sendtobcc?", ":"").$conf->global->MAIN_MAIL_AUTOCOPY_INVOICE_TO));
344  if ($objectclass == 'Supplier_Proposal') $sendtobcc .= (empty($conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_PROPOSAL_TO) ? '' : (($sendtobcc?", ":"").$conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_PROPOSAL_TO));
345  if ($objectclass == 'CommandeFournisseur') $sendtobcc .= (empty($conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_ORDER_TO) ? '' : (($sendtobcc?", ":"").$conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_ORDER_TO));
346  if ($objectclass == 'FactureFournisseur') $sendtobcc .= (empty($conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_INVOICE_TO) ? '' : (($sendtobcc?", ":"").$conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_INVOICE_TO));
347 
348  // $listofqualifiedobj is array with key = object id and value is instance of qualified objects, for the current thirdparty (but thirdparty property is not loaded yet)
349  // $looparray will be an array with number of email to send for the current thirdparty (so 1 or n if n object for same thirdparty)
350  $oneemailperrecipient=(GETPOST('oneemailperrecipient','alpha')=='on'?1:0);
351  $looparray=array();
352  if (! $oneemailperrecipient)
353  {
354  $looparray = $listofqualifiedobj;
355  foreach ($looparray as $key => $objecttmp)
356  {
357  $looparray[$key]->thirdparty = $thirdparty; // Force thirdparty on object
358  }
359  }
360  else
361  {
362  $objectforloop=new $objectclass($db);
363  $objectforloop->thirdparty = $thirdparty; // Force thirdparty on object (even if object was not loaded)
364  $looparray[0]=$objectforloop;
365  }
366  //var_dump($looparray);exit;
367  dol_syslog("We have set an array of ".count($looparray)." emails to send");
368 
369  foreach ($looparray as $objectid => $objecttmp) // $objecttmp is a real object or an empty object if we choose to send one email per thirdparty instead of one per object
370  {
371  // Make substitution in email content
372  $substitutionarray=getCommonSubstitutionArray($langs, 0, null, $objecttmp);
373  $substitutionarray['__ID__'] = ($oneemailperrecipient ? join(', ',array_keys($listofqualifiedobj)) : $objecttmp->id);
374  $substitutionarray['__REF__'] = ($oneemailperrecipient ? join(', ',$listofqualifiedref) : $objecttmp->ref);
375  $substitutionarray['__EMAIL__'] = $thirdparty->email;
376  $substitutionarray['__CHECK_READ__'] = '<img src="'.DOL_MAIN_URL_ROOT.'/public/emailing/mailing-read.php?tag='.$thirdparty->tag.'&securitykey='.urlencode($conf->global->MAILING_EMAIL_UNSUBSCRIBE_KEY).'" width="1" height="1" style="width:1px;height:1px" border="0"/>';
377 
378  $parameters=array('mode'=>'formemail');
379 
380  if ( ! empty( $listofobjectthirdparties ) ) {
381  $parameters['listofobjectthirdparties'] = $listofobjectthirdparties;
382  }
383  if ( ! empty( $listofobjectref ) ) {
384  $parameters['listofobjectref'] = $listofobjectref;
385  }
386 
387  complete_substitutions_array($substitutionarray, $langs, $objecttmp, $parameters);
388 
389  $subject=make_substitutions($subject, $substitutionarray);
390  $message=make_substitutions($message, $substitutionarray);
391 
392  $filepath = $attachedfiles['paths'];
393  $filename = $attachedfiles['names'];
394  $mimetype = $attachedfiles['mimes'];
395 
396  // Define the trackid when emails sent from the mass action
397  if ($oneemailperrecipient)
398  {
399  $trackid='thi'.$thirdparty->id;
400  if ($objecttmp->element == 'expensereport') $trackid='use'.$thirdparty->id;
401  if ($objecttmp->element == 'holiday') $trackid='use'.$thirdparty->id;
402  }
403  else
404  {
405  $trackid=strtolower(get_class($objecttmp));
406  if (get_class($objecttmp)=='Contrat') $trackid='con';
407  if (get_class($objecttmp)=='Propal') $trackid='pro';
408  if (get_class($objecttmp)=='Commande') $trackid='ord';
409  if (get_class($objecttmp)=='Facture') $trackid='inv';
410  if (get_class($objecttmp)=='Supplier_Proposal') $trackid='spr';
411  if (get_class($objecttmp)=='CommandeFournisseur') $trackid='sor';
412  if (get_class($objecttmp)=='FactureFournisseur') $trackid='sin';
413 
414  $trackid.=$objecttmp->id;
415  }
416  //var_dump($filepath);
417  //var_dump($trackid);exit;
418 
419  // Send mail (substitutionarray must be done just before this)
420  require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
421  $mailfile = new CMailFile($subject,$sendto,$from,$message,$filepath,$mimetype,$filename,$sendtocc,$sendtobcc,$deliveryreceipt,-1,'','',$trackid);
422  if ($mailfile->error)
423  {
424  $resaction.='<div class="error">'.$mailfile->error.'</div>';
425  }
426  else
427  {
428  $result=$mailfile->sendfile();
429  if ($result)
430  {
431  $resaction.=$langs->trans('MailSuccessfulySent',$mailfile->getValidAddress($from,2),$mailfile->getValidAddress($sendto,2)).'<br>'; // Must not contain "
432 
433  $error=0;
434 
435  // Insert logs into agenda
436  foreach($listofqualifiedobj as $objid2 => $objectobj2)
437  {
438  if ((! $oneemailperrecipient) && $objid2 != $objectid) continue; // We discard this pass to avoid duplicate with other pass in looparray at higher level
439 
440  dol_syslog("Try to insert email event into agenda for objid=".$objid2." => objectobj=".get_class($objectobj2));
441 
442  /*if ($objectclass == 'Propale') $actiontypecode='AC_PROP';
443  if ($objectclass == 'Commande') $actiontypecode='AC_COM';
444  if ($objectclass == 'Facture') $actiontypecode='AC_FAC';
445  if ($objectclass == 'Supplier_Proposal') $actiontypecode='AC_SUP_PRO';
446  if ($objectclass == 'CommandeFournisseur') $actiontypecode='AC_SUP_ORD';
447  if ($objectclass == 'FactureFournisseur') $actiontypecode='AC_SUP_INV';*/
448 
449  $actionmsg=$langs->transnoentities('MailSentBy').' '.$from.' '.$langs->transnoentities('To').' '.$sendto;
450  if ($message)
451  {
452  if ($sendtocc) $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('Bcc') . ": " . $sendtocc);
453  $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTopic') . ": " . $subject);
454  $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('TextUsedInTheMessageBody') . ":");
455  $actionmsg = dol_concatdesc($actionmsg, $message);
456  }
457  $actionmsg2='';
458 
459  // Initialisation donnees
460  $objectobj2->sendtoid = 0;
461  $objectobj2->actionmsg = $actionmsg; // Long text
462  $objectobj2->actionmsg2 = $actionmsg2; // Short text
463  $objectobj2->fk_element = $objid2;
464  $objectobj2->elementtype = $objectobj2->element;
465 
466  $triggername = strtoupper(get_class($objectobj2)) .'_SENTBYMAIL';
467  if ($triggername == 'SOCIETE_SENTBYMAIL') $triggername = 'COMPANY_SENTBYMAIL';
468  if ($triggername == 'CONTRAT_SENTBYMAIL') $triggername = 'CONTRACT_SENTBYMAIL';
469  if ($triggername == 'COMMANDE_SENTBYMAIL') $triggername = 'ORDER_SENTBYMAIL';
470  if ($triggername == 'FACTURE_SENTBYMAIL') $triggername = 'BILL_SENTBYMAIL';
471  if ($triggername == 'EXPEDITION_SENTBYMAIL') $triggername = 'SHIPPING_SENTBYMAIL';
472  if ($triggername == 'COMMANDEFOURNISSEUR_SENTBYMAIL') $triggername = 'ORDER_SUPPLIER_SENTBYMAIL';
473  if ($triggername == 'FACTUREFOURNISSEUR_SENTBYMAIL') $triggername = 'BILL_SUPPLIER_SENTBYMAIL';
474  if ($triggername == 'SUPPLIERPROPOSAL_SENTBYMAIL') $triggername = 'PROPOSAL_SUPPLIER_SENTBYMAIL';
475 
476  if (! empty($triggername))
477  {
478  // Appel des triggers
479  include_once DOL_DOCUMENT_ROOT . "/core/class/interfaces.class.php";
480  $interface=new Interfaces($db);
481  $result=$interface->run_triggers($triggername, $objectobj2, $user, $langs, $conf);
482  if ($result < 0) { $error++; $errors=$interface->errors; }
483  // Fin appel triggers
484 
485  if ($error)
486  {
487  setEventMessages($db->lasterror(), $errors, 'errors');
488  dol_syslog("Error in trigger ".$triggername.' '.$db->lasterror(), LOG_ERR);
489  }
490  }
491  }
492 
493  $nbsent++; // Nb of email sent (may be lower than number of record selected if we group thirdparties)
494  }
495  else
496  {
497  $langs->load("other");
498  if ($mailfile->error)
499  {
500  $resaction.=$langs->trans('ErrorFailedToSendMail',$from,$sendto);
501  $resaction.='<br><div class="error">'.$mailfile->error.'</div>';
502  }
503  else
504  {
505  $resaction.='<div class="warning">No mail sent. Feature is disabled by option MAIN_DISABLE_ALL_MAILS</div>';
506  }
507  }
508  }
509  }
510  }
511  }
512 
513  $resaction.=($resaction?'<br>':$resaction);
514  $resaction.='<strong>'.$langs->trans("ResultOfMailSending").':</strong><br>'."\n";
515  $resaction.=$langs->trans("NbSelected").': '.count($toselect)."\n<br>";
516  $resaction.=$langs->trans("NbIgnored").': '.($nbignored?$nbignored:0)."\n<br>";
517  $resaction.=$langs->trans("NbSent").': '.($nbsent?$nbsent:0)."\n<br>";
518 
519  if ($nbsent)
520  {
521  $action=''; // Do not show form post if there was at least one successfull sent
522  //setEventMessages($langs->trans("EMailSentToNRecipients", $nbsent.'/'.count($toselect)), null, 'mesgs');
523  setEventMessages($langs->trans("EMailSentForNElements", $nbsent.'/'.count($toselect)), null, 'mesgs');
524  setEventMessages($resaction, null, 'mesgs');
525  }
526  else
527  {
528  //setEventMessages($langs->trans("EMailSentToNRecipients", 0), null, 'warnings'); // May be object has no generated PDF file
529  setEventMessages($resaction, null, 'warnings');
530  }
531 
532  $action='list';
533  $massaction='';
534  }
535 }
536 
537 if ($massaction == 'confirm_createbills')
538 {
539  $orders = GETPOST('toselect','array');
540  $createbills_onebythird = GETPOST('createbills_onebythird', 'int');
541  $validate_invoices = GETPOST('valdate_invoices', 'int');
542 
543  $TFact = array();
544  $TFactThird = array();
545 
546  $nb_bills_created = 0;
547 
548  $db->begin();
549 
550  foreach($orders as $id_order)
551  {
552  $cmd = new Commande($db);
553  if ($cmd->fetch($id_order) <= 0) continue;
554 
555  $objecttmp = new Facture($db);
556  if (!empty($createbills_onebythird) && !empty($TFactThird[$cmd->socid])) $objecttmp = $TFactThird[$cmd->socid]; // If option "one bill per third" is set, we use already created order.
557  else {
558  // Load extrafields of order
559  $cmd->fetch_optionals();
560 
561  $objecttmp->socid = $cmd->socid;
562  $objecttmp->type = Facture::TYPE_STANDARD;
563  $objecttmp->cond_reglement_id = $cmd->cond_reglement_id;
564  $objecttmp->mode_reglement_id = $cmd->mode_reglement_id;
565  $objecttmp->fk_project = $cmd->fk_project;
566 
567  $datefacture = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']);
568  if (empty($datefacture))
569  {
570  $datefacture = dol_mktime(date("h"), date("M"), 0, date("m"), date("d"), date("Y"));
571  }
572 
573  $objecttmp->date = $datefacture;
574  $objecttmp->origin = 'commande';
575  $objecttmp->origin_id = $id_order;
576 
577  $objecttmp->array_options = $cmd->array_options; // Copy extrafields
578 
579  $res = $objecttmp->create($user);
580 
581  if($res > 0) $nb_bills_created++;
582  }
583 
584  if ($objecttmp->id > 0)
585  {
586  $sql = "INSERT INTO ".MAIN_DB_PREFIX."element_element (";
587  $sql.= "fk_source";
588  $sql.= ", sourcetype";
589  $sql.= ", fk_target";
590  $sql.= ", targettype";
591  $sql.= ") VALUES (";
592  $sql.= $id_order;
593  $sql.= ", '".$objecttmp->origin."'";
594  $sql.= ", ".$objecttmp->id;
595  $sql.= ", '".$objecttmp->element."'";
596  $sql.= ")";
597 
598  if (! $db->query($sql))
599  {
600  $error++;
601  }
602 
603  if (! $error)
604  {
605  $lines = $cmd->lines;
606  if (empty($lines) && method_exists($cmd, 'fetch_lines'))
607  {
608  $cmd->fetch_lines();
609  $lines = $cmd->lines;
610  }
611 
612  $fk_parent_line=0;
613  $num=count($lines);
614 
615  for ($i=0;$i<$num;$i++)
616  {
617  $desc=($lines[$i]->desc?$lines[$i]->desc:$lines[$i]->libelle);
618  if ($lines[$i]->subprice < 0)
619  {
620  // Negative line, we create a discount line
621  $discount = new DiscountAbsolute($db);
622  $discount->fk_soc=$objecttmp->socid;
623  $discount->amount_ht=abs($lines[$i]->total_ht);
624  $discount->amount_tva=abs($lines[$i]->total_tva);
625  $discount->amount_ttc=abs($lines[$i]->total_ttc);
626  $discount->tva_tx=$lines[$i]->tva_tx;
627  $discount->fk_user=$user->id;
628  $discount->description=$desc;
629  $discountid=$discount->create($user);
630  if ($discountid > 0)
631  {
632  $result=$objecttmp->insert_discount($discountid);
633  //$result=$discount->link_to_invoice($lineid,$id);
634  }
635  else
636  {
637  setEventMessages($discount->error, $discount->errors, 'errors');
638  $error++;
639  break;
640  }
641  }
642  else
643  {
644  // Positive line
645  $product_type=($lines[$i]->product_type?$lines[$i]->product_type:0);
646  // Date start
647  $date_start=false;
648  if ($lines[$i]->date_debut_prevue) $date_start=$lines[$i]->date_debut_prevue;
649  if ($lines[$i]->date_debut_reel) $date_start=$lines[$i]->date_debut_reel;
650  if ($lines[$i]->date_start) $date_start=$lines[$i]->date_start;
651  //Date end
652  $date_end=false;
653  if ($lines[$i]->date_fin_prevue) $date_end=$lines[$i]->date_fin_prevue;
654  if ($lines[$i]->date_fin_reel) $date_end=$lines[$i]->date_fin_reel;
655  if ($lines[$i]->date_end) $date_end=$lines[$i]->date_end;
656  // Reset fk_parent_line for no child products and special product
657  if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9)
658  {
659  $fk_parent_line = 0;
660  }
661 
662  // Extrafields
663  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && method_exists($lines[$i], 'fetch_optionals')) {
664  $lines[$i]->fetch_optionals($lines[$i]->rowid);
665  $array_options = $lines[$i]->array_options;
666  }
667 
668  $result = $objecttmp->addline(
669  $desc,
670  $lines[$i]->subprice,
671  $lines[$i]->qty,
672  $lines[$i]->tva_tx,
673  $lines[$i]->localtax1_tx,
674  $lines[$i]->localtax2_tx,
675  $lines[$i]->fk_product,
676  $lines[$i]->remise_percent,
677  $date_start,
678  $date_end,
679  0,
680  $lines[$i]->info_bits,
681  $lines[$i]->fk_remise_except,
682  'HT',
683  0,
684  $product_type,
685  $ii,
686  $lines[$i]->special_code,
687  $objecttmp->origin,
688  $lines[$i]->rowid,
689  $fk_parent_line,
690  $lines[$i]->fk_fournprice,
691  $lines[$i]->pa_ht,
692  $lines[$i]->label,
693  $array_options
694  );
695  if ($result > 0)
696  {
697  $lineid=$result;
698  }
699  else
700  {
701  $lineid=0;
702  $error++;
703  break;
704  }
705  // Defined the new fk_parent_line
706  if ($result > 0 && $lines[$i]->product_type == 9)
707  {
708  $fk_parent_line = $result;
709  }
710  }
711  }
712  }
713  }
714 
715  //$cmd->classifyBilled($user); // Disabled. This behavior must be set or not using the workflow module.
716 
717  if(!empty($createbills_onebythird) && empty($TFactThird[$cmd->socid])) $TFactThird[$cmd->socid] = $objecttmp;
718  else $TFact[$objecttmp->id] = $objecttmp;
719  }
720 
721  // Build doc with all invoices
722  $TAllFact = empty($createbills_onebythird) ? $TFact : $TFactThird;
723  $toselect = array();
724 
725  if (! $error && $validate_invoices)
726  {
727  $massaction = $action = 'builddoc';
728 
729  foreach($TAllFact as &$objecttmp)
730  {
731  $result = $objecttmp->validate($user);
732  if ($result <= 0)
733  {
734  $error++;
735  setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
736  break;
737  }
738 
739  $id = $objecttmp->id; // For builddoc action
740  $object = $objecttmp;
741 
742  // Builddoc
743  $donotredirect = 1;
744  $upload_dir = $conf->facture->dir_output;
745  $permissioncreate=$user->rights->facture->creer;
746 
747  // Call action to build doc
748  $savobject = $object;
749  $object = $objecttmp;
750  include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
751  $object = $savobject;
752  }
753 
754  $massaction = $action = 'confirm_createbills';
755  }
756 
757  if (! $error)
758  {
759  $db->commit();
760  setEventMessages($langs->trans('BillCreated', $nb_bills_created), null, 'mesgs');
761 
762  // Make a redirect to avoid to bill twice if we make a refresh or back
763  $param='';
764  if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.urlencode($contextpage);
765  if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.urlencode($limit);
766  if ($sall) $param.='&sall='.urlencode($sall);
767  if ($socid > 0) $param.='&socid='.urlencode($socid);
768  if ($viewstatut != '') $param.='&viewstatut='.urlencode($viewstatut);
769  if ($search_orderday) $param.='&search_orderday='.urlencode($search_orderday);
770  if ($search_ordermonth) $param.='&search_ordermonth='.urlencode($search_ordermonth);
771  if ($search_orderyear) $param.='&search_orderyear='.urlencode($search_orderyear);
772  if ($search_deliveryday) $param.='&search_deliveryday='.urlencode($search_deliveryday);
773  if ($search_deliverymonth) $param.='&search_deliverymonth='.urlencode($search_deliverymonth);
774  if ($search_deliveryyear) $param.='&search_deliveryyear='.urlencode($search_deliveryyear);
775  if ($search_ref) $param.='&search_ref='.urlencode($search_ref);
776  if ($search_company) $param.='&search_company='.urlencode($search_company);
777  if ($search_ref_customer) $param.='&search_ref_customer='.urlencode($search_ref_customer);
778  if ($search_user > 0) $param.='&search_user='.urlencode($search_user);
779  if ($search_sale > 0) $param.='&search_sale='.urlencode($search_sale);
780  if ($search_total_ht != '') $param.='&search_total_ht='.urlencode($search_total_ht);
781  if ($search_total_vat != '') $param.='&search_total_vat='.urlencode($search_total_vat);
782  if ($search_total_ttc != '') $param.='&search_total_ttc='.urlencode($search_total_ttc);
783  if ($search_project_ref >= 0) $param.="&search_project_ref=".urlencode($search_project_ref);
784  if ($show_files) $param.='&show_files=' .urlencode($show_files);
785  if ($optioncss != '') $param.='&optioncss='.urlencode($optioncss);
786  if ($billed != '') $param.='&billed='.urlencode($billed);
787 
788  header("Location: ".$_SERVER['PHP_SELF'].'?'.$param);
789  exit;
790  }
791  else
792  {
793  $db->rollback();
794  $action='create';
795  $_GET["origin"]=$_POST["origin"];
796  $_GET["originid"]=$_POST["originid"];
797  setEventMessages("Error", null, 'errors');
798  $error++;
799  }
800 }
801 
802 if (!$error && $massaction == 'cancelorders')
803 {
804 
805  $db->begin();
806 
807  $nbok = 0;
808 
809 
810  $orders = GETPOST('toselect', 'array');
811  foreach ($orders as $id_order)
812  {
813 
814  $cmd = new Commande($db);
815  if ($cmd->fetch($id_order) <= 0)
816  continue;
817 
818  if ($cmd->statut != Commande::STATUS_VALIDATED)
819  {
820  $langs->load('errors');
821  setEventMessages($langs->trans("ErrorObjectMustHaveStatusValidToBeCanceled", $cmd->ref), null, 'errors');
822  $error++;
823  break;
824  }
825  else
826  $result = $cmd->cancel();
827 
828  if ($result < 0)
829  {
830  setEventMessages($cmd->error, $cmd->errors, 'errors');
831  $error++;
832  break;
833  }
834  else
835  $nbok++;
836  }
837  if (!$error)
838  {
839  if ($nbok > 1)
840  setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs');
841  else
842  setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs');
843  $db->commit();
844  }
845  else
846  {
847  $db->rollback();
848  }
849 }
850 
851 
852 if (! $error && $massaction == "builddoc" && $permtoread && ! GETPOST('button_search'))
853 {
854  if (empty($diroutputmassaction))
855  {
856  dol_print_error(null, 'include of actions_massactions.inc.php is done but var $diroutputmassaction was not defined');
857  exit;
858  }
859 
860  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
861  require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
862  require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
863 
864  $objecttmp=new $objectclass($db);
865  $listofobjectid=array();
866  $listofobjectthirdparties=array();
867  $listofobjectref=array();
868  foreach($toselect as $toselectid)
869  {
870  $objecttmp=new $objectclass($db); // must create new instance because instance is saved into $listofobjectref array for future use
871  $result=$objecttmp->fetch($toselectid);
872  if ($result > 0)
873  {
874  $listofobjectid[$toselectid]=$toselectid;
875  $thirdpartyid=$objecttmp->fk_soc?$objecttmp->fk_soc:$objecttmp->socid;
876  $listofobjectthirdparties[$thirdpartyid]=$thirdpartyid;
877  $listofobjectref[$toselectid]=$objecttmp->ref;
878  }
879  }
880 
881  $arrayofinclusion=array();
882  foreach($listofobjectref as $tmppdf) $arrayofinclusion[]='^'.preg_quote(dol_sanitizeFileName($tmppdf),'/').'\.pdf$';
883  foreach($listofobjectref as $tmppdf) $arrayofinclusion[]='^'.preg_quote(dol_sanitizeFileName($tmppdf),'/').'_[a-zA-Z0-9-_]+\.pdf$'; // To include PDF generated from ODX files
884  $listoffiles = dol_dir_list($uploaddir,'all',1,implode('|',$arrayofinclusion),'\.meta$|\.png','date',SORT_DESC,0,true);
885 
886  // build list of files with full path
887  $files = array();
888  foreach($listofobjectref as $basename)
889  {
890  $basename = dol_sanitizeFileName($basename);
891  foreach($listoffiles as $filefound)
892  {
893  if (strstr($filefound["name"],$basename))
894  {
895  $files[] = $uploaddir.'/'.$basename.'/'.$filefound["name"];
896  break;
897  }
898  }
899  }
900 
901  // Define output language (Here it is not used because we do only merging existing PDF)
902  $outputlangs = $langs;
903  $newlang='';
904  if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang=GETPOST('lang_id','aZ09');
905  if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang=$objecttmp->thirdparty->default_lang;
906  if (! empty($newlang))
907  {
908  $outputlangs = new Translate("",$conf);
909  $outputlangs->setDefaultLang($newlang);
910  }
911 
912  if (!empty($conf->global->USE_PDFTK_FOR_PDF_CONCAT))
913  {
914  // Create output dir if not exists
915  dol_mkdir($diroutputmassaction);
916 
917  // Defined name of merged file
918  $filename=strtolower(dol_sanitizeFileName($langs->transnoentities($objectlabel)));
919  $filename=preg_replace('/\s/','_',$filename);
920 
921  // Save merged file
922  if (in_array($objecttmp->element, array('facture', 'facture_fournisseur')) && $search_status == Facture::STATUS_VALIDATED)
923  {
924  if ($option=='late') $filename.='_'.strtolower(dol_sanitizeFileName($langs->transnoentities("Unpaid"))).'_'.strtolower(dol_sanitizeFileName($langs->transnoentities("Late")));
925  else $filename.='_'.strtolower(dol_sanitizeFileName($langs->transnoentities("Unpaid")));
926  }
927  if ($year) $filename.='_'.$year;
928  if ($month) $filename.='_'.$month;
929 
930  if (count($files)>0)
931  {
932  $now=dol_now();
933  $file=$diroutputmassaction.'/'.$filename.'_'.dol_print_date($now,'dayhourlog').'.pdf';
934 
935  $input_files = '';
936  foreach($files as $f) {
937  $input_files.=' '.escapeshellarg($f);
938  }
939 
940  $cmd = 'pdftk '.escapeshellarg($input_files).' cat output '.escapeshellarg($file);
941  exec($cmd);
942 
943  if (! empty($conf->global->MAIN_UMASK))
944  @chmod($file, octdec($conf->global->MAIN_UMASK));
945 
946  $langs->load("exports");
947  setEventMessages($langs->trans('FileSuccessfullyBuilt',$filename.'_'.dol_print_date($now,'dayhourlog')), null, 'mesgs');
948  }
949  else
950  {
951  setEventMessages($langs->trans('NoPDFAvailableForDocGenAmongChecked'), null, 'errors');
952  }
953  }
954  else {
955  // Create empty PDF
956  $formatarray=pdf_getFormat();
957  $page_largeur = $formatarray['width'];
958  $page_hauteur = $formatarray['height'];
959  $format = array($page_largeur,$page_hauteur);
960 
961  $pdf=pdf_getInstance($format);
962 
963  if (class_exists('TCPDF'))
964  {
965  $pdf->setPrintHeader(false);
966  $pdf->setPrintFooter(false);
967  }
968  $pdf->SetFont(pdf_getPDFFont($outputlangs));
969 
970  if (! empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) $pdf->SetCompression(false);
971 
972  // Add all others
973  foreach($files as $file)
974  {
975  // Charge un document PDF depuis un fichier.
976  $pagecount = $pdf->setSourceFile($file);
977  for ($i = 1; $i <= $pagecount; $i++)
978  {
979  $tplidx = $pdf->importPage($i);
980  $s = $pdf->getTemplatesize($tplidx);
981  $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
982  $pdf->useTemplate($tplidx);
983  }
984  }
985 
986  // Create output dir if not exists
987  dol_mkdir($diroutputmassaction);
988 
989  // Defined name of merged file
990  $filename=strtolower(dol_sanitizeFileName($langs->transnoentities($objectlabel)));
991  $filename=preg_replace('/\s/','_',$filename);
992 
993  // Save merged file
994  if (in_array($objecttmp->element, array('facture', 'facture_fournisseur')) && $search_status == Facture::STATUS_VALIDATED)
995  {
996  if ($option=='late') $filename.='_'.strtolower(dol_sanitizeFileName($langs->transnoentities("Unpaid"))).'_'.strtolower(dol_sanitizeFileName($langs->transnoentities("Late")));
997  else $filename.='_'.strtolower(dol_sanitizeFileName($langs->transnoentities("Unpaid")));
998  }
999  if ($year) $filename.='_'.$year;
1000  if ($month) $filename.='_'.$month;
1001  if ($pagecount)
1002  {
1003  $now=dol_now();
1004  $file=$diroutputmassaction.'/'.$filename.'_'.dol_print_date($now,'dayhourlog').'.pdf';
1005  $pdf->Output($file,'F');
1006  if (! empty($conf->global->MAIN_UMASK))
1007  @chmod($file, octdec($conf->global->MAIN_UMASK));
1008 
1009  $langs->load("exports");
1010  setEventMessages($langs->trans('FileSuccessfullyBuilt',$filename.'_'.dol_print_date($now,'dayhourlog')), null, 'mesgs');
1011  }
1012  else
1013  {
1014  setEventMessages($langs->trans('NoPDFAvailableForDocGenAmongChecked'), null, 'errors');
1015  }
1016  }
1017 }
1018 
1019 // Remove a file from massaction area
1020 if ($action == 'remove_file')
1021 {
1022  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1023 
1024  $langs->load("other");
1025  $upload_dir = $diroutputmassaction;
1026  $file = $upload_dir . '/' . GETPOST('file');
1027  $ret=dol_delete_file($file);
1028  if ($ret) setEventMessages($langs->trans("FileWasRemoved", GETPOST('file')), null, 'mesgs');
1029  else setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('file')), null, 'errors');
1030  $action='';
1031 }
1032 
1033 // Validate records
1034 if (! $error && $massaction == 'validate' && $permtocreate)
1035 {
1036  $objecttmp=new $objectclass($db);
1037 
1038  if ($objecttmp->element == 'invoice' && ! empty($conf->stock->enabled) && ! empty($conf->global->STOCK_CALCULATE_ON_BILL))
1039  {
1040  $langs->load("errors");
1041  setEventMessages($langs->trans('ErrorMassValidationNotAllowedWhenStockIncreaseOnAction'), null, 'errors');
1042  $error++;
1043  }
1044  if ($objecttmp->element == 'invoice_supplier' && ! empty($conf->stock->enabled) && ! empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_BILL))
1045  {
1046  $langs->load("errors");
1047  setEventMessages($langs->trans('ErrorMassValidationNotAllowedWhenStockIncreaseOnAction'), null, 'errors');
1048  $error++;
1049  }
1050  if (! $error)
1051  {
1052  $db->begin();
1053 
1054  $nbok = 0;
1055  foreach($toselect as $toselectid)
1056  {
1057  $result=$objecttmp->fetch($toselectid);
1058  if ($result > 0)
1059  {
1060  //if (in_array($objecttmp->element, array('societe','member'))) $result = $objecttmp->delete($objecttmp->id, $user, 1);
1061  //else
1062  $result = $objecttmp->validate($user);
1063  if ($result == 0)
1064  {
1065  $langs->load("errors");
1066  setEventMessages($langs->trans("ErrorObjectMustHaveStatusDraftToBeValidated", $objecttmp->ref), null, 'errors');
1067  $error++;
1068  break;
1069  }
1070  elseif ($result < 0)
1071  {
1072  setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
1073  $error++;
1074  break;
1075  }
1076  else $nbok++;
1077  }
1078  else
1079  {
1080  setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
1081  $error++;
1082  break;
1083  }
1084  }
1085 
1086  if (! $error)
1087  {
1088  if ($nbok > 1) setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs');
1089  else setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs');
1090  $db->commit();
1091  }
1092  else
1093  {
1094  $db->rollback();
1095  }
1096  //var_dump($listofobjectthirdparties);exit;
1097  }
1098 }
1099 // Closed records
1100 if (!$error && $massaction == 'closed' && $objectclass == "Propal" && $permtoclose) {
1101  $db->begin();
1102 
1103  $objecttmp = new $objectclass($db);
1104  $nbok = 0;
1105  foreach ($toselect as $toselectid) {
1106  $result = $objecttmp->fetch($toselectid);
1107  if ($result > 0) {
1108  $result = $objecttmp->cloture($user, 3);
1109  if ($result <= 0) {
1110  setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
1111  $error++;
1112  break;
1113  } else
1114  $nbok++;
1115  }
1116  else {
1117  setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
1118  $error++;
1119  break;
1120  }
1121  }
1122 
1123  if (!$error) {
1124  if ($nbok > 1)
1125  setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs');
1126  else
1127  setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs');
1128  $db->commit();
1129  }
1130  else {
1131  $db->rollback();
1132  }
1133 }
1134 // Delete record from mass action (massaction = 'delete' for direct delete, action/confirm='delete'/'yes' with a confirmation step before)
1135 if (! $error && ($massaction == 'delete' || ($action == 'delete' && $confirm == 'yes')) && $permtodelete)
1136 {
1137  $db->begin();
1138 
1139  $objecttmp=new $objectclass($db);
1140  $nbok = 0;
1141  foreach($toselect as $toselectid)
1142  {
1143  $result=$objecttmp->fetch($toselectid);
1144  if ($result > 0)
1145  {
1146  // Refuse deletion for some objects/status
1147  if ($objectclass == 'Facture' && empty($conf->global->INVOICE_CAN_ALWAYS_BE_REMOVED) && $objecttmp->status != Facture::STATUS_DRAFT)
1148  {
1149  $langs->load("errors");
1150  $nbignored++;
1151  $resaction.='<div class="error">'.$langs->trans('ErrorOnlyDraftStatusCanBeDeletedInMassAction',$objecttmp->ref).'</div><br>';
1152  continue;
1153  }
1154 
1155  if ($objectclass == "Task" && $objecttmp->hasChildren() > 0)
1156  {
1157  $sql = "UPDATE ".MAIN_DB_PREFIX."projet_task SET fk_task_parent = 0 WHERE fk_task_parent = ".$objecttmp->id;
1158  $res = $db->query($sql);
1159 
1160  if (!$res)
1161  {
1162  setEventMessage('ErrorRecordParentingNotModified', 'errors');
1163  $error++;
1164  }
1165  }
1166 
1167  if (in_array($objecttmp->element, array('societe', 'member'))) $result = $objecttmp->delete($objecttmp->id, $user, 1);
1168  else $result = $objecttmp->delete($user);
1169 
1170  if ($result <= 0)
1171  {
1172  setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
1173  $error++;
1174  break;
1175  }
1176  else $nbok++;
1177  }
1178  else
1179  {
1180  setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
1181  $error++;
1182  break;
1183  }
1184  }
1185 
1186  if (! $error)
1187  {
1188  if ($nbok > 1) setEventMessages($langs->trans("RecordsDeleted", $nbok), null, 'mesgs');
1189  else setEventMessages($langs->trans("RecordDeleted", $nbok), null, 'mesgs');
1190  $db->commit();
1191  }
1192  else
1193  {
1194  $db->rollback();
1195  }
1196  //var_dump($listofobjectthirdparties);exit;
1197 }
1198 
1199 // Generate document foreach object according to model linked to object
1200 // @TODO : propose model selection
1201 if (! $error && $massaction == 'generate_doc' && $permtoread)
1202 {
1203  $db->begin();
1204 
1205  $objecttmp=new $objectclass($db);
1206  $nbok = 0;
1207  foreach($toselect as $toselectid)
1208  {
1209  $result=$objecttmp->fetch($toselectid);
1210  if ($result > 0)
1211  {
1212  $outputlangs = $langs;
1213  $newlang='';
1214 
1215  if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang=GETPOST('lang_id','aZ09');
1216  if ($conf->global->MAIN_MULTILANGS && empty($newlang) && isset($objecttmp->thirdparty->default_lang)) $newlang=$objecttmp->thirdparty->default_lang; // for proposal, order, invoice, ...
1217  if ($conf->global->MAIN_MULTILANGS && empty($newlang) && isset($objecttmp->default_lang)) $newlang=$objecttmp->default_lang; // for thirdparty
1218  if (! empty($newlang))
1219  {
1220  $outputlangs = new Translate("",$conf);
1221  $outputlangs->setDefaultLang($newlang);
1222  }
1223 
1224  // To be sure vars is defined
1225  if (empty($hidedetails)) $hidedetails=0;
1226  if (empty($hidedesc)) $hidedesc=0;
1227  if (empty($hideref)) $hideref=0;
1228  if (empty($moreparams)) $moreparams=null;
1229 
1230  $result= $objecttmp->generateDocument($objecttmp->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1231 
1232  if ($result <= 0)
1233  {
1234  setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
1235  $error++;
1236  break;
1237  }
1238  else $nbok++;
1239  }
1240  else
1241  {
1242  setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
1243  $error++;
1244  break;
1245  }
1246  }
1247 
1248  if (! $error)
1249  {
1250  if ($nbok > 1) setEventMessages($langs->trans("RecordsGenerated", $nbok), null, 'mesgs');
1251  else setEventMessages($langs->trans("RecordGenerated", $nbok), null, 'mesgs');
1252  $db->commit();
1253  }
1254  else
1255  {
1256  $db->rollback();
1257  }
1258 }
1259 
1260 $parameters['toselect']=$toselect;
1261 $parameters['uploaddir']=$uploaddir;
1262 
1263 $reshook=$hookmanager->executeHooks('doMassActions',$parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1264 if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1265 
1266 
1267 
pdf_getInstance($format='', $metric='mm', $pagetype='P')
Return a PDF instance object.
Definition: pdf.lib.php:82
GETPOST($paramname, $check='none', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
const TYPE_STANDARD
Standard invoice.
setEventMessages($mesg, $mesgs, $style='mesgs')
Set event messages in dol_events session object.
if(! empty($conf->facture->enabled) && $user->rights->facture->lire) if(! empty($conf->fournisseur->enabled) && $user->rights->fournisseur->facture->lire) if(! empty($conf->don->enabled) && $user->rights->societe->lire) if(! empty($conf->tax->enabled) && $user->rights->tax->charges->lire) if(! empty($conf->facture->enabled) &&! empty($conf->commande->enabled) && $user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(! empty($conf->facture->enabled) && $user->rights->facture->lire) if(! empty($conf->fournisseur->enabled) && $user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1053
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm=false, $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
pdf_getFormat(Translate $outputlangs=null)
Return array with format properties of default PDF format.
Definition: pdf.lib.php:42
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_mimetype($file, $default='application/octet-stream', $mode=0)
Return mime type of a file.
Class to manage Dolibarr users.
Definition: user.class.php:41
dol_print_error($db='', $error='', $errors=null)
Affiche message erreur system avec toutes les informations pour faciliter le diagnostic et la remonte...
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition: pdf.lib.php:201
dol_concatdesc($text1, $text2, $forxml=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
getCommonSubstitutionArray($outputlangs, $onlykey=0, $exclude=null, $object=null)
Return array of possible common substitutions.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='')
Write log message into outputs.
Class to manage third parties objects (customers, suppliers, prospects...)
const STATUS_VALIDATED
Validated (need to be paid)
Class to send emails (with attachments or not) Usage: $mailfile = new CMailFile($subject,$sendto,$replyto,$message,$filepath,$mimetype,$filename,$cc,$ccc,$deliveryreceipt,$msgishtml,$errors_to,$css,$trackid,$moreinheader,$sendcontext); $mailfile->sendfile();.
Class to manage customers orders.
const STATUS_DRAFT
Draft status.
const STATUS_DRAFT
Draft status.
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1)
Remove a file or several files with a mask.
Definition: files.lib.php:1139
Class to manage translations.
dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0)
Scan a directory and return a list of files/directories.
Definition: files.lib.php:59
dol_now($mode='gmt')
Return date for now.
dol_is_file($pathoffile)
Return if path is a file.
Definition: files.lib.php:451
const STATUS_DRAFT
Draft status.
dol_print_date($time, $format='', $tzoutput='tzserver', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
const STATUS_VALIDATED
Validated status.
setEventMessage($mesgs, $style='mesgs')
Set event message in dol_events session object.
dol_mkdir($dir, $dataroot='', $newmask=null)
Creation of a directory (this can create recursive subdir)
Class to manage absolute discounts.
make_substitutions($text, $substitutionarray, $outputlangs=null)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
Class to manage invoices.
Class to manage triggers.
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...