PageRenderTime 177ms CodeModel.GetById 35ms RepoModel.GetById 9ms app.codeStats 1ms

/plugins/cerberusweb.reports/api/App.php

https://github.com/stolf/cerb4
PHP | 2160 lines | 1598 code | 479 blank | 83 comment | 171 complexity | 252eac9673e4b301c28357c5f9c66f18 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. abstract class Extension_Report extends DevblocksExtension {
  3. function __construct($manifest) {
  4. parent::DevblocksExtension($manifest);
  5. }
  6. function render() {
  7. // Overload
  8. }
  9. };
  10. abstract class Extension_ReportGroup extends DevblocksExtension {
  11. function __construct($manifest) {
  12. parent::DevblocksExtension($manifest);
  13. }
  14. };
  15. class ChReportGroupTickets extends Extension_ReportGroup {
  16. function __construct($manifest) {
  17. parent::__construct($manifest);
  18. }
  19. };
  20. class ChReportGroupWorkers extends Extension_ReportGroup {
  21. function __construct($manifest) {
  22. parent::__construct($manifest);
  23. }
  24. };
  25. class ChReportGroupGroups extends Extension_ReportGroup {
  26. function __construct($manifest) {
  27. parent::__construct($manifest);
  28. }
  29. };
  30. class ChReportGroupCustomFields extends Extension_ReportGroup {
  31. const ID = 'report.group.custom_fields';
  32. function __construct($manifest) {
  33. parent::__construct($manifest);
  34. }
  35. };
  36. class ChReportGroupOrgs extends Extension_ReportGroup {
  37. function __construct($manifest) {
  38. parent::__construct($manifest);
  39. }
  40. };
  41. class ChReportGroupSpam extends Extension_ReportGroup {
  42. function __construct($manifest) {
  43. parent::__construct($manifest);
  44. }
  45. };
  46. class ChReportCustomFieldUsage extends Extension_Report {
  47. private $tpl_path = null;
  48. function __construct($manifest) {
  49. parent::__construct($manifest);
  50. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  51. }
  52. function render() {
  53. $tpl = DevblocksPlatform::getTemplateService();
  54. $tpl->cache_lifetime = "0";
  55. $tpl->assign('path', $this->tpl_path);
  56. // Custom Field sources (tickets, orgs, etc.)
  57. $source_manifests = DevblocksPlatform::getExtensions('cerberusweb.fields.source', false);
  58. uasort($source_manifests, create_function('$a, $b', "return strcasecmp(\$a->name,\$b->name);\n"));
  59. $tpl->assign('source_manifests', $source_manifests);
  60. // Custom Fields
  61. $custom_fields = DAO_CustomField::getAll();
  62. $tpl->assign('custom_fields', $custom_fields);
  63. $tpl->display('file:' . $this->tpl_path . '/reports/custom_fields/usage/index.tpl');
  64. }
  65. private function _getValueCounts($field_id) {
  66. $db = DevblocksPlatform::getDatabaseService();
  67. // Selected custom field
  68. if(null == ($field = DAO_CustomField::get($field_id)))
  69. return;
  70. if(null == ($table = DAO_CustomFieldValue::getValueTableName($field_id)))
  71. return;
  72. $sql = sprintf("SELECT field_value, count(field_value) AS hits ".
  73. "FROM %s ".
  74. "WHERE source_extension = %s ".
  75. "AND field_id = %d ".
  76. "GROUP BY field_value",
  77. $table,
  78. $db->qstr($field->source_extension),
  79. $field->id
  80. );
  81. $rs_values = $db->Execute($sql);
  82. $value_counts = array();
  83. while(!$rs_values->EOF) {
  84. $value = $rs_values->fields['field_value'];
  85. $hits = intval($rs_values->fields['hits']);
  86. $value_counts[$value] = intval($hits);
  87. $rs_values->MoveNext();
  88. }
  89. arsort($value_counts);
  90. return $value_counts;
  91. }
  92. function getReportAction() {
  93. @$field_id = DevblocksPlatform::importGPC($_REQUEST['field_id'],'integer',0);
  94. $tpl = DevblocksPlatform::getTemplateService();
  95. $tpl->cache_lifetime = "0";
  96. $tpl->assign('path', $this->tpl_path);
  97. // Custom Field sources (tickets, orgs, etc.)
  98. $source_manifests = DevblocksPlatform::getExtensions('cerberusweb.fields.source', false);
  99. uasort($source_manifests, create_function('$a, $b', "return strcasecmp(\$a->name,\$b->name);\n"));
  100. $tpl->assign('source_manifests', $source_manifests);
  101. $field = DAO_CustomField::get($field_id);
  102. $tpl->assign('field', $field);
  103. $value_counts = self::_getValueCounts($field_id);
  104. $tpl->assign('value_counts', $value_counts);
  105. $tpl->display('file:' . $this->tpl_path . '/reports/custom_fields/usage/html.tpl');
  106. }
  107. function getChartAction() {
  108. @$field_id = DevblocksPlatform::importGPC($_REQUEST['field_id'],'integer',0);
  109. @$countonly = DevblocksPlatform::importGPC($_REQUEST['countonly'],'integer',0);
  110. $value_counts = self::_getValueCounts($field_id);
  111. if($countonly) {
  112. echo count($value_counts);
  113. return;
  114. }
  115. if(is_array($value_counts))
  116. foreach($value_counts as $value => $count) {
  117. echo $value, "\t", $count . "\n";
  118. }
  119. }
  120. };
  121. class ChReportGroupRoster extends Extension_Report {
  122. private $tpl_path = null;
  123. function __construct($manifest) {
  124. parent::__construct($manifest);
  125. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  126. }
  127. function render() {
  128. $tpl = DevblocksPlatform::getTemplateService();
  129. $tpl->cache_lifetime = "0";
  130. $tpl->assign('path', $this->tpl_path);
  131. $rosters = DAO_Group::getRosters();
  132. $tpl->assign('rosters', $rosters);
  133. $groups = DAO_Group::getAll();
  134. $tpl->assign('groups', $groups);
  135. $workers = DAO_Worker::getAll();
  136. $tpl->assign('workers', $workers);
  137. $tpl->display('file:' . $this->tpl_path . '/reports/group/group_roster/index.tpl');
  138. }
  139. };
  140. class ChReportNewTickets extends Extension_Report {
  141. private $tpl_path = null;
  142. function __construct($manifest) {
  143. parent::__construct($manifest);
  144. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  145. }
  146. function render() {
  147. $tpl = DevblocksPlatform::getTemplateService();
  148. $tpl->cache_lifetime = "0";
  149. $tpl->assign('path', $this->tpl_path);
  150. $tpl->assign('start', '-30 days');
  151. $tpl->assign('end', 'now');
  152. $db = DevblocksPlatform::getDatabaseService();
  153. // Year shortcuts
  154. $years = array();
  155. $sql = "SELECT date_format(from_unixtime(created_date),'%Y') as year FROM ticket WHERE created_date > 0 GROUP BY year having year <= date_format(now(),'%Y') ORDER BY year desc limit 0,10";
  156. $rs = $db->query($sql);
  157. if(is_a($rs,'ADORecordSet'))
  158. while(!$rs->EOF) {
  159. $years[] = intval($rs->fields['year']);
  160. $rs->MoveNext();
  161. }
  162. $tpl->assign('years', $years);
  163. $tpl->display('file:' . $this->tpl_path . '/reports/ticket/new_tickets/index.tpl');
  164. }
  165. function getNewTicketsReportAction() {
  166. @$age = DevblocksPlatform::importGPC($_REQUEST['age'],'string','30d');
  167. $db = DevblocksPlatform::getDatabaseService();
  168. $tpl = DevblocksPlatform::getTemplateService();
  169. $tpl->cache_lifetime = "0";
  170. $tpl->assign('path', $this->tpl_path);
  171. // import dates from form
  172. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  173. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  174. // use date range if specified, else use duration prior to now
  175. $start_time = 0;
  176. $end_time = 0;
  177. if (empty($start) && empty($end)) {
  178. $start = "-30 days";
  179. $end = "now";
  180. $start_time = strtotime($start);
  181. $end_time = strtotime($end);
  182. } else {
  183. $start_time = strtotime($start);
  184. $end_time = strtotime($end);
  185. }
  186. if($start_time === false || $end_time === false) {
  187. $start = "-30 days";
  188. $end = "now";
  189. $start_time = strtotime($start);
  190. $end_time = strtotime($end);
  191. $tpl->assign('invalidDate', true);
  192. }
  193. // reload variables in template
  194. $tpl->assign('start', $start);
  195. $tpl->assign('end', $end);
  196. $tpl->assign('age_dur', abs(floor(($start_time - $end_time)/86400)));
  197. // Top Buckets
  198. $groups = DAO_Group::getAll();
  199. $tpl->assign('groups', $groups);
  200. $group_buckets = DAO_Bucket::getTeams();
  201. $tpl->assign('group_buckets', $group_buckets);
  202. $sql = sprintf("SELECT count(*) AS hits, team_id, category_id ".
  203. "FROM ticket ".
  204. "WHERE created_date > %d AND created_date <= %d ".
  205. "AND is_deleted = 0 ".
  206. "AND spam_score < 0.9000 ".
  207. "AND spam_training != 'S' ".
  208. "GROUP BY team_id, category_id ",
  209. $start_time,
  210. $end_time
  211. );
  212. $rs_buckets = $db->Execute($sql);
  213. $group_counts = array();
  214. while(!$rs_buckets->EOF) {
  215. $team_id = intval($rs_buckets->fields['team_id']);
  216. $category_id = intval($rs_buckets->fields['category_id']);
  217. $hits = intval($rs_buckets->fields['hits']);
  218. if(!isset($group_counts[$team_id]))
  219. $group_counts[$team_id] = array();
  220. $group_counts[$team_id][$category_id] = $hits;
  221. @$group_counts[$team_id]['total'] = intval($group_counts[$team_id]['total']) + $hits;
  222. $rs_buckets->MoveNext();
  223. }
  224. $tpl->assign('group_counts', $group_counts);
  225. $tpl->display('file:' . $this->tpl_path . '/reports/ticket/new_tickets/html.tpl');
  226. }
  227. function getTicketChartDataAction() {
  228. // import dates from form
  229. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  230. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  231. @$countonly = DevblocksPlatform::importGPC($_REQUEST['countonly'],'integer',0);
  232. // use date range if specified, else use duration prior to now
  233. $start_time = 0;
  234. $end_time = 0;
  235. if (empty($start) && empty($end)) {
  236. $start = "-30 days";
  237. $end = "now";
  238. $start_time = strtotime($start);
  239. $end_time = strtotime($end);
  240. } else {
  241. $start_time = strtotime($start);
  242. $end_time = strtotime($end);
  243. }
  244. $db = DevblocksPlatform::getDatabaseService();
  245. $groups = DAO_Group::getAll();
  246. $sql = sprintf("SELECT team.id as group_id, ".
  247. "count(*) as hits ".
  248. "FROM ticket t inner join team on t.team_id = team.id ".
  249. "WHERE t.created_date > %d ".
  250. "AND t.created_date <= %d ".
  251. "AND t.is_deleted = 0 ".
  252. "AND t.spam_score < 0.9000 ".
  253. "AND t.spam_training != 'S' ".
  254. "GROUP BY group_id ORDER by team.name desc ",
  255. $start_time,
  256. $end_time
  257. );
  258. $rs = $db->Execute($sql);
  259. if($countonly) {
  260. echo intval($rs->RecordCount());
  261. return;
  262. }
  263. if(is_a($rs,'ADORecordSet'))
  264. while(!$rs->EOF) {
  265. $hits = intval($rs->fields['hits']);
  266. $group_id = $rs->fields['group_id'];
  267. echo $groups[$group_id]->name, "\t", $hits . "\n";
  268. $rs->MoveNext();
  269. }
  270. }
  271. }
  272. class ChReportWorkerReplies extends Extension_Report {
  273. private $tpl_path = null;
  274. function __construct($manifest) {
  275. parent::__construct($manifest);
  276. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  277. }
  278. function render() {
  279. $tpl = DevblocksPlatform::getTemplateService();
  280. $tpl->cache_lifetime = "0";
  281. $tpl->assign('path', $this->tpl_path);
  282. $tpl->assign('start', '-30 days');
  283. $tpl->assign('end', 'now');
  284. $db = DevblocksPlatform::getDatabaseService();
  285. // Years
  286. $years = array();
  287. $sql = "SELECT date_format(from_unixtime(created_date),'%Y') as year FROM message WHERE created_date > 0 AND is_outgoing = 1 GROUP BY year having year <= date_format(now(),'%Y') ORDER BY year desc limit 0,10";
  288. $rs = $db->query($sql);
  289. if(is_a($rs,'ADORecordSet'))
  290. while(!$rs->EOF) {
  291. $years[] = intval($rs->fields['year']);
  292. $rs->MoveNext();
  293. }
  294. $tpl->assign('years', $years);
  295. $tpl->display('file:' . $this->tpl_path . '/reports/worker/worker_replies/index.tpl');
  296. }
  297. function getWorkerRepliesReportAction() {
  298. @$age = DevblocksPlatform::importGPC($_REQUEST['age'],'string', '30d');
  299. $db = DevblocksPlatform::getDatabaseService();
  300. $tpl = DevblocksPlatform::getTemplateService();
  301. $tpl->cache_lifetime = "0";
  302. $tpl->assign('path', $this->tpl_path);
  303. // import dates from form
  304. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  305. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  306. // use date range if specified, else use duration prior to now
  307. $start_time = 0;
  308. $end_time = 0;
  309. if (empty($start) && empty($end)) {
  310. $start = "-30 days";
  311. $end = "now";
  312. $start_time = strtotime($start);
  313. $end_time = strtotime($end);
  314. } else {
  315. $start_time = strtotime($start);
  316. $end_time = strtotime($end);
  317. }
  318. if($start_time === false || $end_time === false) {
  319. $start = "-30 days";
  320. $end = "now";
  321. $start_time = strtotime($start);
  322. $end_time = strtotime($end);
  323. $tpl->assign('invalidDate', true);
  324. }
  325. // reload variables in template
  326. $tpl->assign('start', $start);
  327. $tpl->assign('end', $end);
  328. $tpl->assign('age_dur', abs(floor(($start_time - $end_time)/86400)));
  329. // Top Workers
  330. $workers = DAO_Worker::getAll();
  331. $tpl->assign('workers', $workers);
  332. $groups = DAO_Group::getAll();
  333. $tpl->assign('groups', $groups);
  334. $sql = sprintf("SELECT count(*) AS hits, t.team_id, m.worker_id ".
  335. "FROM message m ".
  336. "INNER JOIN ticket t ON (t.id=m.ticket_id) ".
  337. "WHERE m.created_date > %d AND m.created_date <= %d ".
  338. "AND m.is_outgoing = 1 ".
  339. "AND t.is_deleted = 0 ".
  340. "GROUP BY t.team_id, m.worker_id ",
  341. $start_time,
  342. $end_time
  343. );
  344. $rs_workers = $db->Execute($sql);
  345. $worker_counts = array();
  346. while(!$rs_workers->EOF) {
  347. $hits = intval($rs_workers->fields['hits']);
  348. $team_id = intval($rs_workers->fields['team_id']);
  349. $worker_id = intval($rs_workers->fields['worker_id']);
  350. if(!isset($worker_counts[$worker_id]))
  351. $worker_counts[$worker_id] = array();
  352. $worker_counts[$worker_id][$team_id] = $hits;
  353. @$worker_counts[$worker_id]['total'] = intval($worker_counts[$worker_id]['total']) + $hits;
  354. $rs_workers->MoveNext();
  355. }
  356. $tpl->assign('worker_counts', $worker_counts);
  357. $tpl->display('file:' . $this->tpl_path . '/reports/worker/worker_replies/html.tpl');
  358. }
  359. function getWorkerRepliesChartAction() {
  360. header("content-type: text/plain");
  361. $db = DevblocksPlatform::getDatabaseService();
  362. // import dates from form
  363. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  364. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  365. @$countonly = DevblocksPlatform::importGPC($_REQUEST['countonly'],'integer',0);
  366. // use date range if specified, else use duration prior to now
  367. $start_time = 0;
  368. $end_time = 0;
  369. if (empty($start) && empty($end)) {
  370. $start = "-30 days";
  371. $end = "now";
  372. $start_time = strtotime($start);
  373. $end_time = strtotime($end);
  374. } else {
  375. $start_time = strtotime($start);
  376. $end_time = strtotime($end);
  377. }
  378. // Top Workers
  379. $workers = DAO_Worker::getAll();
  380. $sql = sprintf("SELECT count(*) AS hits, m.worker_id ".
  381. "FROM message m ".
  382. "INNER JOIN ticket t ON (t.id=m.ticket_id) ".
  383. "INNER JOIN worker w ON w.id=m.worker_id ".
  384. "WHERE m.created_date > %d AND m.created_date <= %d ".
  385. "AND m.is_outgoing = 1 ".
  386. "AND t.is_deleted = 0 ".
  387. "GROUP BY m.worker_id ORDER BY w.last_name DESC ",
  388. $start_time,
  389. $end_time
  390. );
  391. $rs_workers = $db->Execute($sql); /* @var $rs_workers ADORecordSet */
  392. if($countonly) {
  393. echo intval($rs_workers->RecordCount());
  394. return;
  395. }
  396. $worker_counts = array();
  397. while(!$rs_workers->EOF) {
  398. $hits = intval($rs_workers->fields['hits']);
  399. $worker_id = intval($rs_workers->fields['worker_id']);
  400. if(isset($workers[$worker_id]))
  401. echo $workers[$worker_id]->getName() , "\t" , $hits , "\n";
  402. $rs_workers->MoveNext();
  403. }
  404. }
  405. }
  406. class ChReportOrgSharedEmailDomains extends Extension_Report {
  407. private $tpl_path = null;
  408. function __construct($manifest) {
  409. parent::__construct($manifest);
  410. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  411. }
  412. function render() {
  413. $tpl = DevblocksPlatform::getTemplateService();
  414. $tpl->cache_lifetime = "0";
  415. $tpl->assign('path', $this->tpl_path);
  416. $db = DevblocksPlatform::getDatabaseService();
  417. $sql = sprintf("SELECT count(DISTINCT a.contact_org_id) AS num_orgs, substring(a.email,locate('@',a.email)+1) AS domain ".
  418. "FROM address a ".
  419. "INNER JOIN contact_org o ON (a.contact_org_id=o.id) ".
  420. "WHERE a.contact_org_id != 0 ".
  421. "GROUP BY domain ".
  422. "HAVING num_orgs > 1 ".
  423. "ORDER BY num_orgs desc ".
  424. "LIMIT 0,100"
  425. );
  426. $rs = $db->Execute($sql);
  427. $top_domains = array();
  428. if(is_a($rs,'ADORecordSet'))
  429. while(!$rs->EOF) {
  430. $top_domains[$rs->fields['domain']] = intval($rs->fields['num_orgs']);
  431. $rs->MoveNext();
  432. }
  433. $tpl->assign('top_domains', $top_domains);
  434. $tpl->display('file:' . $this->tpl_path . '/reports/org/shared_email_domains/index.tpl');
  435. }
  436. };
  437. class ChReportSpamWords extends Extension_Report {
  438. private $tpl_path = null;
  439. function __construct($manifest) {
  440. parent::__construct($manifest);
  441. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  442. }
  443. function render() {
  444. $tpl = DevblocksPlatform::getTemplateService();
  445. $tpl->cache_lifetime = "0";
  446. $tpl->assign('path', $this->tpl_path);
  447. $db = DevblocksPlatform::getDatabaseService();
  448. $sql = "SELECT spam, nonspam FROM bayes_stats";
  449. if(null != ($row = $db->GetRow($sql))) {
  450. $num_spam = $row['spam'];
  451. $num_nonspam = $row['nonspam'];
  452. }
  453. $tpl->assign('num_spam', intval($num_spam));
  454. $tpl->assign('num_nonspam', intval($num_nonspam));
  455. $top_spam_words = array();
  456. $top_nonspam_words = array();
  457. $sql = "SELECT word,spam,nonspam FROM bayes_words ORDER BY spam desc LIMIT 0,100";
  458. $rs_spam = $db->Execute($sql);
  459. while(!$rs_spam->EOF) {
  460. $top_spam_words[$rs_spam->fields['word']] = array($rs_spam->fields['spam'], $rs_spam->fields['nonspam']);
  461. $rs_spam->MoveNext();
  462. }
  463. $tpl->assign('top_spam_words', $top_spam_words);
  464. $sql = "SELECT word,spam,nonspam FROM bayes_words ORDER BY nonspam desc LIMIT 0,100";
  465. $rs_nonspam = $db->Execute($sql);
  466. while(!$rs_nonspam->EOF) {
  467. $top_nonspam_words[$rs_nonspam->fields['word']] = array($rs_nonspam->fields['spam'], $rs_nonspam->fields['nonspam']);
  468. $rs_nonspam->MoveNext();
  469. }
  470. $tpl->assign('top_nonspam_words', $top_nonspam_words);
  471. $tpl->display('file:' . $this->tpl_path . '/reports/spam/spam_words/index.tpl');
  472. }
  473. };
  474. class ChReportSpamAddys extends Extension_Report {
  475. private $tpl_path = null;
  476. function __construct($manifest) {
  477. parent::__construct($manifest);
  478. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  479. }
  480. function render() {
  481. $tpl = DevblocksPlatform::getTemplateService();
  482. $tpl->cache_lifetime = "0";
  483. $tpl->assign('path', $this->tpl_path);
  484. $db = DevblocksPlatform::getDatabaseService();
  485. $top_spam_addys = array();
  486. $top_nonspam_addys = array();
  487. $sql = "SELECT email,num_spam,num_nonspam,is_banned FROM address WHERE num_spam+num_nonspam > 0 ORDER BY num_spam desc LIMIT 0,100";
  488. $rs_spam = $db->Execute($sql);
  489. while(!$rs_spam->EOF) {
  490. $top_spam_addys[$rs_spam->fields['email']] = array($rs_spam->fields['num_spam'], $rs_spam->fields['num_nonspam'], $rs_spam->fields['is_banned']);
  491. $rs_spam->MoveNext();
  492. }
  493. $tpl->assign('top_spam_addys', $top_spam_addys);
  494. $sql = "SELECT email,num_spam,num_nonspam,is_banned FROM address WHERE num_spam+num_nonspam > 0 ORDER BY num_nonspam desc LIMIT 0,100";
  495. $rs_nonspam = $db->Execute($sql);
  496. while(!$rs_nonspam->EOF) {
  497. $top_nonspam_addys[$rs_nonspam->fields['email']] = array($rs_nonspam->fields['num_spam'], $rs_nonspam->fields['num_nonspam'], $rs_spam->fields['is_banned']);
  498. $rs_nonspam->MoveNext();
  499. }
  500. $tpl->assign('top_nonspam_addys', $top_nonspam_addys);
  501. $tpl->display('file:' . $this->tpl_path . '/reports/spam/spam_addys/index.tpl');
  502. }
  503. };
  504. class ChReportSpamDomains extends Extension_Report {
  505. private $tpl_path = null;
  506. function __construct($manifest) {
  507. parent::__construct($manifest);
  508. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  509. }
  510. function render() {
  511. $tpl = DevblocksPlatform::getTemplateService();
  512. $tpl->cache_lifetime = "0";
  513. $tpl->assign('path', $this->tpl_path);
  514. $db = DevblocksPlatform::getDatabaseService();
  515. $top_spam_domains = array();
  516. $top_nonspam_domains = array();
  517. $sql = "select count(*) as hits, substring(email,locate('@',email)+1) as domain, sum(num_spam) as num_spam, sum(num_nonspam) as num_nonspam from address where num_spam+num_nonspam > 0 group by domain order by num_spam desc limit 0,100";
  518. $rs_spam = $db->Execute($sql);
  519. while(!$rs_spam->EOF) {
  520. $top_spam_domains[$rs_spam->fields['domain']] = array($rs_spam->fields['num_spam'], $rs_spam->fields['num_nonspam'], $rs_spam->fields['is_banned']);
  521. $rs_spam->MoveNext();
  522. }
  523. $tpl->assign('top_spam_domains', $top_spam_domains);
  524. $sql = "select count(*) as hits, substring(email,locate('@',email)+1) as domain, sum(num_spam) as num_spam, sum(num_nonspam) as num_nonspam from address where num_spam+num_nonspam > 0 group by domain order by num_nonspam desc limit 0,100";
  525. $rs_nonspam = $db->Execute($sql);
  526. while(!$rs_nonspam->EOF) {
  527. $top_nonspam_domains[$rs_nonspam->fields['domain']] = array($rs_nonspam->fields['num_spam'], $rs_nonspam->fields['num_nonspam'], $rs_spam->fields['is_banned']);
  528. $rs_nonspam->MoveNext();
  529. }
  530. $tpl->assign('top_nonspam_domains', $top_nonspam_domains);
  531. $tpl->display('file:' . $this->tpl_path . '/reports/spam/spam_domains/index.tpl');
  532. }
  533. };
  534. class ChReportAverageResponseTime extends Extension_Report {
  535. private $tpl_path = null;
  536. function __construct($manifest) {
  537. parent::__construct($manifest);
  538. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  539. }
  540. function render() {
  541. $tpl = DevblocksPlatform::getTemplateService();
  542. $tpl->cache_lifetime = "0";
  543. $tpl->assign('path', $this->tpl_path);
  544. $tpl->display('file:' . $this->tpl_path . '/reports/worker/average_response_time/index.tpl');
  545. }
  546. function getAverageResponseTimeReportAction() {
  547. // init
  548. $db = DevblocksPlatform::getDatabaseService();
  549. $tpl = DevblocksPlatform::getTemplateService();
  550. $tpl->cache_lifetime = "0";
  551. $tpl->assign('path', $this->tpl_path);
  552. // import dates from form
  553. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  554. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  555. // use date range if specified, else use duration prior to now
  556. $start_time = 0;
  557. $end_time = 0;
  558. if (empty($start) && empty($end)) {
  559. $start_time = strtotime("-30 days");
  560. $end_time = strtotime("now");
  561. } else {
  562. $start_time = strtotime($start);
  563. $end_time = strtotime($end);
  564. }
  565. if($start_time === false || $end_time === false) {
  566. $start = "-30 days";
  567. $end = "now";
  568. $start_time = strtotime($start);
  569. $end_time = strtotime($end);
  570. $tpl->assign('invalidDate', true);
  571. }
  572. // reload variables in template
  573. $tpl->assign('start', $start);
  574. $tpl->assign('end', $end);
  575. // set up necessary reference arrays
  576. $groups = DAO_Group::getAll();
  577. $tpl->assign('groups', $groups);
  578. $group_buckets = DAO_Bucket::getTeams();
  579. $tpl->assign('group_buckets', $group_buckets);
  580. $workers = DAO_Worker::getAll();
  581. $tpl->assign('workers',$workers);
  582. // pull data from db
  583. $sql = sprintf("SELECT mm.id, mm.ticket_id, mm.created_date, mm.worker_id, mm.is_outgoing, t.team_id, t.category_id ".
  584. "FROM message m ".
  585. "INNER JOIN ticket t ON (t.id=m.ticket_id) ".
  586. "INNER JOIN message mm ON (mm.ticket_id=t.id) ".
  587. "WHERE m.created_date > %d AND m.created_date <= %d AND m.is_outgoing = 1 ".
  588. "ORDER BY ticket_id,id ",
  589. $start_time,
  590. $end_time
  591. );
  592. $rs_responses = $db->Execute($sql);
  593. // process and count results
  594. $group_responses = array();
  595. $worker_responses = array();
  596. $prev = array();
  597. while(!$rs_responses->EOF) {
  598. // load current data
  599. $id = intval($rs_responses->fields['id']);
  600. $ticket_id = intval($rs_responses->fields['ticket_id']);
  601. $created_date = intval($rs_responses->fields['created_date']);
  602. $worker_id = intval($rs_responses->fields['worker_id']);
  603. $is_outgoing = intval($rs_responses->fields['is_outgoing']);
  604. $team_id = intval($rs_responses->fields['team_id']);
  605. $category_id = intval($rs_responses->fields['category_id']);
  606. // we only add data if it's a worker reply to the same ticket as $prev
  607. if ($is_outgoing==1 && !empty($prev) && $ticket_id==$prev['ticket_id']) {
  608. // Initialize, if necessary
  609. if (!isset($group_responses[$team_id])) $group_responses[$team_id] = array();
  610. if (!isset($worker_responses[$worker_id])) $worker_responses[$worker_id] = array();
  611. // log reply and time
  612. @$group_responses[$team_id]['replies'] += 1;
  613. @$group_responses[$team_id]['time'] += $created_date - $prev['created_date'];
  614. @$worker_responses[$worker_id]['replies'] += 1;
  615. @$worker_responses[$worker_id]['time'] += $created_date - $prev['created_date'];
  616. }
  617. // Save this one as "previous" and move on
  618. $prev = array(
  619. 'id'=>$id,
  620. 'ticket_id'=>$ticket_id,
  621. 'created_date'=>$created_date,
  622. 'worker_id'=>$worker_id,
  623. 'is_outgoing'=>$is_outgoing,
  624. 'team_id'=>$team_id,
  625. 'category_id'=>$category_id,
  626. );
  627. $rs_responses->MoveNext();
  628. }
  629. $tpl->assign('group_responses', $group_responses);
  630. $tpl->assign('worker_responses', $worker_responses);
  631. $tpl->display('file:' . $this->tpl_path . '/reports/worker/average_response_time/html.tpl');
  632. }
  633. }
  634. class ChReportGroupReplies extends Extension_Report {
  635. private $tpl_path = null;
  636. function __construct($manifest) {
  637. parent::__construct($manifest);
  638. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  639. }
  640. function render() {
  641. $tpl = DevblocksPlatform::getTemplateService();
  642. $tpl->cache_lifetime = "0";
  643. $tpl->assign('path', $this->tpl_path);
  644. $tpl->assign('start', '-30 days');
  645. $tpl->assign('end', 'now');
  646. $db = DevblocksPlatform::getDatabaseService();
  647. // Years
  648. $years = array();
  649. $sql = "SELECT date_format(from_unixtime(created_date),'%Y') as year FROM message WHERE created_date > 0 AND is_outgoing = 1 GROUP BY year having year <= date_format(now(),'%Y') ORDER BY year desc limit 0,10";
  650. $rs = $db->query($sql);
  651. if(is_a($rs,'ADORecordSet'))
  652. while(!$rs->EOF) {
  653. $years[] = intval($rs->fields['year']);
  654. $rs->MoveNext();
  655. }
  656. $tpl->assign('years', $years);
  657. $tpl->display('file:' . $this->tpl_path . '/reports/group/group_replies/index.tpl');
  658. }
  659. function getGroupRepliesReportAction() {
  660. @$countonly = DevblocksPlatform::importGPC($_REQUEST['countonly'],'integer',0);
  661. $db = DevblocksPlatform::getDatabaseService();
  662. $tpl = DevblocksPlatform::getTemplateService();
  663. $tpl->cache_lifetime = "0";
  664. $tpl->assign('path', $this->tpl_path);
  665. // import dates from form
  666. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  667. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  668. // use date range if specified, else use duration prior to now
  669. $start_time = 0;
  670. $end_time = 0;
  671. if (empty($start) && empty($end)) {
  672. $start = "-30 days";
  673. $end = "now";
  674. $start_time = strtotime($start);
  675. $end_time = strtotime($end);
  676. } else {
  677. $start_time = strtotime($start);
  678. $end_time = strtotime($end);
  679. }
  680. if($start_time === false || $end_time === false) {
  681. $start = "-30 days";
  682. $end = "now";
  683. $start_time = strtotime($start);
  684. $end_time = strtotime($end);
  685. $tpl->assign('invalidDate', true);
  686. }
  687. // reload variables in template
  688. $tpl->assign('start', $start);
  689. $tpl->assign('end', $end);
  690. $tpl->assign('age_dur', abs(floor(($start_time - $end_time)/86400)));
  691. $groups = DAO_Group::getAll();
  692. $tpl->assign('groups', $groups);
  693. $group_buckets = DAO_Bucket::getTeams();
  694. $tpl->assign('group_buckets', $group_buckets);
  695. $sql = sprintf("SELECT count(*) AS hits, t.team_id, category_id ".
  696. "FROM message m ".
  697. "INNER JOIN ticket t ON (t.id=m.ticket_id) ".
  698. "INNER JOIN team ON t.team_id = team.id ".
  699. "WHERE m.created_date > %d AND m.created_date <= %d ".
  700. "AND m.is_outgoing = 1 ".
  701. "AND t.is_deleted = 0 ".
  702. "AND t.team_id != 0 " .
  703. "GROUP BY t.team_id, category_id ORDER BY team.name ",
  704. $start_time,
  705. $end_time
  706. );
  707. $rs = $db->Execute($sql);
  708. $group_counts = array();
  709. if(is_a($rs,'ADORecordSet'))
  710. while(!$rs->EOF) {
  711. $team_id = intval($rs->fields['team_id']);
  712. $category_id = intval($rs ->fields['category_id']);
  713. $hits = intval($rs->fields['hits']);
  714. if(!isset($group_counts[$team_id]))
  715. $group_counts[$team_id] = array();
  716. $group_counts[$team_id][$category_id] = $hits;
  717. @$group_counts[$team_id]['total'] = intval($group_counts[$team_id]['total']) + $hits;
  718. $rs->MoveNext();
  719. }
  720. $tpl->assign('group_counts', $group_counts);
  721. $tpl->display('file:' . $this->tpl_path . '/reports/group/group_replies/html.tpl');
  722. }
  723. function getGroupRepliesChartAction() {
  724. header("content-type: text/plain");
  725. $db = DevblocksPlatform::getDatabaseService();
  726. // import dates from form
  727. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  728. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  729. @$countonly = DevblocksPlatform::importGPC($_REQUEST['countonly'],'integer',0);
  730. // use date range if specified, else use duration prior to now
  731. $start_time = 0;
  732. $end_time = 0;
  733. if (empty($start) && empty($end)) {
  734. $start = "-30 days";
  735. $end = "now";
  736. $start_time = strtotime($start);
  737. $end_time = strtotime($end);
  738. } else {
  739. $start_time = strtotime($start);
  740. $end_time = strtotime($end);
  741. }
  742. // Top Workers
  743. $groups = DAO_Group::getAll();
  744. $sql = sprintf("SELECT count(*) AS hits, t.team_id as group_id ".
  745. "FROM message m ".
  746. "INNER JOIN ticket t ON (t.id=m.ticket_id) ".
  747. "INNER JOIN team on t.team_id = team.id ".
  748. "WHERE m.created_date > %d AND m.created_date <= %d ".
  749. "AND m.is_outgoing = 1 ".
  750. "AND t.is_deleted = 0 ".
  751. "AND t.team_id != 0 " .
  752. "GROUP BY group_id ORDER BY team.name DESC ",
  753. $start_time,
  754. $end_time
  755. );
  756. $rs_groups = $db->Execute($sql); /* @var $rs_groups ADORecordSet */
  757. if($countonly) {
  758. echo intval($rs_groups ->RecordCount());
  759. return;
  760. }
  761. $worker_counts = array();
  762. while(!$rs_groups ->EOF) {
  763. $hits = intval($rs_groups ->fields['hits']);
  764. $group_id = intval($rs_groups ->fields['group_id']);
  765. if(!isset($groups[$group_id]))
  766. continue;
  767. echo $groups[$group_id]->name , "\t" , $hits , "\n";
  768. $rs_groups ->MoveNext();
  769. }
  770. }
  771. }
  772. class ChReportOpenTickets extends Extension_Report {
  773. private $tpl_path = null;
  774. function __construct($manifest) {
  775. parent::__construct($manifest);
  776. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  777. }
  778. function render() {
  779. $tpl = DevblocksPlatform::getTemplateService();
  780. $tpl->cache_lifetime = "0";
  781. $tpl->assign('path', $this->tpl_path);
  782. $tpl->assign('start', '-5 years');
  783. $tpl->assign('end', 'now');
  784. $db = DevblocksPlatform::getDatabaseService();
  785. // Year shortcuts
  786. $years = array();
  787. $sql = "SELECT date_format(from_unixtime(created_date),'%Y') as year FROM ticket WHERE created_date > 0 GROUP BY year having year <= date_format(now(),'%Y') ORDER BY year desc limit 0,10";
  788. $rs = $db->query($sql);
  789. if(is_a($rs,'ADORecordSet'))
  790. while(!$rs->EOF) {
  791. $years[] = intval($rs->fields['year']);
  792. $rs->MoveNext();
  793. }
  794. $tpl->assign('years', $years);
  795. $tpl->display('file:' . $this->tpl_path . '/reports/ticket/open_tickets/index.tpl');
  796. }
  797. function getOpenTicketsReportAction() {
  798. @$age = DevblocksPlatform::importGPC($_REQUEST['age'],'string','30d');
  799. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  800. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  801. @$countonly = DevblocksPlatform::importGPC($_REQUEST['countonly'],'integer',0);
  802. // use date range if specified, else use duration prior to now
  803. $start_time = 0;
  804. $end_time = 0;
  805. if (empty($start) && empty($end)) {
  806. $start = "-5 years";
  807. $end = "now";
  808. $start_time = strtotime($start);
  809. $end_time = strtotime($end);
  810. } else {
  811. $start_time = strtotime($start);
  812. $end_time = strtotime($end);
  813. }
  814. $db = DevblocksPlatform::getDatabaseService();
  815. $tpl = DevblocksPlatform::getTemplateService();
  816. $tpl->cache_lifetime = "0";
  817. $tpl->assign('path', $this->tpl_path);
  818. // Top Buckets
  819. $groups = DAO_Group::getAll();
  820. $tpl->assign('groups', $groups);
  821. $group_buckets = DAO_Bucket::getTeams();
  822. $tpl->assign('group_buckets', $group_buckets);
  823. $sql = sprintf("SELECT count(*) AS hits, team_id, category_id ".
  824. "FROM ticket ".
  825. "WHERE created_date > %d AND created_date <= %d ".
  826. "AND is_deleted = 0 ".
  827. "AND is_closed = 0 ".
  828. "AND spam_score < 0.9000 ".
  829. "AND spam_training != 'S' ".
  830. "AND is_waiting != 1 " .
  831. "GROUP BY team_id, category_id ",
  832. $start_time,
  833. $end_time);
  834. $rs_buckets = $db->Execute($sql);
  835. $group_counts = array();
  836. while(!$rs_buckets->EOF) {
  837. $team_id = intval($rs_buckets->fields['team_id']);
  838. $category_id = intval($rs_buckets->fields['category_id']);
  839. $hits = intval($rs_buckets->fields['hits']);
  840. if(!isset($group_counts[$team_id]))
  841. $group_counts[$team_id] = array();
  842. $group_counts[$team_id][$category_id] = $hits;
  843. @$group_counts[$team_id]['total'] = intval($group_counts[$team_id]['total']) + $hits;
  844. $rs_buckets->MoveNext();
  845. }
  846. $tpl->assign('group_counts', $group_counts);
  847. $tpl->display('file:' . $this->tpl_path . '/reports/ticket/open_tickets/html.tpl');
  848. }
  849. function getOpenTicketsChartAction() {
  850. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  851. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  852. @$countonly = DevblocksPlatform::importGPC($_REQUEST['countonly'],'integer',0);
  853. // use date range if specified, else use duration prior to now
  854. $start_time = 0;
  855. $end_time = 0;
  856. if (empty($start) && empty($end)) {
  857. $start = "-30 days";
  858. $end = "now";
  859. $start_time = strtotime($start);
  860. $end_time = strtotime($end);
  861. } else {
  862. $start_time = strtotime($start);
  863. $end_time = strtotime($end);
  864. }
  865. $db = DevblocksPlatform::getDatabaseService();
  866. $groups = DAO_Group::getAll();
  867. $sql = sprintf("SELECT team.id as group_id, ".
  868. "count(*) as hits ".
  869. "FROM ticket t inner join team on t.team_id = team.id ".
  870. "WHERE t.created_date > %d AND t.created_date <= %d ".
  871. "AND t.is_deleted = 0 ".
  872. "AND t.is_closed = 0 ".
  873. "AND t.spam_score < 0.9000 ".
  874. "AND t.spam_training != 'S' ".
  875. "AND is_waiting != 1 " .
  876. "GROUP BY group_id ORDER by team.name desc ",
  877. $start_time,
  878. $end_time);
  879. $rs = $db->Execute($sql);
  880. if($countonly) {
  881. echo intval($rs->RecordCount());
  882. return;
  883. }
  884. if(is_a($rs,'ADORecordSet'))
  885. while(!$rs->EOF) {
  886. $hits = intval($rs->fields['hits']);
  887. $group_id = $rs->fields['group_id'];
  888. echo $groups[$group_id]->name, "\t", $hits . "\n";
  889. $rs->MoveNext();
  890. }
  891. }
  892. }
  893. class ChReportOldestOpenTickets extends Extension_Report {
  894. private $tpl_path = null;
  895. function __construct($manifest) {
  896. parent::__construct($manifest);
  897. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  898. }
  899. function render() {
  900. $tpl = DevblocksPlatform::getTemplateService();
  901. $tpl->cache_lifetime = "0";
  902. $tpl->assign('path', $this->tpl_path);
  903. $tpl->assign('start', '-5 years');
  904. $tpl->assign('end', 'now');
  905. $db = DevblocksPlatform::getDatabaseService();
  906. // Year shortcuts
  907. $years = array();
  908. $sql = "SELECT date_format(from_unixtime(created_date),'%Y') as year FROM ticket WHERE created_date > 0 GROUP BY year having year <= date_format(now(),'%Y') ORDER BY year desc limit 0,10";
  909. $rs = $db->query($sql);
  910. if(is_a($rs,'ADORecordSet'))
  911. while(!$rs->EOF) {
  912. $years[] = intval($rs->fields['year']);
  913. $rs->MoveNext();
  914. }
  915. $tpl->assign('years', $years);
  916. $tpl->display('file:' . $this->tpl_path . '/reports/ticket/oldest_open_tickets/index.tpl');
  917. }
  918. function getOldestOpenTicketsReportAction() {
  919. @$age = DevblocksPlatform::importGPC($_REQUEST['age'],'string','30d');
  920. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  921. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  922. @$countonly = DevblocksPlatform::importGPC($_REQUEST['countonly'],'integer',0);
  923. // use date range if specified, else use duration prior to now
  924. $start_time = 0;
  925. $end_time = 0;
  926. if (empty($start) && empty($end)) {
  927. $start = "-5 years";
  928. $end = "now";
  929. $start_time = strtotime($start);
  930. $end_time = strtotime($end);
  931. } else {
  932. $start_time = strtotime($start);
  933. $end_time = strtotime($end);
  934. }
  935. $db = DevblocksPlatform::getDatabaseService();
  936. $tpl = DevblocksPlatform::getTemplateService();
  937. $tpl->cache_lifetime = "0";
  938. $tpl->assign('path', $this->tpl_path);
  939. // Top Buckets
  940. $groups = DAO_Group::getAll();
  941. $tpl->assign('groups', $groups);
  942. $group_buckets = DAO_Bucket::getTeams();
  943. $tpl->assign('group_buckets', $group_buckets);
  944. $oldest_tickets = array();
  945. foreach($groups as $group_id=>$group) {
  946. $sql = sprintf("SELECT mask, subject, created_date ".
  947. "FROM ticket ".
  948. "WHERE created_date > %d AND created_date <= %d ".
  949. "AND is_deleted = 0 ".
  950. "AND is_closed = 0 ".
  951. "AND spam_score < 0.9000 ".
  952. "AND spam_training != 'S' ".
  953. "AND is_waiting != 1 " .
  954. "AND team_id = %d " .
  955. "ORDER BY created_date LIMIT 10",
  956. $start_time,
  957. $end_time,
  958. $group_id);
  959. $rs = $db->Execute($sql);
  960. if(is_a($rs,'ADORecordSet'))
  961. while(!$rs->EOF) {
  962. $mask = $rs->fields['mask'];
  963. $subject = $rs->fields['subject'];
  964. $created_date = intval($rs->fields['created_date']);
  965. if(!isset($oldest_tickets[$group_id]))
  966. $oldest_tickets[$group_id] = array();
  967. unset($ticket_entry);
  968. $ticket_entry->mask = $mask;
  969. $ticket_entry->subject = $subject;
  970. $ticket_entry->created_date = $created_date;
  971. $oldest_tickets[$group_id][]=$ticket_entry;
  972. $rs->MoveNext();
  973. }
  974. unset($rs);
  975. }
  976. //echo "<pre>";print_r($oldest_tickets);echo "</pre>";exit;
  977. $tpl->assign('oldest_tickets', $oldest_tickets);
  978. $tpl->display('file:' . $this->tpl_path . '/reports/ticket/oldest_open_tickets/html.tpl');
  979. }
  980. }
  981. class ChReportWaitingTickets extends Extension_Report {
  982. private $tpl_path = null;
  983. function __construct($manifest) {
  984. parent::__construct($manifest);
  985. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  986. }
  987. function render() {
  988. $tpl = DevblocksPlatform::getTemplateService();
  989. $tpl->cache_lifetime = "0";
  990. $tpl->assign('path', $this->tpl_path);
  991. $tpl->assign('start', '-30 days');
  992. $tpl->assign('end', 'now');
  993. $db = DevblocksPlatform::getDatabaseService();
  994. // Year shortcuts
  995. $years = array();
  996. $sql = "SELECT date_format(from_unixtime(created_date),'%Y') as year FROM ticket WHERE created_date > 0 GROUP BY year having year <= date_format(now(),'%Y') ORDER BY year desc limit 0,10";
  997. $rs = $db->query($sql);
  998. if(is_a($rs,'ADORecordSet'))
  999. while(!$rs->EOF) {
  1000. $years[] = intval($rs->fields['year']);
  1001. $rs->MoveNext();
  1002. }
  1003. $tpl->assign('years', $years);
  1004. $tpl->display('file:' . $this->tpl_path . '/reports/ticket/waiting_tickets/index.tpl');
  1005. }
  1006. function getWaitingTicketsReportAction() {
  1007. @$age = DevblocksPlatform::importGPC($_REQUEST['age'],'string','30d');
  1008. $db = DevblocksPlatform::getDatabaseService();
  1009. $tpl = DevblocksPlatform::getTemplateService();
  1010. $tpl->cache_lifetime = "0";
  1011. $tpl->assign('path', $this->tpl_path);
  1012. // Top Buckets
  1013. $groups = DAO_Group::getAll();
  1014. $tpl->assign('groups', $groups);
  1015. $group_buckets = DAO_Bucket::getTeams();
  1016. $tpl->assign('group_buckets', $group_buckets);
  1017. $sql = "SELECT count(*) AS hits, team_id, category_id ".
  1018. "FROM ticket ".
  1019. "WHERE is_deleted = 0 ".
  1020. "AND is_closed = 0 ".
  1021. "AND spam_score < 0.9000 ".
  1022. "AND spam_training != 'S' ".
  1023. "AND is_waiting = 1 " .
  1024. "GROUP BY team_id, category_id ";
  1025. $rs_buckets = $db->Execute($sql);
  1026. $group_counts = array();
  1027. while(!$rs_buckets->EOF) {
  1028. $team_id = intval($rs_buckets->fields['team_id']);
  1029. $category_id = intval($rs_buckets->fields['category_id']);
  1030. $hits = intval($rs_buckets->fields['hits']);
  1031. if(!isset($group_counts[$team_id]))
  1032. $group_counts[$team_id] = array();
  1033. $group_counts[$team_id][$category_id] = $hits;
  1034. @$group_counts[$team_id]['total'] = intval($group_counts[$team_id]['total']) + $hits;
  1035. $rs_buckets->MoveNext();
  1036. }
  1037. $tpl->assign('group_counts', $group_counts);
  1038. $tpl->display('file:' . $this->tpl_path . '/reports/ticket/waiting_tickets/html.tpl');
  1039. }
  1040. function getWaitingTicketsChartAction() {
  1041. @$countonly = DevblocksPlatform::importGPC($_REQUEST['countonly'],'integer',0);
  1042. $db = DevblocksPlatform::getDatabaseService();
  1043. $groups = DAO_Group::getAll();
  1044. $sql = "SELECT team.id as group_id, ".
  1045. "count(*) as hits ".
  1046. "FROM ticket t inner join team on t.team_id = team.id ".
  1047. "WHERE t.is_deleted = 0 ".
  1048. "AND t.is_closed = 0 ".
  1049. "AND t.spam_score < 0.9000 ".
  1050. "AND t.spam_training != 'S' ".
  1051. "AND is_waiting = 1 " .
  1052. "GROUP BY group_id ORDER by team.name desc ";
  1053. $rs = $db->Execute($sql);
  1054. if($countonly) {
  1055. echo intval($rs->RecordCount());
  1056. return;
  1057. }
  1058. if(is_a($rs,'ADORecordSet'))
  1059. while(!$rs->EOF) {
  1060. $hits = intval($rs->fields['hits']);
  1061. $group_id = $rs->fields['group_id'];
  1062. echo $groups[$group_id]->name, "\t", $hits . "\n";
  1063. $rs->MoveNext();
  1064. }
  1065. }
  1066. }
  1067. class ChReportClosedTickets extends Extension_Report {
  1068. private $tpl_path = null;
  1069. function __construct($manifest) {
  1070. parent::__construct($manifest);
  1071. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  1072. }
  1073. function render() {
  1074. $tpl = DevblocksPlatform::getTemplateService();
  1075. $tpl->cache_lifetime = "0";
  1076. $tpl->assign('path', $this->tpl_path);
  1077. $tpl->assign('start', '-30 days');
  1078. $tpl->assign('end', 'now');
  1079. $db = DevblocksPlatform::getDatabaseService();
  1080. // Year shortcuts
  1081. $years = array();
  1082. $sql = "SELECT date_format(from_unixtime(created_date),'%Y') as year FROM ticket WHERE created_date > 0 GROUP BY year having year <= date_format(now(),'%Y') ORDER BY year desc limit 0,10";
  1083. $rs = $db->query($sql);
  1084. if(is_a($rs,'ADORecordSet'))
  1085. while(!$rs->EOF) {
  1086. $years[] = intval($rs->fields['year']);
  1087. $rs->MoveNext();
  1088. }
  1089. $tpl->assign('years', $years);
  1090. $tpl->display('file:' . $this->tpl_path . '/reports/ticket/closed_tickets/index.tpl');
  1091. }
  1092. function getClosedTicketsReportAction() {
  1093. @$age = DevblocksPlatform::importGPC($_REQUEST['age'],'string','30d');
  1094. $db = DevblocksPlatform::getDatabaseService();
  1095. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  1096. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  1097. @$countonly = DevblocksPlatform::importGPC($_REQUEST['countonly'],'integer',0);
  1098. // use date range if specified, else use duration prior to now
  1099. $start_time = 0;
  1100. $end_time = 0;
  1101. if (empty($start) && empty($end)) {
  1102. $start = "-30 days";
  1103. $end = "now";
  1104. $start_time = strtotime($start);
  1105. $end_time = strtotime($end);
  1106. } else {
  1107. $start_time = strtotime($start);
  1108. $end_time = strtotime($end);
  1109. }
  1110. $tpl = DevblocksPlatform::getTemplateService();
  1111. $tpl->cache_lifetime = "0";
  1112. $tpl->assign('path', $this->tpl_path);
  1113. // Top Buckets
  1114. $groups = DAO_Group::getAll();
  1115. $tpl->assign('groups', $groups);
  1116. $group_buckets = DAO_Bucket::getTeams();
  1117. $tpl->assign('group_buckets', $group_buckets);
  1118. $sql = sprintf("SELECT count(*) AS hits, team_id, category_id ".
  1119. "FROM ticket ".
  1120. "WHERE updated_date > %d AND updated_date <= %d ".
  1121. "AND is_deleted = 0 ".
  1122. "AND is_closed = 1 ".
  1123. "AND spam_score < 0.9000 ".
  1124. "AND spam_training != 'S' ".
  1125. "GROUP BY team_id, category_id" ,
  1126. $start_time,
  1127. $end_time);
  1128. $rs_buckets = $db->Execute($sql);
  1129. $group_counts = array();
  1130. while(!$rs_buckets->EOF) {
  1131. $team_id = intval($rs_buckets->fields['team_id']);
  1132. $category_id = intval($rs_buckets->fields['category_id']);
  1133. $hits = intval($rs_buckets->fields['hits']);
  1134. if(!isset($group_counts[$team_id]))
  1135. $group_counts[$team_id] = array();
  1136. $group_counts[$team_id][$category_id] = $hits;
  1137. @$group_counts[$team_id]['total'] = intval($group_counts[$team_id]['total']) + $hits;
  1138. $rs_buckets->MoveNext();
  1139. }
  1140. $tpl->assign('group_counts', $group_counts);
  1141. $tpl->display('file:' . $this->tpl_path . '/reports/ticket/closed_tickets/html.tpl');
  1142. }
  1143. function getClosedTicketsChartAction() {
  1144. @$countonly = DevblocksPlatform::importGPC($_REQUEST['countonly'],'integer',0);
  1145. $db = DevblocksPlatform::getDatabaseService();
  1146. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  1147. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  1148. @$countonly = DevblocksPlatform::importGPC($_REQUEST['countonly'],'integer',0);
  1149. // use date range if specified, else use duration prior to now
  1150. $start_time = 0;
  1151. $end_time = 0;
  1152. if (empty($start) && empty($end)) {
  1153. $start = "-30 days";
  1154. $end = "now";
  1155. $start_time = strtotime($start);
  1156. $end_time = strtotime($end);
  1157. } else {
  1158. $start_time = strtotime($start);
  1159. $end_time = strtotime($end);
  1160. }
  1161. $groups = DAO_Group::getAll();
  1162. $sql = sprintf("SELECT team.id as group_id, ".
  1163. "count(*) as hits ".
  1164. "FROM ticket t inner join team on t.team_id = team.id ".
  1165. "WHERE updated_date > %d AND updated_date <= %d ".
  1166. "AND t.is_deleted = 0 ".
  1167. "AND t.is_closed = 1 ".
  1168. "AND t.spam_score < 0.9000 ".
  1169. "AND t.spam_training != 'S' ".
  1170. "GROUP BY group_id ORDER by team.name desc ",
  1171. $start_time,
  1172. $end_time);
  1173. $rs = $db->Execute($sql);
  1174. if($countonly) {
  1175. echo intval($rs->RecordCount());
  1176. return;
  1177. }
  1178. if(is_a($rs,'ADORecordSet'))
  1179. while(!$rs->EOF) {
  1180. $hits = intval($rs->fields['hits']);
  1181. $group_id = $rs->fields['group_id'];
  1182. echo $groups[$group_id]->name, "\t", $hits . "\n";
  1183. $rs->MoveNext();
  1184. }
  1185. }
  1186. }
  1187. class ChReportTicketAssignment extends Extension_Report {
  1188. private $tpl_path = null;
  1189. function __construct($manifest) {
  1190. parent::__construct($manifest);
  1191. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  1192. }
  1193. function render() {
  1194. $tpl = DevblocksPlatform::getTemplateService();
  1195. $tpl->cache_lifetime = "0";
  1196. $tpl->assign('path', $this->tpl_path);
  1197. $db = DevblocksPlatform::getDatabaseService();
  1198. $tpl->display('file:' . $this->tpl_path . '/reports/worker/ticket_assignment/index.tpl');
  1199. }
  1200. function getTicketAssignmentReportAction() {
  1201. @$countonly = DevblocksPlatform::importGPC($_REQUEST['countonly'],'integer',0);
  1202. $db = DevblocksPlatform::getDatabaseService();
  1203. $tpl = DevblocksPlatform::getTemplateService();
  1204. $tpl->cache_lifetime = "0";
  1205. $tpl->assign('path', $this->tpl_path);
  1206. $workers = DAO_Worker::getAll();
  1207. $tpl->assign('workers', $workers);
  1208. $sql = sprintf("SELECT w.id worker_id, t.id ticket_id, t.mask, t.subject, t.created_date ".
  1209. "FROM ticket t inner join worker w on t.next_worker_id = w.id ".
  1210. "WHERE t.is_deleted = 0 ".
  1211. "AND t.is_closed = 0 ".
  1212. "AND t.spam_score < 0.9000 ".
  1213. "AND t.spam_training != 'S' ".
  1214. "AND is_waiting != 1 ".
  1215. "ORDER by w.last_name");
  1216. $rs_buckets = $db->Execute($sql);
  1217. $ticket_assignments = array();
  1218. while(!$rs_buckets->EOF) {
  1219. $worker_id = intval($rs_buckets->fields['worker_id']);
  1220. $mask = $rs_buckets->fields['mask'];
  1221. $subject = $rs_buckets->fields['subject'];
  1222. $created_date = intval($rs_buckets->fields['created_date']);
  1223. if(!isset($ticket_assignments[$worker_id]))
  1224. $ticket_assignments[$worker_id] = array();
  1225. unset($assignment);
  1226. $assignment->mask = $mask;
  1227. $assignment->subject = $subject;
  1228. $assignment->created_date = $created_date;
  1229. $ticket_assignments[$worker_id][] = $assignment;
  1230. $rs_buckets->MoveNext();
  1231. }
  1232. $tpl->assign('ticket_assignments', $ticket_assignments);
  1233. //print_r($ticket_assignments);exit;
  1234. $tpl->display('file:' . $this->tpl_path . '/reports/worker/ticket_assignment/html.tpl');
  1235. }
  1236. function getTicketAssignmentChartAction() {
  1237. @$countonly = DevblocksPlatform::importGPC($_REQUEST['countonly'],'integer',0);
  1238. $db = DevblocksPlatform::getDatabaseService();
  1239. $workers = DAO_Worker::getAll();
  1240. $sql = sprintf("SELECT w.id worker_id ,count(*) as hits ".
  1241. "FROM ticket t inner join worker w on t.next_worker_id = w.id ".
  1242. "WHERE t.is_deleted = 0 ".
  1243. "AND t.is_closed = 0 ".
  1244. "AND t.spam_score < 0.9000 ".
  1245. "AND t.spam_training != 'S' ".
  1246. "AND is_waiting != 1 ".
  1247. "GROUP by w.id ".
  1248. "ORDER by w.last_name");
  1249. $rs = $db->Execute($sql);
  1250. if($countonly) {
  1251. echo intval($rs->RecordCount());
  1252. return;
  1253. }
  1254. if(is_a($rs,'ADORecordSet'))
  1255. while(!$rs->EOF) {
  1256. $hits = intval($rs->fields['hits']);
  1257. $worker_id = $rs->fields['worker_id'];
  1258. echo $workers[$worker_id]->getName(), "\t", $hits . "\n";
  1259. $rs->MoveNext();
  1260. }
  1261. }
  1262. }
  1263. class ChReportTopTicketsByContact extends Extension_Report {
  1264. private $tpl_path = null;
  1265. function __construct($manifest) {
  1266. parent::__construct($manifest);
  1267. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  1268. }
  1269. function render() {
  1270. $tpl = DevblocksPlatform::getTemplateService();
  1271. $tpl->cache_lifetime = "0";
  1272. $tpl->assign('path', $this->tpl_path);
  1273. $tpl->assign('start', '-30 days');
  1274. $tpl->assign('end', 'now');
  1275. $db = DevblocksPlatform::getDatabaseService();
  1276. // Year shortcuts
  1277. $years = array();
  1278. $sql = "SELECT date_format(from_unixtime(created_date),'%Y') as year FROM ticket WHERE created_date > 0 GROUP BY year having year <= date_format(now(),'%Y') ORDER BY year desc limit 0,10";
  1279. $rs = $db->query($sql);
  1280. if(is_a($rs,'ADORecordSet'))
  1281. while(!$rs->EOF) {
  1282. $years[] = intval($rs->fields['year']);
  1283. $rs->MoveNext();
  1284. }
  1285. $tpl->assign('years', $years);
  1286. $tpl->display('file:' . $this->tpl_path . '/reports/ticket/top_contacts_tickets/index.tpl');
  1287. }
  1288. function getTopTicketsReportAction() {
  1289. @$age = DevblocksPlatform::importGPC($_REQUEST['age'],'string','30d');
  1290. $db = DevblocksPlatform::getDatabaseService();
  1291. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  1292. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  1293. @$countonly = DevblocksPlatform::importGPC($_REQUEST['countonly'],'integer',0);
  1294. @$by_address = DevblocksPlatform::importGPC($_REQUEST['by_address'],'integer',0);
  1295. // use date range if specified, else use duration prior to now
  1296. $start_time = 0;
  1297. $end_time = 0;
  1298. if (empty($start) && empty($end)) {
  1299. $start = "-30 days";
  1300. $end = "now";
  1301. $start_time = strtotime($start);
  1302. $end_time = strtotime($end);
  1303. } else {
  1304. $start_time = strtotime($start);
  1305. $end_time = strtotime($end);
  1306. }
  1307. $tpl = DevblocksPlatfo

Large files files are truncated, but you can click here to view the full file