PageRenderTime 63ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/auto.php

https://github.com/nicdev007/sitracker
PHP | 1014 lines | 844 code | 88 blank | 82 comment | 148 complexity | d873efec626832304f7d8cca407e4421 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0, BSD-3-Clause
  1. <?php
  2. // auto.php - Regular SiT! maintenance tasks (for scheduling)
  3. //
  4. // SiT (Support Incident Tracker) - Support call tracking system
  5. // Copyright (C) 2000-2009 Salford Software Ltd. and Contributors
  6. //
  7. // This software may be used and distributed according to the terms
  8. // of the GNU General Public License, incorporated herein by reference.
  9. //
  10. // Author: Ivan Lucas <ivanlucas[at]users.sourceforge.net>
  11. // This file should be called from a cron job (or similar) to run tasks periodically
  12. require ('core.php');
  13. include_once (APPLICATION_LIBPATH . 'strings.inc.php');
  14. require_once (APPLICATION_LIBPATH . 'functions.inc.php');
  15. include_once (APPLICATION_LIBPATH . 'billing.inc.php');
  16. require_once (APPLICATION_LIBPATH . 'triggers.inc.php');
  17. populate_syslang();
  18. $crlg = "\n";
  19. /**
  20. * @author Ivan Lucas
  21. **/
  22. function saction_test()
  23. {
  24. echo "<h2>Testing testing 1 2 3.</h2>";
  25. return TRUE;
  26. }
  27. /**
  28. * Select incidents awaiting closure for more than a week where the next action time is not set or has passed
  29. * @author Ivan Lucas
  30. * @param $closure_delay int. The amount of time (in seconds) to wait before closing
  31. **/
  32. function saction_CloseIncidents($closure_delay)
  33. {
  34. $success = TRUE;
  35. global $dbIncidents, $dbUpdates, $CONFIG, $crlf, $now;
  36. if ($closure_delay < 1) $closure_delay = 554400; // Default six days and 10 hours
  37. // Code added back in to fix mark as closure incidents
  38. // http://bugs.sitracker.org/view.php?id=717
  39. $sql = "UPDATE `{$dbIncidents}` SET lastupdated='{$now}', ";
  40. $sql .= "closed='{$now}', status='".STATUS_CLOSED."', closingstatus='4', ";
  41. $sql .= "timeofnextaction='0' WHERE status='".STATUS_CLOSING."' ";
  42. $sql .= "AND (({$now} - lastupdated) > '{$closure_delay}') ";
  43. $sql .= "AND (timeofnextaction='0' OR timeofnextaction <= '{$now}')";
  44. $result = mysql_query($sql);
  45. if (mysql_error())
  46. {
  47. trigger_error(mysql_error(),E_USER_WARNING);
  48. $success = FALSE;
  49. }
  50. // Billing
  51. $sql = "SELECT id, owner, status FROM `{$dbIncidents}` WHERE status='".STATUS_CLOSING."' ";
  52. $sql .= "AND (({$now} - lastupdated) > '{$closure_delay}') ";
  53. $sql .= "AND (timeofnextaction='0' OR timeofnextaction<='{$now}') ";
  54. $result = mysql_query($sql);
  55. if (mysql_error())
  56. {
  57. trigger_error(mysql_error(),E_USER_WARNING);
  58. $success = FALSE;
  59. }
  60. while ($obj = mysql_fetch_object($result))
  61. {
  62. $bill = close_billable_incident($obj->id); // Do the close tasks if necessary
  63. if ($bill)
  64. {
  65. $sqlc = "INSERT INTO `{$dbUpdates}` (incidentid, userid, type, currentowner, currentstatus, bodytext, timestamp, nextaction, customervisibility) ";
  66. $sqlc .= "VALUES ('{$obj->id}', '0', 'closing', '{$obj->owner}', '{$obj->status}', 'Incident Closed by {$CONFIG['application_shortname']}', '{$now}', '', 'show' ) ";
  67. $resultc = mysql_query($sqlc);
  68. if (mysql_error())
  69. {
  70. trigger_error(mysql_error(),E_USER_WARNING);
  71. $success = FALSE;
  72. }
  73. }
  74. else
  75. {
  76. $success = FALSE;
  77. }
  78. }
  79. return $success;
  80. }
  81. /**
  82. * @author Ivan Lucas
  83. **/
  84. function saction_PurgeJournal()
  85. {
  86. global $dbJournal, $now, $CONFIG;
  87. $success = TRUE;
  88. $purgedate = date('YmdHis',($now - $CONFIG['journal_purge_after']));
  89. $sql = "DELETE FROM `{$dbJournal}` WHERE timestamp < $purgedate";
  90. $result = mysql_query($sql);
  91. if (mysql_error())
  92. {
  93. trigger_error(mysql_error(),E_USER_WARNING);
  94. $success = FALSE;
  95. }
  96. if ($CONFIG['debug']) //debug_log("Purged ".mysql_affected_rows()." journal entries");
  97. return $success;
  98. }
  99. /** Calculate SLA times
  100. * @author Tom Gerrard
  101. * @note Moved from htdocs/auto/timecalc.php by INL for 3.40 release
  102. **/
  103. function saction_TimeCalc()
  104. {
  105. global $now;
  106. global $dbIncidents, $dbServiceLevels, $dbMaintenance, $dbUpdates;
  107. global $GLOBALS, $CONFIG;
  108. $success = TRUE;
  109. // FIXME this should only run INSIDE the working day
  110. // FIXME ? this will not update the database fully if two SLAs have been met since last run - does it matter ?
  111. if ($CONFIG['debug']) //debug_log("Calculating SLA times");
  112. $sql = "SELECT id, title, maintenanceid, priority, slaemail, slanotice, servicelevel, status, owner ";
  113. $sql .= "FROM `{$dbIncidents}` WHERE status != ".STATUS_CLOSED." AND status != ".STATUS_CLOSING;
  114. $incident_result = mysql_query($sql);
  115. if (mysql_error())
  116. {
  117. trigger_error(mysql_error(),E_USER_WARNING);
  118. $success = FALSE;
  119. }
  120. while ($incident = mysql_fetch_array($incident_result))
  121. {
  122. // Get the service level timings for this class of incident, we may have one
  123. // from the incident itself, otherwise look at contract type
  124. if ($incident['servicelevel'] == '')
  125. {
  126. $sql = "SELECT tag FROM `{$dbServiceLevels}` s, `{$dbMaintenance}` m ";
  127. $sql .= "WHERE m.id = '{$incident['maintenanceid']}' AND s.id = m.servicelevelid";
  128. $result = mysql_query($sql);
  129. if (mysql_error()) trigger_error(mysql_error(),E_USER_WARNING);
  130. $t = mysql_fetch_row($sql);
  131. $tag = $t[0];
  132. mysql_free_result($result);
  133. }
  134. else $tag = $incident['servicelevel'];
  135. if ($CONFIG['debug']) //debug_log($incident['id']." is a $tag incident");
  136. $newReviewTime = -1;
  137. $newSlaTime = -1;
  138. $sql = "SELECT id, type, sla, timestamp, currentstatus FROM `{$dbUpdates}` WHERE incidentid='{$incident['id']}' ";
  139. $sql .=" AND type = 'slamet' ORDER BY id DESC LIMIT 1";
  140. $update_result = mysql_query($sql);
  141. if (mysql_error())
  142. {
  143. trigger_error(mysql_error(),E_USER_WARNING);
  144. $success = FALSE;
  145. }
  146. if (mysql_num_rows($update_result) != 1)
  147. {
  148. //if ($CONFIG['debug']) //debug_log("Cannot find SLA information for incident ".$incident['id'].", skipping");
  149. }
  150. else
  151. {
  152. $slaInfo = mysql_fetch_array($update_result);
  153. $newSlaTime = calculate_incident_working_time($incident['id'],$slaInfo['timestamp'],$now);
  154. if ($CONFIG['debug'])
  155. {
  156. //debug_log(" Last SLA record is ".$slaInfo['sla']." at ".date("jS F Y H:i",$slaInfo['timestamp'])." which is $newSlaTime working minutes ago");
  157. }
  158. }
  159. mysql_free_result($update_result);
  160. $sql = "SELECT id, type, sla, timestamp, currentstatus, currentowner FROM `{$dbUpdates}` WHERE incidentid='{$incident['id']}' ";
  161. $sql .= "AND type='reviewmet' ORDER BY id DESC LIMIT 1";
  162. $update_result = mysql_query($sql);
  163. if (mysql_error())
  164. {
  165. trigger_error(mysql_error(),E_USER_WARNING);
  166. $success = FALSE;
  167. }
  168. if (mysql_num_rows($update_result) != 1)
  169. {
  170. //if ($CONFIG['debug']) //debug_log("Cannot find review information for incident ".$incident['id'].", skipping");
  171. }
  172. else
  173. {
  174. $reviewInfo = mysql_fetch_array($update_result);
  175. $newReviewTime = floor($now-$reviewInfo['timestamp'])/60;
  176. if ($CONFIG['debug'])
  177. {
  178. //if ($reviewInfo['currentowner'] != 0) //debug_log("There has been no review on incident {$incident['id']}, which was opened $newReviewTime minutes ago");
  179. }
  180. trigger('TRIGGER_INCIDENT_REVIEW_DUE', array('incidentid' => $incident['id'], 'time' => $newReviewTime));
  181. }
  182. mysql_free_result($update_result);
  183. if ($newSlaTime != -1)
  184. {
  185. // Get these time of NEXT SLA requirement in minutes
  186. $coefficient = 1;
  187. $NextslaName = $GLOBALS['strSLATarget'];
  188. switch ($slaInfo['sla'])
  189. {
  190. case 'opened':
  191. $slaRequest='initial_response_mins';
  192. $NextslaName = $GLOBALS['strInitialResponse'];
  193. break;
  194. case 'initialresponse':
  195. $slaRequest='prob_determ_mins';
  196. $NextslaName = $GLOBALS['strProblemDefinition'];
  197. break;
  198. case 'probdef':
  199. $slaRequest = 'action_plan_mins';
  200. $NextslaName = $GLOBALS['strActionPlan'];
  201. break;
  202. case 'actionplan':
  203. $slaRequest = 'resolution_days';
  204. $NextslaName = $GLOBALS['strResolutionReprioritisation'];
  205. $coefficient = ($CONFIG['end_working_day'] - $CONFIG['start_working_day']) / 60;
  206. break;
  207. case 'solution':
  208. $slaRequest = 'initial_response_mins';
  209. $NextslaName = $GLOBALS['strInitialResponse'];
  210. break;
  211. }
  212. // Query the database for the next SLA and review times...
  213. $sql = "SELECT ($slaRequest*$coefficient) as 'next_sla_time', review_days ";
  214. $sql .= "FROM `{$dbServiceLevels}` WHERE tag = '$tag' AND priority = '{$incident['priority']}'";
  215. $result = mysql_query($sql);
  216. if (mysql_error())
  217. {
  218. trigger_error(mysql_error(),E_USER_WARNING);
  219. $success = FALSE;
  220. }
  221. $times = mysql_fetch_assoc($result);
  222. mysql_free_result($result);
  223. if ($CONFIG['debug'])
  224. {
  225. //debug_log("The next SLA target should be met in ".$times['next_sla_time']." minutes");
  226. //debug_log("Reviews need to be made every ".($times['review_days']*24*60)." minutes");
  227. }
  228. if ($incident['slanotice'] == 0)
  229. {
  230. //reaching SLA
  231. if ($times['next_sla_time'] > 0) $reach = $newSlaTime / $times['next_sla_time'];
  232. else $reach = 0;
  233. if ($reach >= ($CONFIG['urgent_threshold'] * 0.01))
  234. {
  235. $timetil = $times['next_sla_time']-$newSlaTime;
  236. trigger('TRIGGER_INCIDENT_NEARING_SLA', array('incidentid' => $incident['id'],
  237. 'nextslatime' => $times['next_sla_time'],
  238. 'nextsla' => $NextslaName));
  239. $sql = "UPDATE `{$dbIncidents}` SET slanotice='1' WHERE id='{$incident['id']}'";
  240. mysql_query($sql);
  241. if (mysql_error()) trigger_error(mysql_error(),E_USER_WARNING);
  242. }
  243. }
  244. }
  245. }
  246. mysql_free_result($incident_result);
  247. return $success;
  248. }
  249. function saction_SetUserStatus()
  250. {
  251. global $dbHolidays, $dbUsers, $CONFIG, $crlf;
  252. // Find users with holidays today who don't have correct status
  253. $success = TRUE;
  254. $startdate = mktime(0,0,0,date('m'),date('d'),date('Y'));
  255. $enddate = mktime(23,59,59,date('m'),date('d'),date('Y'));
  256. $sql = "SELECT * FROM `{$dbHolidays}` ";
  257. $sql .= "WHERE `date` >= FROM_UNIXTIME($startdate) AND `date` < ";
  258. $sql .= "FROM_UNIXTIME($enddate) AND (type >='".HOL_HOLIDAY."' AND type <= ".HOL_FREE.") ";
  259. $sql .= "AND (approved=".HOL_APPROVAL_GRANTED." OR approved=".HOL_APPROVAL_DENIED;
  260. $sql .= " OR approved=".HOL_APPROVAL_GRANTED_ARCHIVED;
  261. $sql .= " OR approved=".HOL_APPROVAL_DENIED_ARCHIVED.")";
  262. $result = mysql_query($sql);
  263. if (mysql_error())
  264. {
  265. $success = FALSE;
  266. trigger_error(mysql_error(),E_USER_WARNING);
  267. }
  268. while ($huser = mysql_fetch_object($result))
  269. {
  270. if ($huser->length == 'day'
  271. OR ($huser->length == 'am' AND date('H') < 12)
  272. OR ($huser->length == 'pm' AND date('H') > 12))
  273. {
  274. $currentstatus = user_status($huser->userid);
  275. $newstatus = $currentstatus;
  276. // Only enabled users
  277. if ($currentstatus > 0)
  278. {
  279. if ($huser->type == HOL_HOLIDAY AND $currentstatus != USERSTATUS_ON_HOLIDAY) $newstatus = USERSTATUS_ON_HOLIDAY;
  280. if ($huser->type == HOL_SICKNESS AND $currentstatus != USERSTATUS_ABSENT_SICK) $newstatus = USERSTATUS_ABSENT_SICK;
  281. if ($huser->type == HOL_WORKING_AWAY AND
  282. ($currentstatus != USERSTATUS_WORKING_FROM_HOME AND
  283. $currentstatus != USERSTATUS_WORKING_AWAY)) $newstatus = USERSTATUS_WORKING_AWAY;
  284. if ($huser->type == HOL_TRAINING AND $currentstatus != USERSTATUS_ON_TRAINING_COURSE) $newstatus = USERSTATUS_ON_TRAINING_COURSE;
  285. if ($huser->type == HOL_FREE AND
  286. ($currentstatus != USERSTATUS_NOT_IN_OFFICE AND
  287. $currentstatus != USERSTATUS_ABSENT_SICK)) $newstatus = USERSTATUS_ABSENT_SICK; // Compassionate
  288. }
  289. if ($newstatus != $currentstatus)
  290. {
  291. $accepting = '';
  292. switch ($newstatus)
  293. {
  294. case USERSTATUS_IN_OFFICE:
  295. $accepting = 'Yes';
  296. break;
  297. case USERSTATUS_NOT_IN_OFFICE:
  298. $accepting = 'No';
  299. break;
  300. case USERSTATUS_IN_MEETING:
  301. // don't change
  302. $accepting = '';
  303. break;
  304. case USERSTATUS_AT_LUNCH:
  305. $accepting = '';
  306. break;
  307. case USERSTATUS_ON_HOLIDAY:
  308. $accepting = 'No';
  309. break;
  310. case USERSTATUS_WORKING_FROM_HOME:
  311. $accepting = 'Yes';
  312. break;
  313. case USERSTATUS_ON_TRAINING_COURSE:
  314. $accepting = 'No';
  315. break;
  316. case USERSTATUS_ABSENT_SICK:
  317. $accepting =' No';
  318. break;
  319. case USERSTATUS_WORKING_AWAY:
  320. // don't change
  321. $accepting = '';
  322. break;
  323. default:
  324. $accepting='';
  325. }
  326. $usql = "UPDATE `{$dbUsers}` SET status='{$newstatus}'";
  327. if ($accepting != '') $usql .= ", accepting='{$accepting}'";
  328. $usql .= " WHERE id='{$huser->userid}' LIMIT 1";
  329. if ($accepting == 'No') incident_backup_switchover($huser->userid, 'no');
  330. if ($CONFIG['debug'])
  331. {
  332. //debug_log(user_realname($huser->userid).': '.userstatus_name($currentstatus).' -> '.userstatus_name($newstatus));
  333. //debug_log($usql);
  334. }
  335. mysql_query($usql);
  336. if (mysql_error())
  337. {
  338. $success = FALSE;
  339. trigger_error(mysql_error(),E_USER_WARNING);
  340. }
  341. }
  342. }
  343. }
  344. // Find users who are set away but have no entry in the holiday calendar
  345. $sql = "SELECT * FROM `{$dbUsers}` WHERE status=".USERSTATUS_ON_HOLIDAY." OR ";
  346. $sql .= "status=".USERSTATUS_ON_TRAINING_COURSE." OR ";
  347. $sql .= "status=".USERSTATUS_ABSENT_SICK." OR status=".USERSTATUS_WORKING_AWAY." ";
  348. $result = mysql_query($sql);
  349. if (mysql_error())
  350. {
  351. $success = FALSE;
  352. trigger_error(mysql_error(),E_USER_WARNING);
  353. }
  354. return $success;
  355. }
  356. /** Chase / Remind customers
  357. * @author Paul Heaney
  358. * @note Moved from htdocs/auto/chase_customer.php by INL for 3.40
  359. */
  360. function saction_ChaseCustomers()
  361. {
  362. global $CONFIG, $now, $sit;
  363. global $dbIncidents, $dbUpdates;
  364. $success = TRUE;
  365. /**
  366. * @author Paul Heaney
  367. */
  368. function not_auto_type($type)
  369. {
  370. if ($type != 'auto_chase_email' AND $type != 'auto_chase_phone' AND $type != 'auto_chase_manager')
  371. {
  372. return TRUE;
  373. }
  374. return FALSE;
  375. }
  376. if ($CONFIG['auto_chase'] == TRUE)
  377. {
  378. // if 'awaiting customer action' for more than $CONFIG['chase_email_minutes'] and NOT in an auto state, send auto email
  379. //$sql = "SELECT incidents.id, contacts.forenames,contacts.surname,contacts.id AS managerid FROM incidents,contacts WHERE status = ".STATUS_CUSTOMER." AND contacts.notify_contactid = contacts.id";
  380. $sql = "SELECT * FROM `{$dbIncidents}` AS i WHERE status = ".STATUS_CUSTOMER;
  381. $result = mysql_query($sql);
  382. if (mysql_error())
  383. {
  384. trigger_error("MySQL Query Error ".mysql_error(), E_USER_WARNING);
  385. $success = FALSE;
  386. }
  387. while ($obj = mysql_fetch_object($result))
  388. {
  389. if (!in_array($obj->maintenanceid, $CONFIG['dont_chase_maintids']))
  390. {
  391. // only annoy these people
  392. $sql_update = "SELECT * FROM `{$dbUpdates}` WHERE incidentid = {$obj->id} ORDER BY timestamp DESC LIMIT 1";
  393. $result_update = mysql_query($sql_update);
  394. if (mysql_error())
  395. {
  396. trigger_error("MySQL Query Error ".mysql_error(), E_USER_WARNING);
  397. $success = FALSE;
  398. }
  399. $obj_update = mysql_fetch_object($result_update);
  400. if ($CONFIG['chase_email_minutes'] != 0)
  401. {
  402. //if (not_auto_type($obj_update->type) AND $obj_update->timestamp <= ($now-$CONFIG['chase_email_minutes']*60))
  403. if (not_auto_type($obj_update->type) AND (($obj->timeofnextaction == 0 AND calculate_working_time($obj_update->timestamp, $now) >= $CONFIG['chase_email_minutes']) OR ($obj->timeofnextaction != 0 AND calculate_working_time($obj->timeofnextupdate, $now) >= $CONFIG['chase_email_minutes'])))
  404. {
  405. $paramarray = array('incidentid' => $obj->id, 'triggeruserid' => $sit[2]);
  406. send_email_template($CONFIG['chase_email_template'], $paramarray);
  407. $sql_insert = "INSERT INTO `{$dbUpdates}` (incidentid, userid, type, currentowner, currentstatus, bodytext, timestamp, customervisibility) VALUES ('{$obj_update->incidentid}','{$sit['2']}', 'auto_chase_email', '{$obj->owner}', '{$obj->status}', 'Sent auto chase email to customer','{$now}','show')";
  408. mysql_query($sql_insert);
  409. if (mysql_error())
  410. {
  411. trigger_error("MySQL Query Error ".mysql_error(), E_USER_ERROR);
  412. $success = FALSE;
  413. }
  414. $sql_update = "UPDATE `{$dbIncidents}` SET lastupdated = '{$now}', nextactiontime = 0 WHERE id = {$obj->id}";
  415. mysql_query($sql_update);
  416. if (mysql_error())
  417. {
  418. trigger_error("MySQL Query Error ".mysql_error(), E_USER_ERROR);
  419. $success = FALSE;
  420. }
  421. }
  422. }
  423. if ($CONFIG['chase_phone_minutes'] != 0)
  424. {
  425. //if ($obj_update->type == 'auto_chase_email' AND $obj_update->timestamp <= ($now-$CONFIG['chase_phone_minutes']*60))
  426. if ($obj_update->type == 'auto_chase_email' AND (($obj->timeofnextaction == 0 AND calculate_working_time($obj_update->timestamp, $now) >= $CONFIG['chase_phone_minutes']) OR ($obj->timeofnextaction != 0 AND calculate_working_time($obj->timeofnextupdate, $now) >= $CONFIG['chase_phone_minutes'])))
  427. {
  428. $sql_insert = "INSERT INTO `{$dbUpdates}` (incidentid, userid, type, currentowner, currentstatus, bodytext, timestamp, customervisibility) VALUES ('{$obj_update->incidentid}','{$sit['2']}','auto_chase_phone', '{$obj->owner}', '{$obj->status}', 'Status: Awaiting Customer Action -&gt; <b>Active</b><hr>Please phone the customer to get an update on this call as {$CONFIG['chase_phone_minutes']} have passed since the auto chase email was sent. Once you have done this please use the update type \"Chased customer - phone\"','{$now}','hide')";
  429. mysql_query($sql_insert);
  430. if (mysql_error())
  431. {
  432. trigger_error("MySQL Query Error ".mysql_error(), E_USER_ERROR);
  433. $success = FALSE;
  434. }
  435. $sql_update = "UPDATE `{$dbIncidents}` SET lastupdated = '{$now}', ";
  436. $sql_update .= "nextactiontime = 0, status = ".STATUS_ACTIVE." WHERE id = {$obj->id}";
  437. mysql_query($sql_update);
  438. if (mysql_error())
  439. {
  440. trigger_error("MySQL Query Error ".mysql_error(), E_USER_ERROR);
  441. $success = FALSE;
  442. }
  443. }
  444. }
  445. if ($CONFIG['chase_manager_minutes'] != 0)
  446. {
  447. //if ($obj_update->type == 'auto_chased_phone' AND $obj_update->timestamp <= ($now-$CONFIG['chase_manager_minutes']*60))
  448. if ($obj_update->type == 'auto_chased_phone' AND (($obj->timeofnextaction == 0 AND calculate_working_time($obj_update->timestamp, $now) >= $CONFIG['chase_manager_minutes']) OR ($obj->timeofnextaction != 0 AND calculate_working_time($obj->timeofnextupdate, $now) >= $CONFIG['chase_manager_minutes'])))
  449. {
  450. $update = "Status: Awaiting Customer Action -&gt; <b>Active</b><hr>";
  451. $update .= "Please phone the customers MANAGER to get an update on this call as ".$CONFIG['chase_manager_minutes']." have passed since the auto chase email was sent.<br />";
  452. $update .= "The manager is <a href='contact_details.php?id={$obj->managerid}'>{$obj->forenames} {$obj->surname}</a><br />";
  453. $update .= " Once you have done this please email the actions to the customer and select the \"Was this a customer chase?\"'";
  454. $sql_insert = "INSERT INTO `{$dbUpdates}` (incidentid, userid, type, currentowner, currentstatus, bodytext, timestamp, customervisibility) VALUES ('{$obj_update->incidentid}','{$sit['2']}','auto_chase_manager', '{$obj->owner}', '{$obj->status}', $update,'{$now}','hide')";
  455. mysql_query($sql_insert);
  456. if (mysql_error())
  457. {
  458. trigger_error("MySQL Query Error ".mysql_error(), E_USER_ERROR);
  459. $success = FALSE;
  460. }
  461. $sql_update = "UPDATE `{$dbIncidents}` SET lastupdated = '{$now}', nextactiontime = 0, status = ".STATUS_ACTIVE." WHERE id = {$obj->id}";
  462. mysql_query($sql_update);
  463. if (mysql_error())
  464. {
  465. trigger_error("MySQL Query Error ".mysql_error(), E_USER_ERROR);
  466. $success = FALSE;
  467. }
  468. }
  469. }
  470. if ($CONFIG['chase_managers_manager_minutes'] != 0)
  471. {
  472. //if ($obj_update->type == 'auto_chased_manager' AND $obj_update->timestamp <= ($now-$CONFIG['chase_managers_manager_minutes']*60))
  473. if ($obj_update->type == 'auto_chased_manager' AND (($obj->timeofnextaction == 0 AND calculate_working_time($obj_update->timestamp, $now) >= $CONFIG['chase_amanager_manager_minutes']) OR ($obj->timeofnextaction != 0 AND calculate_working_time($obj->timeofnextupdate, $now) >= $CONFIG['chase_amanager_manager_minutes'])))
  474. {
  475. $sql_insert = "INSERT INTO `{$dbUpdates}` (incidentid, userid, type, currentowner, currentstatus, bodytext, timestamp, customervisibility) VALUES ('{$obj_update->incidentid}','{$sit['2']}','auto_chase_managers_manager','{$obj->owner}', '{$obj->status}', 'Status: Awaiting Customer Action -&gt; <b>Active</b><hr>Please phone the customers managers manager to get an update on this call as {$CONFIG['chase_manager_minutes']} have passed since the auto chase email was sent. Once you have done this please email the actions to the customer and manager and select the \"Was this a manager chase?\"','{$now}','hide')";
  476. mysql_query($sql_insert);
  477. if (mysql_error())
  478. {
  479. trigger_error("MySQL Query Error ".mysql_error(), E_USER_ERROR);
  480. $success = FALSE;
  481. }
  482. $sql_update = "UPDATE `{$dbIncidents}` SET lastupdated = '{$now}', nextactiontime = 0, status = ".STATUS_ACTIVE." WHERE id = {$obj->id}";
  483. mysql_query($sql_update);
  484. if (mysql_error())
  485. {
  486. trigger_error("MySQL Query Error ".mysql_error(), E_USER_ERROR);
  487. $success = FALSE;
  488. }
  489. }
  490. }
  491. }
  492. }
  493. }
  494. return $success;
  495. }
  496. /** Check the holding queue for waiting email
  497. * @author Ivan Lucas
  498. */
  499. function saction_CheckWaitingEmail()
  500. {
  501. global $dbTempIncoming, $dbUpdates;
  502. $success = TRUE;
  503. $sql = "SELECT COUNT(ti.id), UNIX_TIMESTAMP(NOW()) - `timestamp` AS minswaiting FROM `{$dbTempIncoming}` AS ti ";
  504. $sql .= "LEFT JOIN `{$dbUpdates}` AS u ON ti.updateid = u.id GROUP BY ti.id";
  505. $result = mysql_query($sql);
  506. if (mysql_error())
  507. {
  508. trigger_error("MySQL Query Error".mysql_error(), E_USER_WARNING);
  509. $success = FALSE;
  510. }
  511. list($count, $minswaiting) = mysql_fetch_row($result);
  512. if ($count > 0)
  513. {
  514. trigger("TRIGGER_WAITING_HELD_EMAIL", array('minswaiting' => $minswaiting));
  515. }
  516. return $success;
  517. }
  518. /**
  519. * Checks for expired FTP files (where expired is before now) and removes them
  520. * @author Paul Heaney
  521. */
  522. function saction_PurgeExpiredFTPItems()
  523. {
  524. global $dbFiles, $now;
  525. $success = TRUE;
  526. // Retreieve names first so we can delete them from FTP site
  527. $sql = "SELECT * FROM `{$dbFiles}` WHERE expiry <= '{$now}' AND expiry != 0";
  528. $result = mysql_query($sql);
  529. if (mysql_error())
  530. {
  531. trigger_error("MySQL Query Error".mysql_error(), E_USER_WARNING);
  532. $success = FALSE;
  533. }
  534. if (mysql_numrows($result) > 0)
  535. {
  536. $connection = create_ftp_connection();
  537. while ($obj = mysql_fetch_object($result))
  538. {
  539. $success &= ftp_delete($connection, $obj->path."/".$obj->filename);
  540. $sqlDel = "DELETE FROM `{$dbFiles}` WHERE id = {$obj->id}";
  541. $resultdel = mysql_query($sqlDel);
  542. if (mysql_error())
  543. {
  544. trigger_error("MySQL Query Error".mysql_error(), E_USER_WARNING);
  545. $success = FALSE;
  546. }
  547. }
  548. ftp_close($connection);
  549. }
  550. return $success;
  551. }
  552. // TODO PurgeAttachments
  553. // Look for the review due trigger, where did it go
  554. /**
  555. *
  556. * @author Paul Heaney
  557. * @todo TODO document this
  558. */
  559. function saction_MailPreviousMonthsTransactions()
  560. {
  561. global $CONFIG;
  562. /*
  563. Get todays date
  564. Subtract one from the month and find last month
  565. Find the last day of last month
  566. fope(transactions.php?mode=csv&start=X&end=Y&breakdonw=yes
  567. mail to people
  568. TODO need a mechanism to subscribe to scheduled events? Could this be done with a trigger? Hmmhhhhhh
  569. */
  570. $currentmonth = date('m');
  571. $currentyear = date('y');
  572. if ($currentmonth == 1)
  573. {
  574. $currentyear--;
  575. $lastmonth = 12;
  576. }
  577. else
  578. {
  579. $lastmonth = $currentmonth - 1;
  580. }
  581. $startdate = "{$currentyear}-{$lastmonth}-01";
  582. // Find last date of previous month, 5 day an arbitary choice
  583. $lastday = date('t', strtotime('{$currentyear}-{$lastmonth}-05'));
  584. $enddate = "{$currentyear}-{$lastmonth}-{$lastday}";
  585. $csv = transactions_report('', $startdate, $enddate, '', 'csv', TRUE);
  586. $extra_headers = "Reply-To: {$CONFIG['support_email']}\nErrors-To: {$CONFIG['support_email']}\n"; // TODO should probably be different
  587. $extra_headers .= "X-Mailer: {$CONFIG['application_shortname']} {$application_version_string}/PHP " . phpversion() . "\n";
  588. $extra_headers .= "X-Originating-IP: {$_SERVER['REMOTE_ADDR']}\n";
  589. // if ($ccfield != '') $extra_headers .= "cc: $ccfield\n";
  590. // if ($bccfield != '') $extra_headers .= "Bcc: $bccfield\n";
  591. $extra_headers .= "\n"; // add an extra crlf to create a null line to separate headers from body
  592. // this appears to be required by some email clients - INL
  593. $subject = sprintf($GLOBALS['strBillableIncidentsForPeriodXtoX'], $startdate, $enddate);
  594. $bodytext = $GLOBALS['strAttachedIsBillableIncidentsForAbovePeriod'];
  595. $mime = new MIME_mail($CONFIG['support_email'], $CONFIG['billing_reports_email'], html_entity_decode($subject), $bodytext, $extra_headers, '');
  596. $mime->attach($csv, "Billable report", OCTET, BASE64, "filename=billable_incidents_{$lastmonth}_{$currentyear}.csv");
  597. return $mime->send_mail();
  598. }
  599. function saction_CheckIncomingMail()
  600. {
  601. global $CONFIG;
  602. if ($CONFIG['enable_inbound_mail'] == 'POP/IMAP')
  603. {
  604. include 'inboundemail.php';
  605. }
  606. return TRUE;
  607. }
  608. function saction_CheckTasksDue()
  609. {
  610. $rtn = TRUE;
  611. $sql = "SELECT `interval` FROM {$GLOBALS['dbScheduler']} ";
  612. $sql .= "WHERE `s.action`='CheckTasksDue'";
  613. if ($result = mysql_query($sql))
  614. {
  615. $intervalobj = mysql_fetch_object($result);
  616. // check the tasks due between now and in N minutes time,
  617. // where N is the time this action is run
  618. $format = "Y-m-d H:i:s";
  619. $startdue = date($format, $GLOBALS['now']);
  620. $enddue = date($format, $GLOBALS['now'] + $intervalobj->interval);
  621. $sql = "SELECT * FROM {$GLOBALS['dbTasks']} ";
  622. $sql .= "WHERE duedate > {$startdue} AND duedate < {$enddue} ";
  623. if ($result = mysql_query($sql))
  624. {
  625. while ($row = mysql_fetch_object($result))
  626. {
  627. trigger('TRIGGER_TASK_DUE', array('taskid' => $row->id));
  628. }
  629. }
  630. }
  631. return $rtn;
  632. }
  633. /**
  634. * Perform the periodic sync of existing user and contact details from LDAP
  635. * @author Paul Heaney
  636. * @note This function does not create users or contacts it simply updates existing
  637. * @note details.
  638. */
  639. function saction_ldapSync()
  640. {
  641. global $CONFIG;
  642. $success = FALSE;
  643. if ($CONFIG['use_ldap'])
  644. {
  645. $ldap_conn = ldapOpen();
  646. if ($ldap_conn)
  647. {
  648. // NOTE TODO FIXME would be more optimal to pass the user type into the create as in the case where the group membership isn't stored its looked up again
  649. // Search for members of each group and then unique the members and loop through
  650. // Populate an array ($users) with a list of SIT users in LDAP
  651. // Only want GROUPS
  652. $filter = "(objectClass={$CONFIG['ldap_grpobjecttype']})";
  653. $attributesToGet = array($CONFIG['ldap_grpattributegrp']);
  654. $users = array();
  655. $userGrps = array($CONFIG['ldap_admin_group'], $CONFIG['ldap_manager_group'], $CONFIG['ldap_user_group'] );
  656. foreach ($userGrps AS $grp)
  657. {
  658. if (!empty($grp))
  659. {
  660. $sr = ldap_search($ldap_conn, $grp, $filter, $attributesToGet);
  661. if (ldap_count_entries($ldap_conn, $sr) != 1)
  662. {
  663. trigger_error ("Group {$grp} not found in LDAP");
  664. }
  665. else
  666. {
  667. $entry = ldap_first_entry($ldap_conn, $sr);
  668. $attributes = ldap_get_attributes($ldap_conn, $entry);
  669. for ($i = 0; $i < $attributes[$CONFIG['ldap_grpattributegrp']]['count']; $i++)
  670. {
  671. $member = $attributes[$CONFIG['ldap_grpattributegrp']][$i];
  672. if (endsWith(strtolower($member), strtolower($CONFIG['ldap_user_base'])) AND $CONFIG['ldap_grpfulldn'])
  673. {
  674. $users[$member] = $member;
  675. }
  676. elseif (!$CONFIG['ldap_grpfulldn'])
  677. {
  678. $users[$member] = $member;
  679. }
  680. }
  681. }
  682. }
  683. }
  684. // Populate an array with the LDAP users already in the SiT database
  685. $sit_db_users = array();
  686. $sql = "SELECT id, username, status FROM `{$GLOBALS['dbUsers']}` WHERE user_source = 'ldap'";
  687. $result = mysql_query($sql);
  688. if (mysql_error()) trigger_error("MySQL Query Error".mysql_error(), E_USER_WARNING);
  689. if (mysql_num_rows($result) > 0)
  690. {
  691. while ($obj = mysql_fetch_object($result))
  692. {
  693. $user_obj = new User();
  694. $user_obj->id = $obj->id;
  695. $user_obj->username = $obj->username;
  696. $user_obj->status = $obj->status;
  697. $sit_db_users[$obj->username] = $user_obj;
  698. }
  699. }
  700. foreach ($users AS $u)
  701. {
  702. $e = ldap_getDetails($u, FALSE, $ldap_conn);
  703. if ($e)
  704. {
  705. $user_attributes = ldap_get_attributes($ldap_conn, $e);
  706. debug_log("user attributes: ".print_r($user_attributes, true), TRUE);
  707. debug_log("db users: ".print_r($sit_db_users, true), TRUE);
  708. // If the directory supports disabling of users
  709. if (!empty($CONFIG['ldap_logindisabledattribute']))
  710. {
  711. if ($sit_db_users[$user_attributes[$CONFIG['ldap_userattribute']][0]]->status === USERSTATUS_ACCOUNT_DISABLED)
  712. {
  713. // User is disabled in the SIT db, check to see if we need to re-enable
  714. if (!empty($user_attributes[$CONFIG['ldap_logindisabledattribute']]))
  715. {
  716. if (strtolower($user_attributes[$CONFIG['ldap_logindisabledattribute']][0]) != strtolower($CONFIG['ldap_logindisabledvalue']))
  717. {
  718. // The user is enabled in LDAP so we want to enable
  719. debug_log("Re-enabling user '{$u}' in the SiT users database", TRUE);
  720. $sit_db_users[$user_attributes[$CONFIG['ldap_userattribute']][0]]->status = $CONFIG['ldap_default_user_status'];
  721. $sit_db_users[$user_attributes[$CONFIG['ldap_userattribute']][0]]->edit();
  722. }
  723. }
  724. }
  725. else
  726. {
  727. // User is not disabled in the SiT database, check to see if we need to disable
  728. if (strtolower($user_attributes[$CONFIG['ldap_logindisabledattribute']][0]) == strtolower($CONFIG['ldap_logindisabledvalue']))
  729. {
  730. // User is disabled in LDAP so we want to disable
  731. $sit_db_users[$user_attributes[$CONFIG['ldap_userattribute']][0]]->disable();
  732. }
  733. }
  734. }
  735. $userid = 0;
  736. if (!empty($sit_db_users[$user_attributes[$CONFIG['ldap_userattribute']][0]]))
  737. {
  738. $userid = $sit_db_users[$user_attributes[$CONFIG['ldap_userattribute']][0]]->id;
  739. unset ($sit_db_users[$user_attributes[$CONFIG['ldap_userattribute']][0]]);
  740. }
  741. if (!ldap_storeDetails('', $userid, TRUE, TRUE, $ldap_conn, $user_attributes))
  742. {
  743. trigger_error("Failed to store details for userid {$userid}", E_USER_WARNING);
  744. $success = FALSE;
  745. }
  746. else
  747. {
  748. $success = TRUE;
  749. }
  750. }
  751. else
  752. {
  753. debug_log ("Failed to get details for {$u}");
  754. }
  755. }
  756. // Disable users we no longer know about
  757. // TODO reassign incidents?
  758. foreach ($sit_db_users AS $u)
  759. {
  760. debug_log ("Disabling {$u->username}");
  761. $u->disable();
  762. }
  763. /** CONTACTS */
  764. $contacts = array();
  765. if (!empty($CONFIG["ldap_customer_group"]))
  766. {
  767. debug_log ("CONTACTS");
  768. $sr = ldap_search($ldap_conn, $CONFIG["ldap_customer_group"], $filter, $attributesToGet);
  769. if (ldap_count_entries($ldap_conn, $sr) != 1)
  770. {
  771. trigger_error ("No contact group found in LDAP");
  772. }
  773. else
  774. {
  775. $entry = ldap_first_entry($ldap_conn, $sr);
  776. $attributes = ldap_get_attributes($ldap_conn, $entry);
  777. for ($i = 0; $i < $attributes[$CONFIG['ldap_grpattributegrp']]['count']; $i++)
  778. {
  779. $member = $attributes[$CONFIG['ldap_grpattributegrp']][$i];
  780. if (endsWith(strtolower($member), strtolower($CONFIG['ldap_user_base'])) AND $CONFIG['ldap_grpfulldn'])
  781. {
  782. $contacts[$member] = $member;
  783. }
  784. elseif (!$CONFIG['ldap_grpfulldn'])
  785. {
  786. $contacts[$member] = $member;
  787. }
  788. }
  789. }
  790. $sit_db_contacts = array();
  791. $sql = "SELECT id, username, active FROM `{$GLOBALS['dbContacts']}` WHERE contact_source = 'ldap'";
  792. $result = mysql_query($sql);
  793. if (mysql_error()) trigger_error("MySQL Query Error".mysql_error(), E_USER_WARNING);
  794. if (mysql_num_rows($result) > 0)
  795. {
  796. while ($obj = mysql_fetch_object($result))
  797. {
  798. $c = new Contact();
  799. $c->id = $obj->id;
  800. $c->username = $obj->username;
  801. $c->status = $obj->active;
  802. $sit_db_contacts[$c->username] = $c;
  803. }
  804. }
  805. foreach ($contacts AS $c)
  806. {
  807. $e = ldap_getDetails($c, FALSE, $ldap_conn);
  808. if ($e)
  809. {
  810. $contact_attributes = ldap_get_attributes($ldap_conn, $e);
  811. if (isset($CONFIG['ldap_logindisabledattribute']))
  812. {
  813. // Directory supports disabling
  814. if ($sit_db_contacts[$contact_attributes[$CONFIG['ldap_userattribute']][0]]->status == 'false')
  815. {
  816. // User disabled in SIT check if needs renameding
  817. if (!empty($contact_attributes[$CONFIG['ldap_logindisabledattribute']]))
  818. {
  819. if (strtolower($contact_attributes[$CONFIG['ldap_logindisabledattribute']][0]) != strtolower($CONFIG['ldap_logindisabledvalue']))
  820. {
  821. // We want to enable
  822. $sit_db_contacts[$contact_attributes[$CONFIG['ldap_userattribute']][0]]->active = 'true';
  823. $sit_db_contacts[$contact_attributes[$CONFIG['ldap_userattribute']][0]]->edit();
  824. }
  825. }
  826. }
  827. elseif (!empty($contact_attributes[$CONFIG['ldap_logindisabledattribute']]))
  828. {
  829. // User not disabled in SiT though attribite is available to us
  830. if (strtolower($contact_attributes[$CONFIG['ldap_logindisabledattribute']][0]) == strtolower($CONFIG['ldap_logindisabledvalue']))
  831. {
  832. // We want to disable
  833. $sit_db_contacts[$contact_attributes[$CONFIG['ldap_userattribute']][0]]->disable();
  834. }
  835. }
  836. }
  837. $contactid = 0;
  838. if (!empty($sit_db_contacts[$contact_attributes[$CONFIG['ldap_userattribute']][0]]))
  839. {
  840. $contactid = $sit_db_contacts[$contact_attributes[$CONFIG['ldap_userattribute']][0]]->id;
  841. unset ($sit_db_contacts[$contact_attributes[$CONFIG['ldap_userattribute']][0]]);
  842. }
  843. if (!ldap_storeDetails('', $contactid, FALSE, TRUE, $ldap_conn, $contact_attributes))
  844. {
  845. trigger_error("Failed to store details for userid {$contactid}", E_USER_WARNING);
  846. $success = FALSE;
  847. }
  848. }
  849. }
  850. // Disable users we no longer know about
  851. // TODO reassign incidents?
  852. foreach ($sit_db_contacts AS $c)
  853. {
  854. debug_log ("Disabling {$c->username}", TRUE);
  855. $c->disable();
  856. }
  857. }
  858. }
  859. }
  860. else
  861. {
  862. $success = TRUE;
  863. }
  864. return $success;
  865. }
  866. // =======================================================================================
  867. $actions = schedule_actions_due();
  868. if ($actions !== FALSE)
  869. {
  870. foreach ($actions AS $action => $params)
  871. {
  872. $fn = "saction_{$action}";
  873. if ($verbose)
  874. echo "<strong>{$fn}()</strong> ";
  875. // Possibly initiate a trigger here named TRIGGER_SCHED_{$action} ?
  876. if (function_exists($fn))
  877. {
  878. $success = $fn($params);
  879. schedule_action_done($action, $success);
  880. }
  881. else schedule_action_done($action, FALSE);
  882. if ($success && $verbose)
  883. echo "TRUE<br />";
  884. elseif ($verbose)
  885. echo "FALSE<br />";
  886. }
  887. }
  888. plugin_do('automata');
  889. ?>