notify.class.php 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878
  1. <?php
  2. /* Copyright (C) 2003-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (C) 2004-2011 Laurent Destailleur <eldy@users.sourceforge.net>
  4. * Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>
  5. * Copyright (C) 2018 Philippe Grand <philippe.grand@atoo-net.com>
  6. * Copyright (C) 2021 Thibault FOUCART <support@ptibogxiv.net>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. */
  21. /**
  22. * \file htdocs/core/class/notify.class.php
  23. * \ingroup notification
  24. * \brief File of class to manage notifications
  25. */
  26. require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
  27. /**
  28. * Class to manage notifications
  29. */
  30. class Notify
  31. {
  32. /**
  33. * @var int ID
  34. */
  35. public $id;
  36. /**
  37. * @var DoliDB Database handler.
  38. */
  39. public $db;
  40. /**
  41. * @var string Error code (or message)
  42. */
  43. public $error = '';
  44. /**
  45. * @var string[] Error codes (or messages)
  46. */
  47. public $errors = array();
  48. public $author;
  49. public $ref;
  50. public $date;
  51. public $duree;
  52. public $note;
  53. /**
  54. * @var int Project ID
  55. */
  56. public $fk_project;
  57. // Les codes actions sont definis dans la table llx_notify_def
  58. // codes actions supported are
  59. // @todo defined also into interface_50_modNotification_Notification.class.php
  60. public $arrayofnotifsupported = array(
  61. 'BILL_VALIDATE',
  62. 'BILL_PAYED',
  63. 'ORDER_VALIDATE',
  64. 'PROPAL_VALIDATE',
  65. 'PROPAL_CLOSE_SIGNED',
  66. 'FICHINTER_VALIDATE',
  67. 'FICHINTER_ADD_CONTACT',
  68. 'ORDER_SUPPLIER_VALIDATE',
  69. 'ORDER_SUPPLIER_APPROVE',
  70. 'ORDER_SUPPLIER_REFUSE',
  71. 'SHIPPING_VALIDATE',
  72. 'EXPENSE_REPORT_VALIDATE',
  73. 'EXPENSE_REPORT_APPROVE',
  74. 'HOLIDAY_VALIDATE',
  75. 'HOLIDAY_APPROVE',
  76. 'ACTION_CREATE'
  77. );
  78. /**
  79. * Constructor
  80. *
  81. * @param DoliDB $db Database handler
  82. */
  83. public function __construct($db)
  84. {
  85. $this->db = $db;
  86. }
  87. /**
  88. * Return message that say how many notification (and to which email) will occurs on requested event.
  89. * This is to show confirmation messages before event is recorded.
  90. *
  91. * @param string $action Id of action in llx_c_action_trigger
  92. * @param int $socid Id of third party
  93. * @param Object $object Object the notification is about
  94. * @return string Message
  95. */
  96. public function confirmMessage($action, $socid, $object)
  97. {
  98. global $langs;
  99. $langs->load("mails");
  100. $listofnotiftodo = $this->getNotificationsArray($action, $socid, $object, 0);
  101. $texte = '';
  102. $nb = -1;
  103. if (is_array($listofnotiftodo)) {
  104. $nb = count($listofnotiftodo);
  105. }
  106. if ($nb < 0) {
  107. $texte = img_object($langs->trans("Notifications"), 'email').' '.$langs->trans("ErrorFailedToGetListOfNotificationsToSend");
  108. } elseif ($nb == 0) {
  109. $texte = img_object($langs->trans("Notifications"), 'email').' '.$langs->trans("NoNotificationsWillBeSent");
  110. } elseif ($nb == 1) {
  111. $texte = img_object($langs->trans("Notifications"), 'email').' '.$langs->trans("ANotificationsWillBeSent");
  112. } elseif ($nb >= 2) {
  113. $texte = img_object($langs->trans("Notifications"), 'email').' '.$langs->trans("SomeNotificationsWillBeSent", $nb);
  114. }
  115. if (is_array($listofnotiftodo)) {
  116. $i = 0;
  117. foreach ($listofnotiftodo as $val) {
  118. if ($i) {
  119. $texte .= ', ';
  120. } else {
  121. $texte .= ' (';
  122. }
  123. if ($val['isemailvalid']) {
  124. $texte .= $val['email'];
  125. } else {
  126. $texte .= $val['emaildesc'];
  127. }
  128. $i++;
  129. }
  130. if ($i) {
  131. $texte .= ')';
  132. }
  133. }
  134. return $texte;
  135. }
  136. /**
  137. * Return number of notifications activated for action code (and third party)
  138. *
  139. * @param string $notifcode Code of action in llx_c_action_trigger (new usage) or Id of action in llx_c_action_trigger (old usage)
  140. * @param int $socid Id of third party or 0 for all thirdparties or -1 for no thirdparties
  141. * @param Object $object Object the notification is about (need it to check threshold value of some notifications)
  142. * @param int $userid Id of user or 0 for all users or -1 for no users
  143. * @param array $scope Scope where to search
  144. * @return array|int <0 if KO, array of notifications to send if OK
  145. */
  146. public function getNotificationsArray($notifcode, $socid = 0, $object = null, $userid = 0, $scope = array('thirdparty', 'user', 'global'))
  147. {
  148. global $conf, $user;
  149. $error = 0;
  150. $resarray = array();
  151. $valueforthreshold = 0;
  152. if (is_object($object)) {
  153. $valueforthreshold = $object->total_ht;
  154. }
  155. $sqlnotifcode = '';
  156. if ($notifcode) {
  157. if (is_numeric($notifcode)) {
  158. $sqlnotifcode = " AND n.fk_action = ".((int) $notifcode); // Old usage
  159. } else {
  160. $sqlnotifcode = " AND a.code = '".$this->db->escape($notifcode)."'"; // New usage
  161. }
  162. }
  163. if (!$error) {
  164. if ($socid >= 0 && in_array('thirdparty', $scope)) {
  165. $sql = "SELECT a.code, c.email, c.rowid";
  166. $sql .= " FROM ".MAIN_DB_PREFIX."notify_def as n,";
  167. $sql .= " ".MAIN_DB_PREFIX."socpeople as c,";
  168. $sql .= " ".MAIN_DB_PREFIX."c_action_trigger as a,";
  169. $sql .= " ".MAIN_DB_PREFIX."societe as s";
  170. $sql .= " WHERE n.fk_contact = c.rowid";
  171. $sql .= " AND a.rowid = n.fk_action";
  172. $sql .= " AND n.fk_soc = s.rowid";
  173. $sql .= $sqlnotifcode;
  174. $sql .= " AND s.entity IN (".getEntity('societe').")";
  175. if ($socid > 0) {
  176. $sql .= " AND s.rowid = ".((int) $socid);
  177. }
  178. dol_syslog(__METHOD__." ".$notifcode.", ".$socid."", LOG_DEBUG);
  179. $resql = $this->db->query($sql);
  180. if ($resql) {
  181. $num = $this->db->num_rows($resql);
  182. $i = 0;
  183. while ($i < $num) {
  184. $obj = $this->db->fetch_object($resql);
  185. if ($obj) {
  186. $newval2 = trim($obj->email);
  187. $isvalid = isValidEmail($newval2);
  188. if (empty($resarray[$newval2])) {
  189. $resarray[$newval2] = array('type'=> 'tocontact', 'code'=>trim($obj->code), 'emaildesc'=>'Contact id '.$obj->rowid, 'email'=>$newval2, 'contactid'=>$obj->rowid, 'isemailvalid'=>$isvalid);
  190. }
  191. }
  192. $i++;
  193. }
  194. } else {
  195. $error++;
  196. $this->error = $this->db->lasterror();
  197. }
  198. }
  199. }
  200. if (!$error) {
  201. if ($userid >= 0 && in_array('user', $scope)) {
  202. $sql = "SELECT a.code, c.email, c.rowid";
  203. $sql .= " FROM ".MAIN_DB_PREFIX."notify_def as n,";
  204. $sql .= " ".MAIN_DB_PREFIX."user as c,";
  205. $sql .= " ".MAIN_DB_PREFIX."c_action_trigger as a";
  206. $sql .= " WHERE n.fk_user = c.rowid";
  207. $sql .= " AND a.rowid = n.fk_action";
  208. $sql .= $sqlnotifcode;
  209. $sql .= " AND c.entity IN (".getEntity('user').")";
  210. if ($userid > 0) {
  211. $sql .= " AND c.rowid = ".((int) $userid);
  212. }
  213. dol_syslog(__METHOD__." ".$notifcode.", ".$socid."", LOG_DEBUG);
  214. $resql = $this->db->query($sql);
  215. if ($resql) {
  216. $num = $this->db->num_rows($resql);
  217. $i = 0;
  218. while ($i < $num) {
  219. $obj = $this->db->fetch_object($resql);
  220. if ($obj) {
  221. $newval2 = trim($obj->email);
  222. $isvalid = isValidEmail($newval2);
  223. if (empty($resarray[$newval2])) {
  224. $resarray[$newval2] = array('type'=> 'touser', 'code'=>trim($obj->code), 'emaildesc'=>'User id '.$obj->rowid, 'email'=>$newval2, 'userid'=>$obj->rowid, 'isemailvalid'=>$isvalid);
  225. }
  226. }
  227. $i++;
  228. }
  229. } else {
  230. $error++;
  231. $this->error = $this->db->lasterror();
  232. }
  233. }
  234. }
  235. if (!$error) {
  236. if (in_array('global', $scope)) {
  237. // List of notifications enabled for fixed email
  238. foreach ($conf->global as $key => $val) {
  239. if ($notifcode) {
  240. if ($val == '' || !preg_match('/^NOTIFICATION_FIXEDEMAIL_'.$notifcode.'_THRESHOLD_HIGHER_(.*)$/', $key, $reg)) {
  241. continue;
  242. }
  243. } else {
  244. if ($val == '' || !preg_match('/^NOTIFICATION_FIXEDEMAIL_.*_THRESHOLD_HIGHER_(.*)$/', $key, $reg)) {
  245. continue;
  246. }
  247. }
  248. $threshold = (float) $reg[1];
  249. if ($valueforthreshold < $threshold) {
  250. continue;
  251. }
  252. $tmpemail = explode(',', $val);
  253. foreach ($tmpemail as $key2 => $val2) {
  254. $newval2 = trim($val2);
  255. if ($newval2 == '__SUPERVISOREMAIL__') {
  256. if ($user->fk_user > 0) {
  257. $tmpuser = new User($this->db);
  258. $tmpuser->fetch($user->fk_user);
  259. if ($tmpuser->email) {
  260. $newval2 = trim($tmpuser->email);
  261. } else {
  262. $newval2 = '';
  263. }
  264. } else {
  265. $newval2 = '';
  266. }
  267. }
  268. if ($newval2) {
  269. $isvalid = isValidEmail($newval2, 0);
  270. if (empty($resarray[$newval2])) {
  271. $resarray[$newval2] = array('type'=> 'tofixedemail', 'code'=>trim($key), 'emaildesc'=>trim($val2), 'email'=>$newval2, 'isemailvalid'=>$isvalid);
  272. }
  273. }
  274. }
  275. }
  276. }
  277. }
  278. if ($error) {
  279. return -1;
  280. }
  281. //var_dump($resarray);
  282. return $resarray;
  283. }
  284. /**
  285. * Check if notification are active for couple action/company.
  286. * If yes, send mail and save trace into llx_notify.
  287. *
  288. * @param string $notifcode Code of action in llx_c_action_trigger (new usage) or Id of action in llx_c_action_trigger (old usage)
  289. * @param Object $object Object the notification deals on
  290. * @param array $filename_list List of files to attach (full path of filename on file system)
  291. * @param array $mimetype_list List of MIME type of attached files
  292. * @param array $mimefilename_list List of attached file name in message
  293. * @return int <0 if KO, or number of changes if OK
  294. */
  295. public function send($notifcode, $object, $filename_list = array(), $mimetype_list = array(), $mimefilename_list = array())
  296. {
  297. global $user, $conf, $langs, $mysoc;
  298. global $hookmanager;
  299. global $dolibarr_main_url_root;
  300. global $action;
  301. if (!in_array($notifcode, $this->arrayofnotifsupported)) {
  302. return 0;
  303. }
  304. include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  305. if (!is_object($hookmanager)) {
  306. include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
  307. $hookmanager = new HookManager($this->db);
  308. }
  309. $hookmanager->initHooks(array('notification'));
  310. dol_syslog(get_class($this)."::send notifcode=".$notifcode.", object=".$object->id);
  311. $langs->load("other");
  312. // Define $urlwithroot
  313. $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
  314. $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
  315. //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
  316. // Define some vars
  317. $application = 'Dolibarr';
  318. if (!empty($conf->global->MAIN_APPLICATION_TITLE)) {
  319. $application = $conf->global->MAIN_APPLICATION_TITLE;
  320. }
  321. $replyto = $conf->notification->email_from;
  322. $object_type = '';
  323. $link = '';
  324. $num = 0;
  325. $error = 0;
  326. $oldref = (empty($object->oldref) ? $object->ref : $object->oldref);
  327. $newref = (empty($object->newref) ? $object->ref : $object->newref);
  328. $sql = '';
  329. // Check notification per third party
  330. if (!empty($object->socid) && $object->socid > 0) {
  331. $sql .= "SELECT 'tocontactid' as type_target, c.email, c.rowid as cid, c.lastname, c.firstname, c.default_lang,";
  332. $sql .= " a.rowid as adid, a.label, a.code, n.rowid, n.type";
  333. $sql .= " FROM ".MAIN_DB_PREFIX."socpeople as c,";
  334. $sql .= " ".MAIN_DB_PREFIX."c_action_trigger as a,";
  335. $sql .= " ".MAIN_DB_PREFIX."notify_def as n,";
  336. $sql .= " ".MAIN_DB_PREFIX."societe as s";
  337. $sql .= " WHERE n.fk_contact = c.rowid AND a.rowid = n.fk_action";
  338. $sql .= " AND n.fk_soc = s.rowid";
  339. $sql .= " AND c.statut = 1";
  340. if (is_numeric($notifcode)) {
  341. $sql .= " AND n.fk_action = ".((int) $notifcode); // Old usage
  342. } else {
  343. $sql .= " AND a.code = '".$this->db->escape($notifcode)."'"; // New usage
  344. }
  345. $sql .= " AND s.rowid = ".((int) $object->socid);
  346. $sql .= "\nUNION\n";
  347. }
  348. // Check notification per user
  349. $sql .= "SELECT 'touserid' as type_target, c.email, c.rowid as cid, c.lastname, c.firstname, c.lang as default_lang,";
  350. $sql .= " a.rowid as adid, a.label, a.code, n.rowid, n.type";
  351. $sql .= " FROM ".MAIN_DB_PREFIX."user as c,";
  352. $sql .= " ".MAIN_DB_PREFIX."c_action_trigger as a,";
  353. $sql .= " ".MAIN_DB_PREFIX."notify_def as n";
  354. $sql .= " WHERE n.fk_user = c.rowid AND a.rowid = n.fk_action";
  355. $sql .= " AND c.statut = 1";
  356. if (is_numeric($notifcode)) {
  357. $sql .= " AND n.fk_action = ".$notifcode; // Old usage
  358. } else {
  359. $sql .= " AND a.code = '".$this->db->escape($notifcode)."'"; // New usage
  360. }
  361. $result = $this->db->query($sql);
  362. if ($result) {
  363. $num = $this->db->num_rows($result);
  364. $projtitle = '';
  365. if (!empty($object->fk_project)) {
  366. require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
  367. $proj = new Project($this->db);
  368. $proj->fetch($object->fk_project);
  369. $projtitle = '('.$proj->title.')';
  370. }
  371. if ($num > 0) {
  372. $i = 0;
  373. while ($i < $num && !$error) { // For each notification couple defined (third party/actioncode)
  374. $obj = $this->db->fetch_object($result);
  375. $sendto = dolGetFirstLastname($obj->firstname, $obj->lastname)." <".$obj->email.">";
  376. $notifcodedefid = $obj->adid;
  377. $trackid = '';
  378. if ($obj->type_target == 'tocontactid') {
  379. $trackid = 'con'.$obj->id;
  380. }
  381. if ($obj->type_target == 'touserid') {
  382. $trackid = 'use'.$obj->id;
  383. }
  384. if (dol_strlen($obj->email)) {
  385. // Set output language
  386. $outputlangs = $langs;
  387. if ($obj->default_lang && $obj->default_lang != $langs->defaultlang) {
  388. $outputlangs = new Translate('', $conf);
  389. $outputlangs->setDefaultLang($obj->default_lang);
  390. $outputlangs->loadLangs(array("main", "other"));
  391. }
  392. $subject = '['.$mysoc->name.'] '.$outputlangs->transnoentitiesnoconv("DolibarrNotification").($projtitle ? ' '.$projtitle : '');
  393. switch ($notifcode) {
  394. case 'BILL_VALIDATE':
  395. $link = '<a href="'.$urlwithroot.'/compta/facture/card.php?facid='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  396. $dir_output = $conf->facture->dir_output."/".get_exdir(0, 0, 0, 1, $object, 'invoice');
  397. $object_type = 'facture';
  398. $labeltouse = $conf->global->BILL_VALIDATE_TEMPLATE;
  399. $mesg = $outputlangs->transnoentitiesnoconv("EMailTextInvoiceValidated", $link);
  400. break;
  401. case 'BILL_PAYED':
  402. $link = '<a href="'.$urlwithroot.'/compta/facture/card.php?facid='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  403. $dir_output = $conf->facture->dir_output."/".get_exdir(0, 0, 0, 1, $object, 'invoice');
  404. $object_type = 'facture';
  405. $labeltouse = $conf->global->BILL_PAYED_TEMPLATE;
  406. $mesg = $outputlangs->transnoentitiesnoconv("EMailTextInvoicePayed", $link);
  407. break;
  408. case 'ORDER_VALIDATE':
  409. $link = '<a href="'.$urlwithroot.'/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  410. $dir_output = $conf->commande->dir_output."/".get_exdir(0, 0, 0, 1, $object, 'commande');
  411. $object_type = 'order';
  412. $labeltouse = $conf->global->ORDER_VALIDATE_TEMPLATE;
  413. $mesg = $outputlangs->transnoentitiesnoconv("EMailTextOrderValidated", $link);
  414. break;
  415. case 'PROPAL_VALIDATE':
  416. $link = '<a href="'.$urlwithroot.'/comm/propal/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  417. $dir_output = $conf->propal->multidir_output[$object->entity]."/".get_exdir(0, 0, 0, 1, $object, 'propal');
  418. $object_type = 'propal';
  419. $labeltouse = $conf->global->PROPAL_VALIDATE_TEMPLATE;
  420. $mesg = $outputlangs->transnoentitiesnoconv("EMailTextProposalValidated", $link);
  421. break;
  422. case 'PROPAL_CLOSE_SIGNED':
  423. $link = '<a href="'.$urlwithroot.'/comm/propal/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  424. $dir_output = $conf->propal->multidir_output[$object->entity]."/".get_exdir(0, 0, 0, 1, $object, 'propal');
  425. $object_type = 'propal';
  426. $labeltouse = $conf->global->PROPAL_CLOSE_SIGNED_TEMPLATE;
  427. $mesg = $outputlangs->transnoentitiesnoconv("EMailTextProposalClosedSigned", $link);
  428. break;
  429. case 'FICHINTER_ADD_CONTACT':
  430. $link = '<a href="'.$urlwithroot.'/fichinter/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  431. $dir_output = $conf->ficheinter->dir_output;
  432. $object_type = 'ficheinter';
  433. $mesg = $outputlangs->transnoentitiesnoconv("EMailTextInterventionAddedContact", $link);
  434. break;
  435. case 'FICHINTER_VALIDATE':
  436. $link = '<a href="'.$urlwithroot.'/fichinter/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  437. $dir_output = $conf->ficheinter->dir_output;
  438. $object_type = 'ficheinter';
  439. $mesg = $outputlangs->transnoentitiesnoconv("EMailTextInterventionValidated", $link);
  440. break;
  441. case 'ORDER_SUPPLIER_VALIDATE':
  442. $link = '<a href="'.$urlwithroot.'/fourn/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  443. $dir_output = $conf->fournisseur->commande->dir_output;
  444. $object_type = 'order_supplier';
  445. $mesg = $outputlangs->transnoentitiesnoconv("Hello").",\n\n";
  446. $mesg .= $outputlangs->transnoentitiesnoconv("EMailTextOrderValidatedBy", $link, $user->getFullName($outputlangs));
  447. $mesg .= "\n\n".$outputlangs->transnoentitiesnoconv("Sincerely").".\n\n";
  448. break;
  449. case 'ORDER_SUPPLIER_APPROVE':
  450. $link = '<a href="'.$urlwithroot.'/fourn/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  451. $dir_output = $conf->fournisseur->commande->dir_output;
  452. $object_type = 'order_supplier';
  453. $mesg = $outputlangs->transnoentitiesnoconv("Hello").",\n\n";
  454. $mesg .= $outputlangs->transnoentitiesnoconv("EMailTextOrderApprovedBy", $link, $user->getFullName($outputlangs));
  455. $mesg .= "\n\n".$outputlangs->transnoentitiesnoconv("Sincerely").".\n\n";
  456. break;
  457. case 'ORDER_SUPPLIER_REFUSE':
  458. $link = '<a href="'.$urlwithroot.'/fourn/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  459. $dir_output = $conf->fournisseur->commande->dir_output;
  460. $object_type = 'order_supplier';
  461. $mesg = $outputlangs->transnoentitiesnoconv("Hello").",\n\n";
  462. $mesg .= $outputlangs->transnoentitiesnoconv("EMailTextOrderRefusedBy", $link, $user->getFullName($outputlangs));
  463. $mesg .= "\n\n".$outputlangs->transnoentitiesnoconv("Sincerely").".\n\n";
  464. break;
  465. case 'SHIPPING_VALIDATE':
  466. $link = '<a href="'.$urlwithroot.'/expedition/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  467. $dir_output = $conf->expedition->dir_output."/sending/".get_exdir(0, 0, 0, 1, $object, 'shipment');
  468. $object_type = 'shipping';
  469. $labeltouse = $conf->global->SHIPPING_VALIDATE_TEMPLATE;
  470. $mesg = $outputlangs->transnoentitiesnoconv("EMailTextExpeditionValidated", $link);
  471. break;
  472. case 'EXPENSE_REPORT_VALIDATE':
  473. $link = '<a href="'.$urlwithroot.'/expensereport/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  474. $dir_output = $conf->expensereport->dir_output;
  475. $object_type = 'expensereport';
  476. $labeltouse = $conf->global->EXPENSE_REPORT_VALIDATE_TEMPLATE;
  477. $mesg = $outputlangs->transnoentitiesnoconv("EMailTextExpenseReportValidated", $link);
  478. break;
  479. case 'EXPENSE_REPORT_APPROVE':
  480. $link = '<a href="'.$urlwithroot.'/expensereport/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  481. $dir_output = $conf->expensereport->dir_output;
  482. $object_type = 'expensereport';
  483. $labeltouse = $conf->global->EXPENSE_REPORT_APPROVE_TEMPLATE;
  484. $mesg = $outputlangs->transnoentitiesnoconv("EMailTextExpenseReportApproved", $link);
  485. break;
  486. case 'HOLIDAY_VALIDATE':
  487. $link = '<a href="'.$urlwithroot.'/holiday/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  488. $dir_output = $conf->holiday->dir_output;
  489. $object_type = 'holiday';
  490. $labeltouse = $conf->global->HOLIDAY_VALIDATE_TEMPLATE;
  491. $mesg = $outputlangs->transnoentitiesnoconv("EMailTextHolidayValidated", $link);
  492. break;
  493. case 'HOLIDAY_APPROVE':
  494. $link = '<a href="'.$urlwithroot.'/holiday/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  495. $dir_output = $conf->holiday->dir_output;
  496. $object_type = 'holiday';
  497. $labeltouse = $conf->global->HOLIDAY_APPROVE_TEMPLATE;
  498. $mesg = $outputlangs->transnoentitiesnoconv("EMailTextHolidayApproved", $link);
  499. break;
  500. case 'ACTION_CREATE':
  501. $link = '<a href="'.$urlwithroot.'/comm/action/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  502. $dir_output = $conf->agenda->dir_output;
  503. $object_type = 'action';
  504. $labeltouse = $conf->global->ACTION_CREATE_TEMPLATE;
  505. $mesg = $outputlangs->transnoentitiesnoconv("EMailTextActionAdded", $link);
  506. break;
  507. }
  508. include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
  509. $formmail = new FormMail($this->db);
  510. $arraydefaultmessage = null;
  511. if (!empty($labeltouse)) $arraydefaultmessage = $formmail->getEMailTemplate($this->db, $object_type.'_send', $user, $outputlangs, 0, 1, $labeltouse);
  512. if (!empty($labeltouse) && is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) {
  513. $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $object);
  514. complete_substitutions_array($substitutionarray, $outputlangs, $object);
  515. $subject = make_substitutions($arraydefaultmessage->topic, $substitutionarray, $outputlangs);
  516. $message = make_substitutions($arraydefaultmessage->content, $substitutionarray, $outputlangs);
  517. } else {
  518. $message = $outputlangs->transnoentities("YouReceiveMailBecauseOfNotification", $application, $mysoc->name)."\n";
  519. $message .= $outputlangs->transnoentities("YouReceiveMailBecauseOfNotification2", $application, $mysoc->name)."\n";
  520. $message .= "\n";
  521. $message .= $mesg;
  522. }
  523. $ref = dol_sanitizeFileName($newref);
  524. $pdf_path = $dir_output."/".$ref.".pdf";
  525. if (!dol_is_file($pdf_path)) {
  526. // We can't add PDF as it is not generated yet.
  527. $filepdf = '';
  528. } else {
  529. $filepdf = $pdf_path;
  530. $filename_list[] = $filepdf;
  531. $mimetype_list[] = mime_content_type($filepdf);
  532. $mimefilename_list[] = $ref.".pdf";
  533. }
  534. $parameters = array('notifcode'=>$notifcode, 'sendto'=>$sendto, 'replyto'=>$replyto, 'file'=>$filename_list, 'mimefile'=>$mimetype_list, 'filename'=>$mimefilename_list);
  535. if (!isset($action)) {
  536. $action = '';
  537. }
  538. $reshook = $hookmanager->executeHooks('formatNotificationMessage', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
  539. if (empty($reshook)) {
  540. if (!empty($hookmanager->resArray['subject'])) {
  541. $subject .= $hookmanager->resArray['subject'];
  542. }
  543. if (!empty($hookmanager->resArray['message'])) {
  544. $message .= $hookmanager->resArray['message'];
  545. }
  546. }
  547. $mailfile = new CMailFile(
  548. $subject,
  549. $sendto,
  550. $replyto,
  551. $message,
  552. $filename_list,
  553. $mimetype_list,
  554. $mimefilename_list,
  555. '',
  556. '',
  557. 0,
  558. -1,
  559. '',
  560. '',
  561. $trackid,
  562. '',
  563. 'notification'
  564. );
  565. if ($mailfile->sendfile()) {
  566. if ($obj->type_target == 'touserid') {
  567. $sql = "INSERT INTO ".MAIN_DB_PREFIX."notify (daten, fk_action, fk_soc, fk_user, type, objet_type, type_target, objet_id, email)";
  568. $sql .= " VALUES ('".$this->db->idate(dol_now())."', ".$notifcodedefid.", ".($object->socid ? $object->socid : 'null').", ".$obj->cid.", '".$obj->type."', '".$object_type."', '".$obj->type_target."', ".$object->id.", '".$this->db->escape($obj->email)."')";
  569. } else {
  570. $sql = "INSERT INTO ".MAIN_DB_PREFIX."notify (daten, fk_action, fk_soc, fk_contact, type, objet_type, type_target, objet_id, email)";
  571. $sql .= " VALUES ('".$this->db->idate(dol_now())."', ".$notifcodedefid.", ".($object->socid ? $object->socid : 'null').", ".$obj->cid.", '".$obj->type."', '".$object_type."', '".$obj->type_target."', ".$object->id.", '".$this->db->escape($obj->email)."')";
  572. }
  573. if (!$this->db->query($sql)) {
  574. dol_print_error($this->db);
  575. }
  576. } else {
  577. $error++;
  578. $this->errors[] = $mailfile->error;
  579. }
  580. } else {
  581. dol_syslog("No notification sent for ".$sendto." because email is empty");
  582. }
  583. $i++;
  584. }
  585. } else {
  586. dol_syslog("No notification to thirdparty sent, nothing into notification setup for the thirdparty socid = ".(empty($object->socid) ? '' : $object->socid));
  587. }
  588. } else {
  589. $error++;
  590. $this->errors[] = $this->db->lasterror();
  591. dol_syslog("Failed to get list of notification to send ".$this->db->lasterror(), LOG_ERR);
  592. return -1;
  593. }
  594. // Check notification using fixed email
  595. if (!$error) {
  596. foreach ($conf->global as $key => $val) {
  597. $reg = array();
  598. if ($val == '' || !preg_match('/^NOTIFICATION_FIXEDEMAIL_'.$notifcode.'_THRESHOLD_HIGHER_(.*)$/', $key, $reg)) {
  599. continue;
  600. }
  601. $threshold = (float) $reg[1];
  602. if (!empty($object->total_ht) && $object->total_ht <= $threshold) {
  603. dol_syslog("A notification is requested for notifcode = ".$notifcode." but amount = ".$object->total_ht." so lower than threshold = ".$threshold.". We discard this notification");
  604. continue;
  605. }
  606. $param = 'NOTIFICATION_FIXEDEMAIL_'.$notifcode.'_THRESHOLD_HIGHER_'.$reg[1];
  607. $sendto = $conf->global->$param;
  608. $notifcodedefid = dol_getIdFromCode($this->db, $notifcode, 'c_action_trigger', 'code', 'rowid');
  609. if ($notifcodedefid <= 0) {
  610. dol_print_error($this->db, 'Failed to get id from code');
  611. }
  612. $trackid = '';
  613. $object_type = '';
  614. $link = '';
  615. $num++;
  616. $subject = '['.$mysoc->name.'] '.$langs->transnoentitiesnoconv("DolibarrNotification").($projtitle ? ' '.$projtitle : '');
  617. switch ($notifcode) {
  618. case 'BILL_VALIDATE':
  619. $link = '<a href="'.$urlwithroot.'/compta/facture/card.php?facid='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  620. $dir_output = $conf->facture->dir_output."/".get_exdir(0, 0, 0, 1, $object, 'invoice');
  621. $object_type = 'facture';
  622. $mesg = $langs->transnoentitiesnoconv("EMailTextInvoiceValidated", $link);
  623. break;
  624. case 'BILL_PAYED':
  625. $link = '<a href="'.$urlwithroot.'/compta/facture/card.php?facid='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  626. $dir_output = $conf->facture->dir_output."/".get_exdir(0, 0, 0, 1, $object, 'invoice');
  627. $object_type = 'facture';
  628. $mesg = $langs->transnoentitiesnoconv("EMailTextInvoicePayed", $link);
  629. break;
  630. case 'ORDER_VALIDATE':
  631. $link = '<a href="'.$urlwithroot.'/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  632. $dir_output = $conf->commande->dir_output."/".get_exdir(0, 0, 0, 1, $object, 'commande');
  633. $object_type = 'order';
  634. $mesg = $langs->transnoentitiesnoconv("EMailTextOrderValidated", $link);
  635. break;
  636. case 'PROPAL_VALIDATE':
  637. $link = '<a href="'.$urlwithroot.'/comm/propal/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  638. $dir_output = $conf->propal->multidir_output[$object->entity]."/".get_exdir(0, 0, 0, 1, $object, 'propal');
  639. $object_type = 'propal';
  640. $mesg = $langs->transnoentitiesnoconv("EMailTextProposalValidated", $link);
  641. break;
  642. case 'PROPAL_CLOSE_SIGNED':
  643. $link = '<a href="'.$urlwithroot.'/comm/propal/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  644. $dir_output = $conf->propal->multidir_output[$object->entity]."/".get_exdir(0, 0, 0, 1, $object, 'propal');
  645. $object_type = 'propal';
  646. $mesg = $langs->transnoentitiesnoconv("EMailTextProposalClosedSigned", $link);
  647. break;
  648. case 'FICHINTER_ADD_CONTACT':
  649. $link = '<a href="'.$urlwithroot.'/fichinter/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  650. $dir_output = $conf->ficheinter->dir_output;
  651. $object_type = 'ficheinter';
  652. $mesg = $langs->transnoentitiesnoconv("EMailTextInterventionAddedContact", $link);
  653. break;
  654. case 'FICHINTER_VALIDATE':
  655. $link = '<a href="'.$urlwithroot.'/fichinter/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  656. $dir_output = $conf->facture->dir_output;
  657. $object_type = 'ficheinter';
  658. $mesg = $langs->transnoentitiesnoconv("EMailTextInterventionValidated", $link);
  659. break;
  660. case 'ORDER_SUPPLIER_VALIDATE':
  661. $link = '<a href="'.$urlwithroot.'/fourn/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  662. $dir_output = $conf->fournisseur->commande->dir_output;
  663. $object_type = 'order_supplier';
  664. $mesg = $langs->transnoentitiesnoconv("Hello").",\n\n";
  665. $mesg .= $langs->transnoentitiesnoconv("EMailTextOrderValidatedBy", $link, $user->getFullName($langs));
  666. $mesg .= "\n\n".$langs->transnoentitiesnoconv("Sincerely").".\n\n";
  667. break;
  668. case 'ORDER_SUPPLIER_APPROVE':
  669. $link = '<a href="'.$urlwithroot.'/fourn/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  670. $dir_output = $conf->fournisseur->commande->dir_output;
  671. $object_type = 'order_supplier';
  672. $mesg = $langs->transnoentitiesnoconv("Hello").",\n\n";
  673. $mesg .= $langs->transnoentitiesnoconv("EMailTextOrderApprovedBy", $link, $user->getFullName($langs));
  674. $mesg .= "\n\n".$langs->transnoentitiesnoconv("Sincerely").".\n\n";
  675. break;
  676. case 'ORDER_SUPPLIER_APPROVE2':
  677. $link = '<a href="'.$urlwithroot.'/fourn/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  678. $dir_output = $conf->fournisseur->commande->dir_output;
  679. $object_type = 'order_supplier';
  680. $mesg = $langs->transnoentitiesnoconv("Hello").",\n\n";
  681. $mesg .= $langs->transnoentitiesnoconv("EMailTextOrderApprovedBy", $link, $user->getFullName($langs));
  682. $mesg .= "\n\n".$langs->transnoentitiesnoconv("Sincerely").".\n\n";
  683. break;
  684. case 'ORDER_SUPPLIER_REFUSE':
  685. $link = '<a href="'.$urlwithroot.'/fourn/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  686. $dir_output = $conf->fournisseur->dir_output.'/commande/';
  687. $object_type = 'order_supplier';
  688. $mesg = $langs->transnoentitiesnoconv("Hello").",\n\n";
  689. $mesg .= $langs->transnoentitiesnoconv("EMailTextOrderRefusedBy", $link, $user->getFullName($langs));
  690. $mesg .= "\n\n".$langs->transnoentitiesnoconv("Sincerely").".\n\n";
  691. break;
  692. case 'SHIPPING_VALIDATE':
  693. $link = '<a href="'.$urlwithroot.'/expedition/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  694. $dir_output = $conf->expedition->dir_output."/sending/".get_exdir(0, 0, 0, 1, $object, 'shipment');
  695. $object_type = 'order_supplier';
  696. $mesg = $langs->transnoentitiesnoconv("EMailTextExpeditionValidated", $link);
  697. break;
  698. case 'EXPENSE_REPORT_VALIDATE':
  699. $link = '<a href="'.$urlwithroot.'/expensereport/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  700. $dir_output = $conf->expensereport->dir_output;
  701. $object_type = 'expensereport';
  702. $mesg = $langs->transnoentitiesnoconv("EMailTextExpenseReportValidated", $link);
  703. break;
  704. case 'EXPENSE_REPORT_APPROVE':
  705. $link = '<a href="'.$urlwithroot.'/expensereport/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  706. $dir_output = $conf->expensereport->dir_output;
  707. $object_type = 'expensereport';
  708. $mesg = $langs->transnoentitiesnoconv("EMailTextExpenseReportApproved", $link);
  709. break;
  710. case 'HOLIDAY_VALIDATE':
  711. $link = '<a href="'.$urlwithroot.'/holiday/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  712. $dir_output = $conf->holiday->dir_output;
  713. $object_type = 'holiday';
  714. $mesg = $langs->transnoentitiesnoconv("EMailTextHolidayValidated", $link);
  715. break;
  716. case 'HOLIDAY_APPROVE':
  717. $link = '<a href="'.$urlwithroot.'/holiday/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  718. $dir_output = $conf->holiday->dir_output;
  719. $object_type = 'holiday';
  720. $mesg = $langs->transnoentitiesnoconv("EMailTextHolidayApproved", $link);
  721. break;
  722. case 'ACTION_CREATE':
  723. $link = '<a href="'.$urlwithroot.'/comm/action/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
  724. $dir_output = $conf->agenda->dir_output;
  725. $object_type = 'action';
  726. $mesg = $langs->transnoentitiesnoconv("EMailTextActionAdded", $link);
  727. break;
  728. }
  729. $ref = dol_sanitizeFileName($newref);
  730. $pdf_path = $dir_output."/".$ref."/".$ref.".pdf";
  731. if (!dol_is_file($pdf_path)) {
  732. // We can't add PDF as it is not generated yet.
  733. $filepdf = '';
  734. } else {
  735. $filepdf = $pdf_path;
  736. $filename_list[] = $pdf_path;
  737. $mimetype_list[] = mime_content_type($filepdf);
  738. $mimefilename_list[] = $ref.".pdf";
  739. }
  740. $message .= $langs->transnoentities("YouReceiveMailBecauseOfNotification2", $application, $mysoc->name)."\n";
  741. $message .= "\n";
  742. $message .= $mesg;
  743. $message = nl2br($message);
  744. // Replace keyword __SUPERVISOREMAIL__
  745. if (preg_match('/__SUPERVISOREMAIL__/', $sendto)) {
  746. $newval = '';
  747. if ($user->fk_user > 0) {
  748. $supervisoruser = new User($this->db);
  749. $supervisoruser->fetch($user->fk_user);
  750. if ($supervisoruser->email) {
  751. $newval = trim(dolGetFirstLastname($supervisoruser->firstname, $supervisoruser->lastname).' <'.$supervisoruser->email.'>');
  752. }
  753. }
  754. dol_syslog("Replace the __SUPERVISOREMAIL__ key into recipient email string with ".$newval);
  755. $sendto = preg_replace('/__SUPERVISOREMAIL__/', $newval, $sendto);
  756. $sendto = preg_replace('/,\s*,/', ',', $sendto); // in some case you can have $sendto like "email, __SUPERVISOREMAIL__ , otheremail" then you have "email, , othermail" and it's not valid
  757. $sendto = preg_replace('/^[\s,]+/', '', $sendto); // Clean start of string
  758. $sendto = preg_replace('/[\s,]+$/', '', $sendto); // Clean end of string
  759. }
  760. if ($sendto) {
  761. $parameters = array('notifcode'=>$notifcode, 'sendto'=>$sendto, 'replyto'=>$replyto, 'file'=>$filename_list, 'mimefile'=>$mimetype_list, 'filename'=>$mimefilename_list);
  762. $reshook = $hookmanager->executeHooks('formatNotificationMessage', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
  763. if (empty($reshook)) {
  764. if (!empty($hookmanager->resArray['subject'])) {
  765. $subject .= $hookmanager->resArray['subject'];
  766. }
  767. if (!empty($hookmanager->resArray['message'])) {
  768. $message .= $hookmanager->resArray['message'];
  769. }
  770. }
  771. $mailfile = new CMailFile(
  772. $subject,
  773. $sendto,
  774. $replyto,
  775. $message,
  776. $filename_list,
  777. $mimetype_list,
  778. $mimefilename_list,
  779. '',
  780. '',
  781. 0,
  782. 1,
  783. '',
  784. $trackid,
  785. '',
  786. '',
  787. 'notification'
  788. );
  789. if ($mailfile->sendfile()) {
  790. $sql = "INSERT INTO ".MAIN_DB_PREFIX."notify (daten, fk_action, fk_soc, fk_contact, type, type_target, objet_type, objet_id, email)";
  791. $sql .= " VALUES ('".$this->db->idate(dol_now())."', ".$notifcodedefid.", ".($object->socid ? $object->socid : 'null').", null, 'email', 'tofixedemail', '".$object_type."', ".$object->id.", '".$this->db->escape($conf->global->$param)."')";
  792. if (!$this->db->query($sql)) {
  793. dol_print_error($this->db);
  794. }
  795. } else {
  796. $error++;
  797. $this->errors[] = $mailfile->error;
  798. }
  799. }
  800. }
  801. }
  802. if (!$error) {
  803. return $num;
  804. } else {
  805. return -1 * $error;
  806. }
  807. }
  808. }