PageRenderTime 48ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/plugins/answernet.internal.reports/api/App.php

https://github.com/rmiddle/cerb4_plugins
PHP | 1177 lines | 863 code | 169 blank | 145 comment | 87 complexity | 82d14b62c2dbf0bbafb21d25d4cd2392 MD5 | raw file
  1. <?php
  2. class AnswernetInternalReportPlugin extends DevblocksPlugin {
  3. function load(DevblocksPluginManifest $manifest) {
  4. }
  5. };
  6. if (class_exists('DevblocksTranslationsExtension',true)):
  7. class AnswernetInternalTranslations extends DevblocksTranslationsExtension {
  8. function __construct($manifest) {
  9. parent::__construct($manifest);
  10. }
  11. function getTmxFile() {
  12. return dirname(dirname(__FILE__)) . '/strings.xml';
  13. }
  14. };
  15. endif;
  16. class AnswernetInternalReportGroups extends Extension_ReportGroup {
  17. function __construct($manifest) {
  18. parent::__construct($manifest);
  19. }
  20. };
  21. class AnswernetInternalReportGroupsTime extends Extension_ReportGroup {
  22. function __construct($manifest) {
  23. parent::__construct($manifest);
  24. }
  25. };
  26. class AnswernetInternalReportWorkers extends Extension_Report {
  27. private $tpl_path = null;
  28. function __construct($manifest) {
  29. parent::__construct($manifest);
  30. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  31. }
  32. function render() {
  33. $tpl = DevblocksPlatform::getTemplateService();
  34. $tpl->cache_lifetime = "0";
  35. $tpl->assign('path', $this->tpl_path);
  36. $tpl->assign('start', '-5 year');
  37. $tpl->assign('end', 'now');
  38. $db = DevblocksPlatform::getDatabaseService();
  39. $workers = DAO_Worker::getAll();
  40. $tpl->assign('workers', $workers);
  41. // Teams
  42. $teams = DAO_Group::getAll();
  43. $tpl->assign('teams', $teams);
  44. // Categories
  45. $team_categories = DAO_Bucket::getTeams(); // [TODO] Cache these
  46. $tpl->assign('team_categories', $team_categories);
  47. $tpl->display('file:' . $this->tpl_path . '/report_stats.tpl');
  48. }
  49. function getTicketAssignmentReportAction() {
  50. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  51. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  52. @$countonly = DevblocksPlatform::importGPC($_REQUEST['countonly'],'integer',0);
  53. @$sel_worker_id = DevblocksPlatform::importGPC($_REQUEST['worker_id'],'integer',0);
  54. @$sel_group_id = DevblocksPlatform::importGPC($_REQUEST['group_select'],'string','');
  55. list($g_id, $b_id) = CerberusApplication::translateTeamCategoryCode($sel_group_id);
  56. // use date range if specified, else use duration prior to now
  57. $start_time = 0;
  58. $end_time = 0;
  59. if (empty($start) && empty($end)) {
  60. $start = "-5 year";
  61. $end = "now";
  62. $start_time = strtotime($start);
  63. $end_time = strtotime($end);
  64. } else {
  65. $start_time = strtotime($start);
  66. $end_time = strtotime($end);
  67. }
  68. $db = DevblocksPlatform::getDatabaseService();
  69. $tpl = DevblocksPlatform::getTemplateService();
  70. $tpl->cache_lifetime = "0";
  71. $tpl->assign('path', $this->tpl_path);
  72. $workers = DAO_Worker::getAll();
  73. $groups = DAO_Group::getAll();
  74. $buckets = DAO_Bucket::getAll();
  75. $tpl->assign('workers', $workers);
  76. $sql = "SELECT w.id worker_id, t.id ticket_id, t.mask, t.subject, t.created_date, ";
  77. $sql .= "t.updated_date, t.is_waiting, t.team_id, t.category_id ";
  78. $sql .= "FROM ticket t inner join worker w on t.next_worker_id = w.id ";
  79. $sql .= sprintf("WHERE updated_date > %d AND updated_date <= %d ", $start_time, $end_time);
  80. $sql .= "AND t.is_deleted = 0 ";
  81. $sql .= "AND t.is_closed = 0 ";
  82. $sql .= "AND t.spam_score < 0.9000 ";
  83. $sql .= "AND t.spam_training != 'S' ";
  84. if ($sel_worker_id) {
  85. $sql .= sprintf("AND w.id = %d ", $sel_worker_id);
  86. }
  87. if ($g_id > 0) {
  88. $sql .= sprintf("AND t.team_id = %d ", $g_id);
  89. if ($b_id > -1) {
  90. $sql .= sprintf("AND t.category_id = %d ", $b_id);
  91. }
  92. }
  93. $sql .= "ORDER by w.last_name";
  94. $rs_buckets = $db->Execute($sql);
  95. $ticket_assignments = array();
  96. while(!$rs_buckets->EOF) {
  97. $worker_id = intval($rs_buckets->fields['worker_id']);
  98. $mask = $rs_buckets->fields['mask'];
  99. $subject = $rs_buckets->fields['subject'];
  100. $created_date = intval($rs_buckets->fields['created_date']);
  101. $updated_date = intval($rs_buckets->fields['updated_date']);
  102. If ($rs_buckets->fields['is_waiting']) {
  103. $status = "Waiting for Reply";
  104. } else {
  105. $status = "Open";
  106. }
  107. $team_id = intval($rs_buckets->fields['team_id']);
  108. $category_id = intval($rs_buckets->fields['category_id']);
  109. if(!isset($ticket_assignments[$worker_id]))
  110. $ticket_assignments[$worker_id] = array();
  111. unset($assignment);
  112. $assignment->mask = $mask;
  113. $assignment->subject = $subject;
  114. $assignment->created_date = $created_date;
  115. $assignment->updated_date = $updated_date;
  116. $assignment->status = $status;
  117. $assignment->team_id = $groups[$team_id]->name;
  118. if ( $category_id ) {
  119. $assignment->category_id = $buckets[$category_id]->name;
  120. } else {
  121. $assignment->category_id = 'Inbox';
  122. }
  123. $ticket_assignments[$worker_id][] = $assignment;
  124. $rs_buckets->MoveNext();
  125. }
  126. $tpl->assign('ticket_assignments', $ticket_assignments);
  127. //print_r($ticket_assignments);exit;
  128. $tpl->display('file:' . $this->tpl_path . '/report_stats_html.tpl');
  129. }
  130. function getTicketAssignmentChartAction() {
  131. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  132. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  133. @$countonly = DevblocksPlatform::importGPC($_REQUEST['countonly'],'integer',0);
  134. @$sel_worker_id = DevblocksPlatform::importGPC($_REQUEST['worker_id'],'integer',0);
  135. @$sel_group_id = DevblocksPlatform::importGPC($_REQUEST['group_id'],'string','');
  136. list($g_id, $b_id) = CerberusApplication::translateTeamCategoryCode($sel_group_id);
  137. // use date range if specified, else use duration prior to now
  138. $start_time = 0;
  139. $end_time = 0;
  140. if (empty($start) && empty($end)) {
  141. $start = "-5 year";
  142. $end = "now";
  143. $start_time = strtotime($start);
  144. $end_time = strtotime($end);
  145. } else {
  146. $start_time = strtotime($start);
  147. $end_time = strtotime($end);
  148. }
  149. $db = DevblocksPlatform::getDatabaseService();
  150. $workers = DAO_Worker::getAll();
  151. $sql = "SELECT w.id worker_id ,count(*) as hits ";
  152. $sql .= "FROM ticket t inner join worker w on t.next_worker_id = w.id ";
  153. $sql .= sprintf("WHERE updated_date > %d AND updated_date <= %d ", $start_time, $end_time);
  154. $sql .= "AND t.is_deleted = 0 ";
  155. $sql .= "AND t.is_closed = 0 ";
  156. $sql .= "AND t.spam_score < 0.9000 ";
  157. $sql .= "AND t.spam_training != 'S' ";
  158. if ($sel_worker_id) {
  159. $sql .= sprintf("AND w.id = %d ", $sel_worker_id);
  160. }
  161. if ($g_id > 0) {
  162. $sql .= sprintf("AND t.team_id = %d ", $g_id);
  163. if ($b_id > -1) {
  164. $sql .= sprintf("AND t.category_id = %d ", $b_id);
  165. }
  166. }
  167. $sql .= "GROUP by w.id ";
  168. $sql .= "ORDER by hits ";
  169. $rs = $db->Execute($sql);
  170. if($countonly) {
  171. echo intval($rs->RecordCount());
  172. return;
  173. }
  174. if(is_a($rs,'ADORecordSet'))
  175. while(!$rs->EOF) {
  176. $hits = intval($rs->fields['hits']);
  177. $worker_id = $rs->fields['worker_id'];
  178. echo $workers[$worker_id]->getName(true), "\t", $hits . "\n";
  179. $rs->MoveNext();
  180. }
  181. }
  182. };
  183. if (class_exists('Extension_Report',true)):
  184. class AnswernetInternalReportAssetTime extends Extension_Report {
  185. private $tpl_path = null;
  186. function __construct($manifest) {
  187. parent::__construct($manifest);
  188. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  189. }
  190. function render() {
  191. $tpl = DevblocksPlatform::getTemplateService();
  192. $tpl->cache_lifetime = "0";
  193. $tpl->assign('path', $this->tpl_path);
  194. $tpl->assign('start', '-30 days');
  195. $tpl->assign('end', 'now');
  196. $db = DevblocksPlatform::getDatabaseService();
  197. $workers = DAO_Worker::getAll();
  198. $tpl->assign('workers', $workers);
  199. // Teams
  200. $teams = DAO_Group::getAll();
  201. $tpl->assign('teams', $teams);
  202. // Categories
  203. $team_categories = DAO_Bucket::getTeams(); // [TODO] Cache these
  204. $tpl->assign('team_categories', $team_categories);
  205. $tpl->display('file:' . $this->tpl_path . '/report_asset_time.tpl');
  206. }
  207. /*
  208. function getTimeSpentTicketReportAction() {
  209. $db = DevblocksPlatform::getDatabaseService();
  210. @$sel_worker_id = DevblocksPlatform::importGPC($_REQUEST['worker_id'],'integer',0);
  211. $tpl = DevblocksPlatform::getTemplateService();
  212. $tpl->cache_lifetime = "0";
  213. $tpl->assign('path', $this->tpl_path);
  214. // import dates from form
  215. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  216. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  217. // use date rang@$sel_worker_id = DevblocksPlatform::importGPC($_REQUEST['worker_id'],'integer',0);e if specified, else use duration prior to now
  218. $start_time = 0;
  219. $end_time = 0;
  220. if (empty($start) && empty($end)) {
  221. $start = "-30 days";
  222. $end = "now";
  223. $start_time = strtotime($start);
  224. $end_time = strtotime($end);
  225. } else {
  226. $start_time = strtotime($start);
  227. $end_time = strtotime($end);
  228. }
  229. if($start_time === false || $end_time === false) {
  230. $start = "-30 days";
  231. $end = "now";
  232. $start_time = strtotime($start);
  233. $end_time = strtotime($end);
  234. $tpl->assign('invalidDate', true);
  235. }
  236. // reload variables in template
  237. $tpl->assign('start', $start);
  238. $tpl->assign('end', $end);
  239. $workers = DAO_Worker::getAll();
  240. $tpl->assign('workers', $workers);
  241. $sources = DAO_TimeTrackingEntry::getSources();
  242. $tpl->assign('sources', $sources);
  243. $sql = sprintf("SELECT tte.log_date, tte.time_actual_mins, tte.worker_id, tte.notes, ".
  244. "tte.source_extension_id, tte.source_id, ".
  245. "tta.name activity_name, o.name org_name, o.id org_id ".
  246. "FROM timetracking_entry tte ".
  247. "INNER JOIN timetracking_activity tta ON tte.activity_id = tta.id ".
  248. "LEFT JOIN contact_org o ON o.id = tte.debit_org_id ".
  249. "INNER JOIN worker w ON tte.worker_id = w.id ".
  250. "WHERE log_date > %d AND log_date <= %d ".
  251. (($sel_worker_id!=0) ? "AND tte.worker_id = ". $sel_worker_id. ' ' : '') .
  252. "ORDER BY w.first_name, w.last_name, w.id, tte.log_date ",
  253. $start_time,
  254. $end_time
  255. );
  256. //echo $sql;
  257. $rs = $db->Execute($sql);
  258. $time_entries = array();
  259. if(is_a($rs,'ADORecordSet'))
  260. while(!$rs->EOF) {
  261. $mins = intval($rs->fields['time_actual_mins']);
  262. $worker_id = intval($rs->fields['worker_id']);
  263. $org_id = intval($rs->fields['org_id']);
  264. $activity = $rs->fields['activity_name'];
  265. $org_name = $rs->fields['org_name'];
  266. $log_date = intval($rs->fields['log_date']);
  267. $notes = $rs->fields['notes'];
  268. if(!isset($time_entries[$worker_id]))
  269. $time_entries[$worker_id] = array();
  270. unset($time_entry);
  271. $time_entry['activity_name'] = $activity;
  272. $time_entry['org_name'] = $org_name;
  273. $time_entry['mins'] = $mins;
  274. $time_entry['log_date'] = $log_date;
  275. $time_entry['notes'] = $notes;
  276. $time_entry['source_extension_id'] = $rs->fields['source_extension_id'];
  277. $time_entry['source_id'] = intval($rs->fields['source_id']);
  278. $time_entries[$worker_id]['entries'][] = $time_entry;
  279. @$time_entries[$worker_id]['total_mins'] = intval($time_entries[$worker_id]['total_mins']) + $mins;
  280. $rs->MoveNext();
  281. }
  282. //print_r($time_entries);
  283. $tpl->assign('time_entries', $time_entries);
  284. $tpl->display('file:' . $this->tpl_path . '/report_ticket_time_html.tpl');
  285. }
  286. */
  287. function getTimeSpentAssetChartAction() {
  288. // import dates from form
  289. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  290. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  291. @$countonly = DevblocksPlatform::importGPC($_REQUEST['countonly'],'integer',0);
  292. @$sel_worker_id = DevblocksPlatform::importGPC($_REQUEST['worker_id'],'integer',0);
  293. @$sel_group_id = DevblocksPlatform::importGPC($_REQUEST['group_id'],'string','');
  294. list($g_id, $b_id) = CerberusApplication::translateTeamCategoryCode($sel_group_id);
  295. // use date range if specified, else use duration prior to now
  296. $start_time = 0;
  297. $end_time = 0;
  298. if (empty($start) && empty($end)) {
  299. $start = "-30 days";
  300. $end = "now";
  301. $start_time = strtotime($start);
  302. $end_time = strtotime($end);
  303. } else {
  304. $start_time = strtotime($start);
  305. $end_time = strtotime($end);
  306. }
  307. $db = DevblocksPlatform::getDatabaseService();
  308. $groups = DAO_Group::getAll();
  309. $sql = "SELECT sum(tte.time_actual_mins) mins, cfs.field_value ";
  310. $sql .= "FROM timetracking_entry tte ";
  311. $sql .= "INNER JOIN ticket t ON tte.source_id = t.id ";
  312. $sql .= "INNER JOIN custom_field_stringvalue cfs ON t.id = cfs.source_id ";
  313. $sql .= sprintf("WHERE log_date > %d AND log_date <= %d ", $start_time, $end_time);
  314. $sql .= "AND tte.source_extension_id = 'timetracking.source.ticket' ";
  315. $sql .= "AND cfs.field_id = 11 ";
  316. if ($sel_worker_id) {
  317. $sql .= sprintf("AND tte.worker_id = %d ", $sel_worker_id);
  318. }
  319. if ($g_id > 0) {
  320. $sql .= sprintf("AND t.team_id = %d ", $g_id);
  321. if ($b_id > -1) {
  322. $sql .= sprintf("AND t.category_id = %d ", $b_id);
  323. }
  324. }
  325. $sql .= "GROUP BY cfs.field_value ";
  326. $sql .= "ORDER BY cfs.field_value ";
  327. $rs = $db->Execute($sql);
  328. if($countonly) {
  329. echo intval($rs->RecordCount());
  330. return;
  331. }
  332. if(is_a($rs,'ADORecordSet'))
  333. while(!$rs->EOF) {
  334. $mins = intval($rs->fields['mins']);
  335. $field_value = $rs->fields['field_value'];
  336. echo $field_value, "\t", $mins . "\n";
  337. $rs->MoveNext();
  338. }
  339. }
  340. };
  341. endif;
  342. if (class_exists('Extension_Report',true)):
  343. class AnswernetInternalReportClientTime extends Extension_Report {
  344. private $tpl_path = null;
  345. function __construct($manifest) {
  346. parent::__construct($manifest);
  347. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  348. }
  349. function render() {
  350. $tpl = DevblocksPlatform::getTemplateService();
  351. $tpl->cache_lifetime = "0";
  352. $tpl->assign('path', $this->tpl_path);
  353. $tpl->assign('start', '-30 days');
  354. $tpl->assign('end', 'now');
  355. $db = DevblocksPlatform::getDatabaseService();
  356. $workers = DAO_Worker::getAll();
  357. $tpl->assign('workers', $workers);
  358. // Teams
  359. $teams = DAO_Group::getAll();
  360. $tpl->assign('teams', $teams);
  361. // Categories
  362. $team_categories = DAO_Bucket::getTeams(); // [TODO] Cache these
  363. $tpl->assign('team_categories', $team_categories);
  364. $tpl->display('file:' . $this->tpl_path . '/report_client_time.tpl');
  365. }
  366. function getTimeSpentClientChartAction() {
  367. // import dates from form
  368. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  369. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  370. @$countonly = DevblocksPlatform::importGPC($_REQUEST['countonly'],'integer',0);
  371. @$sel_worker_id = DevblocksPlatform::importGPC($_REQUEST['worker_id'],'integer',0);
  372. @$sel_group_id = DevblocksPlatform::importGPC($_REQUEST['group_id'],'string','');
  373. list($g_id, $b_id) = CerberusApplication::translateTeamCategoryCode($sel_group_id);
  374. // use date range if specified, else use duration prior to now
  375. $start_time = 0;
  376. $end_time = 0;
  377. if (empty($start) && empty($end)) {
  378. $start = "-30 days";
  379. $end = "now";
  380. $start_time = strtotime($start);
  381. $end_time = strtotime($end);
  382. } else {
  383. $start_time = strtotime($start);
  384. $end_time = strtotime($end);
  385. }
  386. $db = DevblocksPlatform::getDatabaseService();
  387. $groups = DAO_Group::getAll();
  388. $sql = "SELECT sum(tte.time_actual_mins) mins, cfs.field_value ";
  389. $sql .= "FROM timetracking_entry tte ";
  390. $sql .= "INNER JOIN ticket t ON tte.source_id = t.id ";
  391. $sql .= "INNER JOIN custom_field_stringvalue cfs ON t.id = cfs.source_id ";
  392. $sql .= sprintf("WHERE log_date > %d AND log_date <= %d ", $start_time, $end_time);
  393. $sql .= "AND tte.source_extension_id = 'timetracking.source.ticket' ";
  394. $sql .= "AND cfs.field_id = 10 ";
  395. if ($sel_worker_id) {
  396. $sql .= sprintf("AND tte.worker_id = %d ", $sel_worker_id);
  397. }
  398. if ($g_id > 0) {
  399. $sql .= sprintf("AND t.team_id = %d ", $g_id);
  400. if ($b_id > -1) {
  401. $sql .= sprintf("AND t.category_id = %d ", $b_id);
  402. }
  403. }
  404. $sql .= "GROUP BY cfs.field_value ";
  405. $sql .= "ORDER BY cfs.field_value ";
  406. $rs = $db->Execute($sql);
  407. if($countonly) {
  408. echo intval($rs->RecordCount());
  409. return;
  410. }
  411. if(is_a($rs,'ADORecordSet'))
  412. while(!$rs->EOF) {
  413. $mins = intval($rs->fields['mins']);
  414. $field_value = $rs->fields['field_value'];
  415. echo $field_value, "\t", $mins . "\n";
  416. $rs->MoveNext();
  417. }
  418. }
  419. };
  420. endif;
  421. if (class_exists('Extension_Report',true)):
  422. class AnswernetInternalReportSiteNameTime extends Extension_Report {
  423. private $tpl_path = null;
  424. function __construct($manifest) {
  425. parent::__construct($manifest);
  426. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  427. }
  428. function render() {
  429. $tpl = DevblocksPlatform::getTemplateService();
  430. $tpl->cache_lifetime = "0";
  431. $tpl->assign('path', $this->tpl_path);
  432. $tpl->assign('start', '-30 days');
  433. $tpl->assign('end', 'now');
  434. $db = DevblocksPlatform::getDatabaseService();
  435. $workers = DAO_Worker::getAll();
  436. $tpl->assign('workers', $workers);
  437. // Teams
  438. $teams = DAO_Group::getAll();
  439. $tpl->assign('teams', $teams);
  440. // Categories
  441. $team_categories = DAO_Bucket::getTeams(); // [TODO] Cache these
  442. $tpl->assign('team_categories', $team_categories);
  443. $tpl->display('file:' . $this->tpl_path . '/report_sitename_time.tpl');
  444. }
  445. function getTimeSpentSiteNameChartAction() {
  446. // import dates from form
  447. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  448. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  449. @$countonly = DevblocksPlatform::importGPC($_REQUEST['countonly'],'integer',0);
  450. @$sel_worker_id = DevblocksPlatform::importGPC($_REQUEST['worker_id'],'integer',0);
  451. @$sel_group_id = DevblocksPlatform::importGPC($_REQUEST['group_id'],'string','');
  452. list($g_id, $b_id) = CerberusApplication::translateTeamCategoryCode($sel_group_id);
  453. // use date range if specified, else use duration prior to now
  454. $start_time = 0;
  455. $end_time = 0;
  456. if (empty($start) && empty($end)) {
  457. $start = "-30 days";
  458. $end = "now";
  459. $start_time = strtotime($start);
  460. $end_time = strtotime($end);
  461. } else {
  462. $start_time = strtotime($start);
  463. $end_time = strtotime($end);
  464. }
  465. $db = DevblocksPlatform::getDatabaseService();
  466. $groups = DAO_Group::getAll();
  467. $sql = "SELECT sum(tte.time_actual_mins) mins, cfs.field_value ";
  468. $sql .= "FROM timetracking_entry tte ";
  469. $sql .= "INNER JOIN ticket t ON tte.source_id = t.id ";
  470. $sql .= "INNER JOIN custom_field_stringvalue cfs ON t.id = cfs.source_id ";
  471. $sql .= sprintf("WHERE log_date > %d AND log_date <= %d ", $start_time, $end_time);
  472. $sql .= "AND tte.source_extension_id = 'timetracking.source.ticket' ";
  473. $sql .= "AND cfs.field_id = 1 ";
  474. if ($sel_worker_id) {
  475. $sql .= sprintf("AND tte.worker_id = %d ", $sel_worker_id);
  476. }
  477. if ($g_id > 0) {
  478. $sql .= sprintf("AND t.team_id = %d ", $g_id);
  479. if ($b_id > -1) {
  480. $sql .= sprintf("AND t.category_id = %d ", $b_id);
  481. }
  482. }
  483. $sql .= "GROUP BY cfs.field_value ";
  484. $sql .= "ORDER BY cfs.field_value ";
  485. $rs = $db->Execute($sql);
  486. if($countonly) {
  487. echo intval($rs->RecordCount());
  488. return;
  489. }
  490. if(is_a($rs,'ADORecordSet'))
  491. while(!$rs->EOF) {
  492. $mins = intval($rs->fields['mins']);
  493. $field_value = $rs->fields['field_value'];
  494. echo $field_value, "\t", $mins . "\n";
  495. $rs->MoveNext();
  496. }
  497. }
  498. };
  499. endif;
  500. if (class_exists('Extension_Report',true)):
  501. class AnswernetInternalReportTicketTime extends Extension_Report {
  502. private $tpl_path = null;
  503. function __construct($manifest) {
  504. parent::__construct($manifest);
  505. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  506. }
  507. function render() {
  508. $tpl = DevblocksPlatform::getTemplateService();
  509. $tpl->cache_lifetime = "0";
  510. $tpl->assign('path', $this->tpl_path);
  511. $tpl->assign('start', '-30 days');
  512. $tpl->assign('end', 'now');
  513. $db = DevblocksPlatform::getDatabaseService();
  514. $workers = DAO_Worker::getAll();
  515. $tpl->assign('workers', $workers);
  516. // Teams
  517. $teams = DAO_Group::getAll();
  518. $tpl->assign('teams', $teams);
  519. // Categories
  520. $team_categories = DAO_Bucket::getTeams(); // [TODO] Cache these
  521. $tpl->assign('team_categories', $team_categories);
  522. $tpl->display('file:' . $this->tpl_path . '/report_ticket_time.tpl');
  523. }
  524. function getTimeSpentTicketChartAction() {
  525. $sql_array = array();
  526. // import form data
  527. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  528. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  529. @$countonly = DevblocksPlatform::importGPC($_REQUEST['countonly'],'integer',0);
  530. @$sel_worker_id = DevblocksPlatform::importGPC($_REQUEST['worker_id'],'integer',0);
  531. @$sel_group_id = DevblocksPlatform::importGPC($_REQUEST['group_id'],'string','');
  532. list($g_id, $b_id) = CerberusApplication::translateTeamCategoryCode($sel_group_id);
  533. // use date range if specified, else use duration prior to now
  534. $start_time = 0;
  535. $end_time = 0;
  536. if (empty($start) && empty($end)) {
  537. $start = "-30 days";
  538. $end = "now";
  539. $start_time = strtotime($start);
  540. $end_time = strtotime($end);
  541. } else {
  542. $start_time = strtotime($start);
  543. $end_time = strtotime($end);
  544. }
  545. $db = DevblocksPlatform::getDatabaseService();
  546. // $groups = DAO_Group::getAll();
  547. // $buckets = DAO_Bucket::getAll();
  548. $sql = "SELECT sum(tte.time_actual_mins) mins, t.mask ";
  549. $sql .= "FROM timetracking_entry tte ";
  550. $sql .= "INNER JOIN ticket t ON tte.source_id = t.id ";
  551. $sql .= sprintf("WHERE log_date > %d AND log_date <= %d ", $start_time, $end_time);
  552. $sql .= "AND tte.source_extension_id = 'timetracking.source.ticket' ";
  553. if ($sel_worker_id) {
  554. $sql .= sprintf("AND tte.worker_id = %d ", $sel_worker_id);
  555. }
  556. if ($g_id > 0) {
  557. $sql .= sprintf("AND t.team_id = %d ", $g_id);
  558. if ($b_id > -1) {
  559. $sql .= sprintf("AND t.category_id = %d ", $b_id);
  560. }
  561. }
  562. $sql .= "GROUP BY t.mask ";
  563. $sql .= "ORDER BY mins ";
  564. $rs = $db->Execute($sql);
  565. if($countonly) {
  566. echo intval($rs->RecordCount());
  567. return;
  568. }
  569. if(is_a($rs,'ADORecordSet'))
  570. while(!$rs->EOF) {
  571. $mins = intval($rs->fields['mins']);
  572. $ticket_mask = $rs->fields['mask'];
  573. echo $ticket_mask, "\t", $mins . "\n";
  574. $rs->MoveNext();
  575. }
  576. }
  577. };
  578. endif;
  579. if (class_exists('Extension_Report',true)):
  580. class AnswernetInternalReportWorkerTime extends Extension_Report {
  581. private $tpl_path = null;
  582. function __construct($manifest) {
  583. parent::__construct($manifest);
  584. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  585. }
  586. function render() {
  587. $tpl = DevblocksPlatform::getTemplateService();
  588. $tpl->cache_lifetime = "0";
  589. $tpl->assign('path', $this->tpl_path);
  590. $tpl->assign('start', 'Last Monday');
  591. $tpl->assign('end', 'now');
  592. $db = DevblocksPlatform::getDatabaseService();
  593. $workers = DAO_Worker::getAll();
  594. $tpl->assign('workers', $workers);
  595. // Teams
  596. $teams = DAO_Group::getAll();
  597. $tpl->assign('teams', $teams);
  598. // Categories
  599. $team_categories = DAO_Bucket::getTeams(); // [TODO] Cache these
  600. $tpl->assign('team_categories', $team_categories);
  601. // Security
  602. if(null == ($active_worker = CerberusApplication::getActiveWorker()))
  603. die($translate->_('common.access_denied'));
  604. $tpl->assign('active_worker', $active_worker);
  605. $filename = "worker-".$active_worker->id.".csv";
  606. $href_filename = 'storage/answernet/'.$filename;
  607. $tpl->assign('href_filename', $href_filename);
  608. $tpl->display('file:' . $this->tpl_path . '/report_worker_time.tpl');
  609. }
  610. function getTimeSpentWorkerReportAction() {
  611. $db = DevblocksPlatform::getDatabaseService();
  612. $subtotal = array();
  613. $total_cm = array();
  614. DevblocksPlatform::getExtensions('timetracking.source', true);
  615. @$sel_worker_id = DevblocksPlatform::importGPC($_REQUEST['worker_id'],'integer',0);
  616. @$report_type = DevblocksPlatform::importGPC($_REQUEST['report_type'],'integer',0);
  617. // Security
  618. if(null == ($active_worker = CerberusApplication::getActiveWorker()))
  619. die($translate->_('common.access_denied'));
  620. $tpl = DevblocksPlatform::getTemplateService();
  621. $tpl->cache_lifetime = "0";
  622. $tpl->assign('path', $this->tpl_path);
  623. // import dates from form
  624. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  625. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  626. // use date rang@$sel_worker_id = DevblocksPlatform::importGPC($_REQUEST['worker_id'],'integer',0);e if specified, else use duration prior to now
  627. $start_time = 0;
  628. $end_time = 0;
  629. if (empty($start) && empty($end)) {
  630. $start = "Last Monday";
  631. $end = "now";
  632. $start_time = strtotime($start);
  633. $end_time = strtotime($end);
  634. } else {
  635. $start_time = strtotime($start);
  636. $end_time = strtotime($end);
  637. }
  638. if($start_time === false || $end_time === false) {
  639. $start = "Last Monday";
  640. $end = "now";
  641. $start_time = strtotime($start);
  642. $end_time = strtotime($end);
  643. $tpl->assign('invalidDate', true);
  644. }
  645. // reload variables in template
  646. $tpl->assign('start', $start);
  647. $tpl->assign('end', $end);
  648. $workers = DAO_Worker::getAll();
  649. $tpl->assign('workers', $workers);
  650. $sources = DAO_TimeTrackingEntry::getSources();
  651. $tpl->assign('sources', $sources);
  652. $sql = "SELECT tte.log_date, tte.time_actual_mins, tte.worker_id, tte.notes, ";
  653. $sql .= "tte.source_extension_id, tte.source_id, ";
  654. $sql .= "tta.name activity_name ";
  655. $sql .= "FROM timetracking_entry tte ";
  656. $sql .= "INNER JOIN timetracking_activity tta ON tte.activity_id = tta.id ";
  657. $sql .= "INNER JOIN worker w ON tte.worker_id = w.id ";
  658. $sql .= sprintf("WHERE log_date > %d AND log_date <= %d ", $start_time, $end_time);
  659. if ($sel_worker_id) {
  660. $sql .= sprintf("AND tte.worker_id = %d ", $sel_worker_id);
  661. }
  662. // Do Not use Group By it breaks things.
  663. // $sql .= "GROUP BY activity_name ";
  664. $sql .= "ORDER BY w.last_name, w.first_name, activity_name, w.id, tte.log_date ";
  665. // echo $sql;
  666. $rs = $db->Execute($sql);
  667. $time_entries = array();
  668. $filename = "worker-".$active_worker->id.".csv";
  669. $full_filename = getcwd().'/storage/answernet/'.$filename;
  670. if (file_exists($full_filename)):
  671. if(!is_writable($full_filename)):
  672. die ("The file: $full_filename is not writable");
  673. endif;
  674. elseif( !is_writable( getcwd().'/storage/answernet/' ) ):
  675. die("you cannot create files in this directory. Check the permissions");
  676. endif;
  677. //open the file for Writing
  678. $fh = fopen($full_filename, "w");
  679. //Lock the file for the write operation
  680. flock($fh, LOCK_EX);
  681. $label = array( "Worker Name", "Ticket No", "Client", "Asset", "Site Name", "Billing Group", "Billing Min", "Sub-Total", "Total", "Date Recorded", "Notes");
  682. fputcsv($fh, $label, ",", "\"");
  683. if(is_a($rs,'ADORecordSet'))
  684. while(!$rs->EOF) {
  685. $csv = array();
  686. $custom_fields = array();
  687. $mins = intval($rs->fields['time_actual_mins']);
  688. $worker_id = intval($rs->fields['worker_id']);
  689. $org_id = intval($rs->fields['org_id']);
  690. $activity = $rs->fields['activity_name'];
  691. $log_date = intval($rs->fields['log_date']);
  692. $notes = $rs->fields['notes'];
  693. if(!isset($time_entries[$worker_id])) {
  694. $time_entries[$worker_id] = array();
  695. $time_entries[$worker_id]['mins'] = array();
  696. }
  697. if(!isset($subtotal)) {
  698. $subtotal = array();
  699. $subtotal_activity = $activity;
  700. $subtotal['name'] = $workers[$worker_id]->getName(false);
  701. $subtotal['source_id'] = "";
  702. $subtotal['client'] = "";
  703. $subtotal['asset'] = "";
  704. $subtotal['sitename'] = "";
  705. $subtotal['activity_name'] = $activity;
  706. $subtotal['mins'] = "";
  707. } else if ($subtotal_activity != $activity) {
  708. //Dump Sub Total
  709. fputcsv($fh, $subtotal, ",", "\"");
  710. $subtotal = array();
  711. $subtotal_activity = $activity;
  712. $subtotal['name'] = $workers[$worker_id]->getName(false);
  713. $subtotal['source_id'] = "";
  714. $subtotal['client'] = "";
  715. $subtotal['asset'] = "";
  716. $subtotal['sitename'] = "";
  717. $subtotal['activity_name'] = $activity;
  718. $subtotal['mins'] = "";
  719. }
  720. if(!isset($total_cm)) {
  721. $total_cm = array();
  722. $total_worker_id = $worker_id;
  723. $total_cm['name'] = $workers[$worker_id]->getName(false);
  724. $total_cm['source_id'] = "";
  725. $total_cm['client'] = "";
  726. $total_cm['asset'] = "";
  727. $total_cm['sitename'] = "";
  728. $total_cm['activity_name'] = "";
  729. $total_cm['mins'] = "";
  730. } else if ($total_worker_id != $worker_id) {
  731. //Dump Total
  732. fputcsv($fh, $total_cm, ",", "\"");
  733. $total_cm = array();
  734. $total_worker_id = $worker_id;
  735. $total_cm['name'] = $workers[$worker_id]->getName(false);
  736. $total_cm['source_id'] = "";
  737. $total_cm['client'] = "";
  738. $total_cm['asset'] = "";
  739. $total_cm['sitename'] = "";
  740. $total_cm['activity_name'] = "";
  741. $total_cm['mins'] = "";
  742. }
  743. $csv['name'] = $workers[$worker_id]->getName(false);
  744. unset($time_entry);
  745. $time_entry['activity_name'] = $activity;
  746. $time_entry['mins'] = $mins;
  747. $time_entry['log_date'] = $log_date;
  748. $time_entry['notes'] = $notes;
  749. $time_entry['source_extension_id'] = $rs->fields['source_extension_id'];
  750. $time_entry['source_id'] = intval($rs->fields['source_id']);
  751. $csv['source_id'] = intval($rs->fields['source_id']);
  752. $custom_fields = DAO_CustomFieldValue::getValuesBySourceIds(ChCustomFieldSource_Ticket::ID, $csv['source_id']);
  753. if(isset($custom_fields[$csv['source_id']][10])) {
  754. $csv['client'] = $custom_fields[$csv['source_id']][10];
  755. } else {
  756. $csv['client'] = "";
  757. }
  758. if(isset($custom_fields[$csv['source_id']][11])) {
  759. $csv['asset'] = $custom_fields[$csv['source_id']][11];
  760. } else {
  761. $csv['asset'] = "";
  762. }
  763. if(isset($custom_fields[$csv['source_id']][1])) {
  764. $csv['sitename'] = $custom_fields[$csv['source_id']][1];
  765. } else {
  766. $csv['sitename'] = "";
  767. }
  768. $csv['activity_name'] = $activity;
  769. $csv['mins'] = $mins;
  770. $csv['subtotal'] = "";
  771. $csv['total'] = "";
  772. $csv['log_date'] = date("Y-m-d h:i A", $log_date);
  773. $csv['notes'] = $notes;
  774. $time_entries[$worker_id]['entries'][] = $time_entry;
  775. @$time_entries[$worker_id]['mins'][$activity] = intval($time_entries[$worker_id]['mins'][$activity]) + $mins;
  776. @$time_entries[$worker_id]['mins']['total'] = intval($time_entries[$worker_id]['mins']['total']) + $mins;
  777. $subtotal['subtotal'] = $time_entries[$worker_id]['mins'][$activity];
  778. $total_cm['subtotal'] = "";
  779. $subtotal['total'] = "";
  780. $total_cm['total'] = $time_entries[$worker_id]['mins']['total'];
  781. fputcsv($fh, $csv, ",", "\"");
  782. $rs->MoveNext();
  783. }
  784. // print_r($time_entries);
  785. $tpl->assign('time_entries', $time_entries);
  786. $tpl->assign('report_type', $report_type);
  787. $tpl->assign('href_filename', $href_filename);
  788. fputcsv($fh, $subtotal, ",", "\"");
  789. fputcsv($fh, $total_cm, ",", "\"");
  790. fclose($fh);
  791. $tpl->display('file:' . $this->tpl_path . '/report_worker_time_html.tpl');
  792. }
  793. };
  794. endif;
  795. if (class_exists('Extension_Report',true)):
  796. class AnswernetInternalReportPlus1Time extends Extension_Report {
  797. private $tpl_path = null;
  798. function __construct($manifest) {
  799. parent::__construct($manifest);
  800. $this->tpl_path = dirname(dirname(__FILE__)).'/templates';
  801. }
  802. function render() {
  803. $tpl = DevblocksPlatform::getTemplateService();
  804. $tpl->cache_lifetime = "0";
  805. $tpl->assign('path', $this->tpl_path);
  806. $tpl->assign('start', '-30 days');
  807. $tpl->assign('end', 'now');
  808. $db = DevblocksPlatform::getDatabaseService();
  809. $workers = DAO_Worker::getAll();
  810. $tpl->assign('workers', $workers);
  811. // Teams
  812. $teams = DAO_Group::getAll();
  813. $tpl->assign('teams', $teams);
  814. // Categories
  815. $team_categories = DAO_Bucket::getTeams(); // [TODO] Cache these
  816. $tpl->assign('team_categories', $team_categories);
  817. // Security
  818. if(null == ($active_worker = CerberusApplication::getActiveWorker()))
  819. die($translate->_('common.access_denied'));
  820. $tpl->assign('active_worker', $active_worker);
  821. $filename = "report-plus1-".$active_worker->id.".csv";
  822. $href_filename = 'storage/answernet/'.$filename;
  823. $tpl->assign('href_filename', $href_filename);
  824. $tpl->display('file:' . $this->tpl_path . '/report_plus1_time.tpl');
  825. }
  826. function getTimeSpentPlus1ReportAction() {
  827. $db = DevblocksPlatform::getDatabaseService();
  828. DevblocksPlatform::getExtensions('timetracking.source', true);
  829. // Security
  830. if(null == ($active_worker = CerberusApplication::getActiveWorker()))
  831. die($translate->_('common.access_denied'));
  832. $tpl = DevblocksPlatform::getTemplateService();
  833. $tpl->cache_lifetime = "0";
  834. $tpl->assign('path', $this->tpl_path);
  835. // import dates from form
  836. @$start = DevblocksPlatform::importGPC($_REQUEST['start'],'string','');
  837. @$end = DevblocksPlatform::importGPC($_REQUEST['end'],'string','');
  838. $start_time = 0;
  839. $end_time = 0;
  840. if (empty($start) && empty($end)) {
  841. $start = "-30 days";
  842. $end = "now";
  843. $start_time = strtotime($start);
  844. $end_time = strtotime($end);
  845. } else {
  846. $start_time = strtotime($start);
  847. $end_time = strtotime($end);
  848. }
  849. if($start_time === false || $end_time === false) {
  850. $start = "-30 days";
  851. $end = "now";
  852. $start_time = strtotime($start);
  853. $end_time = strtotime($end);
  854. $tpl->assign('invalidDate', true);
  855. }
  856. $groups = DAO_Group::getAll();
  857. $buckets = DAO_Bucket::getAll();
  858. // reload variables in template
  859. $tpl->assign('start', $start);
  860. $tpl->assign('end', $end);
  861. $sources = DAO_TimeTrackingEntry::getSources();
  862. $tpl->assign('sources', $sources);
  863. $sql = "SELECT t.mask, t.id, sum(tte.time_actual_mins) mins, a.email, ";
  864. $sql .= "t.subject, t.created_date, t.updated_date, t.is_closed, ";
  865. $sql .= "t.is_waiting, t.team_id, t.category_id ";
  866. $sql .= "FROM timetracking_entry tte ";
  867. $sql .= "INNER JOIN ticket t ON tte.source_id = t.id ";
  868. $sql .= "INNER JOIN address a ON t.first_wrote_address_id = a.id ";
  869. $sql .= sprintf("WHERE log_date > %d AND log_date <= %d ", $start_time, $end_time);
  870. $sql .= "GROUP BY t.id ";
  871. $sql .= "ORDER BY t.id, tte.log_date ";
  872. // echo $sql;
  873. $rs = $db->Execute($sql);
  874. $time_entries = array();
  875. $filename = "report-plus1-".$active_worker->id.".csv";
  876. $full_filename = getcwd().'/storage/answernet/'.$filename;
  877. if (file_exists($full_filename)):
  878. if(!is_writable($full_filename)):
  879. die ("The file: $full_filename is not writable");
  880. endif;
  881. elseif( !is_writable( getcwd().'/storage/answernet/' ) ):
  882. die("you cannot create files in this directory. Check the permissions");
  883. endif;
  884. //open the file for Writing
  885. $fh = fopen($full_filename, "w");
  886. //Lock the file for the write operation
  887. flock($fh, LOCK_EX);
  888. $label = array( "Ticket Mask", "Ticket Number", "Client Name", "Asset Name", "Site Name", "Requestor", "Subject", "Created Date", "Last Updated", "Group", "Bucket", "Status", "Total Min");
  889. fputcsv($fh, $label, ",", "\"");
  890. if(is_a($rs,'ADORecordSet'))
  891. while(!$rs->EOF) {
  892. $csv = array();
  893. $custom_fields = array();
  894. $mask = $rs->fields['mask'];
  895. $id = intval($rs->fields['id']);
  896. $email = $rs->fields['email'];
  897. $subject = $rs->fields['subject'];
  898. $team_id = intval($rs->fields['team_id']);
  899. $category_id = intval($rs->fields['category_id']);
  900. $created_date = intval($rs->fields['created_date']);
  901. $updated_date = intval($rs->fields['updated_date']);
  902. $status = "Open";
  903. if (intval($rs->fields['is_waiting'])) {
  904. $status = "Waiting for Reply";
  905. }
  906. if (intval($rs->fields['is_closed'])) {
  907. $status = "Completed";
  908. }
  909. $mins = intval($rs->fields['mins']);
  910. if(!isset($time_entries[$id])) {
  911. $time_entries[$id] = array();
  912. }
  913. $csv['mask'] = $mask;
  914. $csv['id'] = $id;
  915. unset($time_entry);
  916. $time_entry['mask'] = $mask;
  917. $custom_fields = DAO_CustomFieldValue::getValuesBySourceIds(ChCustomFieldSource_Ticket::ID, $id);
  918. if(isset($custom_fields[$id][10])) {
  919. $csv['client'] = $custom_fields[$id][10];
  920. $time_entry['client'] = $custom_fields[$id][10];
  921. } else {
  922. $csv['client'] = "";
  923. $time_entry['client'] = "";
  924. }
  925. if(isset($custom_fields[$id][11])) {
  926. $csv['asset'] = $custom_fields[$id][11];
  927. $time_entry['asset'] = $custom_fields[$id][11];
  928. } else {
  929. $csv['asset'] = "";
  930. $time_entry['asset'] = "";
  931. }
  932. if(isset($custom_fields[$id][1])) {
  933. $csv['sitename'] = $custom_fields[$id][1];
  934. $time_entry['sitename'] = $custom_fields[$id][1];
  935. } else {
  936. $csv['sitename'] = "";
  937. $time_entry['sitename'] = "";
  938. }
  939. $csv['email'] = $email;
  940. $time_entry['email'] = $email;
  941. $csv['subject'] = $subject;
  942. $time_entry['subject'] = $subject;
  943. $csv['created_date'] = date("Y-m-d h:i A", $created_date);
  944. $time_entry['created_date'] = $created_date;
  945. $csv['updated_date'] = date("Y-m-d h:i A", $updated_date);
  946. $time_entry['updated_date'] = $updated_date;
  947. $csv['group'] = $groups[$team_id]->name;
  948. $time_entry['group'] = $groups[$team_id]->name;
  949. if ( $category_id ) {
  950. $csv['bucket'] = $buckets[$category_id]->name;
  951. $time_entry['bucket'] = $buckets[$category_id]->name;
  952. } else {
  953. $csv['bucket'] = 'Inbox';
  954. $time_entry['bucket'] = 'Inbox';
  955. }
  956. $csv['status'] = $status;
  957. $time_entry['status'] = $status;
  958. $csv['mins'] = $mins;
  959. $time_entry['mins'] = $mins;
  960. $time_entries[$id] = $time_entry;
  961. fputcsv($fh, $csv, ",", "\"");
  962. $rs->MoveNext();
  963. }
  964. fclose($fh);
  965. $tpl->assign('time_entries', $time_entries);
  966. $tpl->display('file:' . $this->tpl_path . '/report_plus1_time_html.tpl');
  967. }
  968. };
  969. endif;
  970. ?>