model.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750
  1. <?php
  2. /**
  3. * The model file of report module of ZenTaoPMS.
  4. *
  5. * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
  6. * @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
  7. * @author Chunsheng Wang <chunsheng@cnezsoft.com>
  8. * @package report
  9. * @version $Id: model.php 4726 2013-05-03 05:51:27Z chencongzhi520@gmail.com $
  10. * @link https://www.zentao.net
  11. */
  12. ?>
  13. <?php
  14. class reportModel extends model
  15. {
  16. /**
  17. * 构造函数。
  18. * Construct.
  19. *
  20. * @access public
  21. * @return void
  22. */
  23. public function __construct()
  24. {
  25. parent::__construct();
  26. $this->loadBIDAO();
  27. }
  28. /**
  29. * 计算每项数据的百分比。
  30. * Compute percent of every item.
  31. *
  32. * @param array $datas
  33. * @access public
  34. * @return array
  35. */
  36. public function computePercent($datas)
  37. {
  38. /* Get data total. */
  39. $sum = 0;
  40. foreach($datas as $data) $sum += $data->value;
  41. /* Compute percent, and get total percent. */
  42. $totalPercent = 0;
  43. foreach($datas as $i => $data)
  44. {
  45. $data->percent = $data->value ? round($data->value / $sum, 4) : 0;
  46. $totalPercent += $data->percent;
  47. }
  48. if(isset($i)) $datas[$i]->percent = round(1 - $totalPercent + $datas[$i]->percent, 4);
  49. return $datas;
  50. }
  51. /**
  52. * 创建单个图表的 json 数据。
  53. * Create json data of single charts
  54. *
  55. * @param array $sets
  56. * @param array $dateList
  57. * @return array
  58. */
  59. public function createSingleJSON($sets, $dateList)
  60. {
  61. $preValue = 0;
  62. $data = array();
  63. $now = date('Y-m-d');
  64. $setsDate = array_keys($sets);
  65. foreach($dateList as $date)
  66. {
  67. $date = date('Y-m-d', strtotime($date));
  68. if($date > $now) break;
  69. if(!isset($sets[$date]) && $sets)
  70. {
  71. $tmpDate = $setsDate;
  72. $tmpDate[] = $date;
  73. sort($tmpDate);
  74. $tmpDateStr = ',' . join(',', $tmpDate);
  75. $preDate = rtrim(substr($tmpDateStr, 0, strpos($tmpDateStr, $date)), ',');
  76. $preDate = substr($preDate, strrpos($preDate, ',') + 1);
  77. if($preDate)
  78. {
  79. $preValue = $sets[$preDate];
  80. $preValue = $preValue->value;
  81. }
  82. }
  83. $data[] = isset($sets[$date]) ? $sets[$date]->value : $preValue;
  84. }
  85. return $data;
  86. }
  87. /**
  88. * 转换日期格式。
  89. * Convert date format.
  90. *
  91. * @param array $dateList
  92. * @param string $format
  93. * @access public
  94. * @return array
  95. */
  96. public function convertFormat($dateList, $format = 'Y-m-d')
  97. {
  98. foreach($dateList as $i => $date) $dateList[$i] = date($format, strtotime($date));
  99. return $dateList;
  100. }
  101. /**
  102. * 获取系统的 URL。
  103. * Get System URL.
  104. *
  105. * @access public
  106. * @return string
  107. */
  108. public function getSysURL()
  109. {
  110. if(isset($this->config->mail->domain)) return $this->config->mail->domain;
  111. /* Ger URL when run in shell. */
  112. if(PHP_SAPI == 'cli')
  113. {
  114. $url = parse_url(trim($this->server->argv[1]));
  115. $port = empty($url['port']) || $url['port'] == 80 ? '' : $url['port'];
  116. $host = empty($port) ? $url['host'] : $url['host'] . ':' . $port;
  117. return $url['scheme'] . '://' . $host;
  118. }
  119. else
  120. {
  121. return common::getSysURL();
  122. }
  123. }
  124. /**
  125. * 获取用户的 bugs。
  126. * Get user bugs.
  127. *
  128. * @access public
  129. * @return array
  130. */
  131. public function getUserBugs()
  132. {
  133. return $this->dao->select('t1.id, t1.title, t2.account as user, t1.deadline')
  134. ->from(TABLE_BUG)->alias('t1')
  135. ->leftJoin(TABLE_USER)->alias('t2')
  136. ->on('t1.assignedTo = t2.account')
  137. ->where('t1.assignedTo')->ne('')
  138. ->andWhere('t1.assignedTo')->ne('closed')
  139. ->andWhere('t1.deleted')->eq(0)
  140. ->andWhere('t2.deleted')->eq(0)
  141. ->andWhere('t1.deadline', true)->isNull()
  142. ->orWhere('t1.deadline')->lt(date(DT_DATE1, strtotime('+4 day')))
  143. ->markRight(1)
  144. ->fetchGroup('user');
  145. }
  146. /**
  147. * 获取用户的任务。
  148. * Get user tasks.
  149. *
  150. * @access public
  151. * @return void
  152. */
  153. public function getUserTasks()
  154. {
  155. return $this->dao->select('t1.id, t1.name, t2.account as user, t1.deadline')->from(TABLE_TASK)->alias('t1')
  156. ->leftJoin(TABLE_USER)->alias('t2')->on('t1.assignedTo = t2.account')
  157. ->leftJoin(TABLE_EXECUTION)->alias('t3')->on('t1.execution = t3.id')
  158. ->leftJoin(TABLE_PROJECT)->alias('t4')->on('t1.project = t4.id')
  159. ->where('t1.assignedTo')->ne('')
  160. ->andWhere('t1.deleted')->eq(0)
  161. ->andWhere('t2.deleted')->eq(0)
  162. ->andWhere('t3.deleted')->eq(0)
  163. ->andWhere('t4.deleted')->eq(0)
  164. ->andWhere('t1.status')->in('wait,doing')
  165. ->andWhere('t3.status')->ne('suspended')
  166. ->andWhere('t1.deadline', true)->isNull()
  167. ->orWhere('t1.deadline')->lt(date(DT_DATE1, strtotime('+4 day')))
  168. ->markRight(1)
  169. ->fetchGroup('user');
  170. }
  171. /**
  172. * 获取用户的待办。
  173. * Get user todos.
  174. *
  175. * @access public
  176. * @return array
  177. */
  178. public function getUserTodos()
  179. {
  180. $users = $this->loadModel('user')->getPairs('nodeleted');
  181. $rows = $this->dao->select('*')->from(TABLE_TODO)
  182. ->where('cycle')->eq(0)
  183. ->andWhere('deleted')->eq(0)
  184. ->andWhere('status')->in('wait,doing')
  185. ->fetchAll();
  186. $todos = array();
  187. foreach($rows as $todo)
  188. {
  189. $user = !empty($todo->assignedTo) ? $todo->assignedTo : $todo->account;
  190. if(!isset($users[$user])) continue;
  191. if($todo->type == 'task') $todo->name = $this->dao->findById($todo->objectID)->from(TABLE_TASK)->fetch('name');
  192. if($todo->type == 'bug') $todo->name = $this->dao->findById($todo->objectID)->from(TABLE_BUG)->fetch('title');
  193. $todos[$user][] = $todo;
  194. }
  195. return $todos;
  196. }
  197. /**
  198. * 获取用户的测试单。
  199. * Get user testTasks.
  200. *
  201. * @access public
  202. * @return array
  203. */
  204. public function getUserTestTasks()
  205. {
  206. return $this->dao->select('t1.*, t2.account as user')->from(TABLE_TESTTASK)->alias('t1')
  207. ->leftJoin(TABLE_USER)->alias('t2')->on('t1.owner = t2.account')
  208. ->where('t1.deleted')->eq('0')
  209. ->andWhere('t2.deleted')->eq('0')
  210. ->andWhere("(t1.status='wait' OR t1.status='doing')")
  211. ->fetchGroup('user');
  212. }
  213. /**
  214. * 获取用户的卡片。
  215. * Get user kanban cards.
  216. *
  217. * @access public
  218. * @return array
  219. */
  220. public function getUserKanbanCards()
  221. {
  222. $expireDays = isset($this->config->kanban->reminder->expireDays) ? $this->config->kanban->reminder->expireDays : 1;
  223. $cards = $this->dao->select('id, name, assignedTo, end as deadline, kanban')
  224. ->from(TABLE_KANBANCARD)
  225. ->where('assignedTo')->ne('')
  226. ->andWhere('progress')->lt(100)
  227. ->andWhere('archived')->eq(0)
  228. ->andWhere('deleted')->eq(0)
  229. ->andWhere('end')->lt(date(DT_DATE1, strtotime('+' . $expireDays . ' day')))
  230. ->fetchAll();
  231. $cardGroups = array();
  232. foreach($cards as $card)
  233. {
  234. $assignedToList = explode(',', $card->assignedTo);
  235. foreach($assignedToList as $assignedTo)
  236. {
  237. $cardGroups[$assignedTo][] = $card;
  238. }
  239. }
  240. return $cardGroups;
  241. }
  242. /**
  243. * 获取用户今年的登录次数。
  244. * Get user login count in this year.
  245. *
  246. * @param array $accounts
  247. * @param string $year
  248. * @access public
  249. * @return int
  250. */
  251. public function getUserYearLogins($accounts, $year)
  252. {
  253. return $this->dao->select('COUNT(1) AS count')->from(TABLE_ACTION)->where('actor')->in($accounts)->andWhere('LEFT(date, 4)')->eq($year)->andWhere('action')->eq('login')->fetch('count');
  254. }
  255. /**
  256. * 获取用户本年的操作数。
  257. * Get user action count in this year.
  258. *
  259. * @param array $accounts
  260. * @param string $year
  261. * @access public
  262. * @return int
  263. * @param bool $deptEmpty
  264. */
  265. public function getUserYearActions($accounts, $year, $deptEmpty = true)
  266. {
  267. return $this->dao->select('COUNT(1) AS count')->from(TABLE_ACTION)
  268. ->where('LEFT(date, 4)')->eq($year)
  269. ->beginIF($accounts)->andWhere('actor')->in($accounts)->fi()
  270. ->fetch('count');
  271. }
  272. /**
  273. * 获取用户某年的动态数量。
  274. * Get contribution count in this year of accounts.
  275. *
  276. * @param array $accounts
  277. * @param string $year
  278. * @access public
  279. * @return int
  280. */
  281. public function getUserYearContributionCount($accounts, $year)
  282. {
  283. $stmt = $this->dao->select('id,objectType,action')->from(TABLE_ACTION)
  284. ->where('LEFT(date, 4)')->eq($year)
  285. ->andWhere('objectType')->in(array_keys($this->config->report->annualData['contributionCount']))
  286. ->beginIF($accounts)->andWhere('actor')->in($accounts)->fi()
  287. ->query();
  288. $count = 0;
  289. while($action = $stmt->fetch())
  290. {
  291. if(isset($this->config->report->annualData['contributionCount'][$action->objectType][strtolower($action->action)])) $count ++;
  292. }
  293. return $count;
  294. }
  295. /**
  296. * 获取贡献数的提示信息。
  297. * Get tips of contribution count.
  298. *
  299. * @param string $mode
  300. * @access public
  301. * @return array
  302. */
  303. public function getContributionCountTips($mode)
  304. {
  305. if($this->config->edition == 'open')
  306. {
  307. unset($this->lang->report->contributionCountObject['audit']);
  308. unset($this->lang->report->contributionCountObject['issue']);
  309. unset($this->lang->report->contributionCountObject['risk']);
  310. unset($this->lang->report->contributionCountObject['qa']);
  311. unset($this->lang->report->contributionCountObject['feedback']);
  312. unset($this->lang->report->contributionCountObject['ticket']);
  313. }
  314. if($this->config->edition == 'biz')
  315. {
  316. unset($this->lang->report->contributionCountObject['audit']);
  317. unset($this->lang->report->contributionCountObject['issue']);
  318. unset($this->lang->report->contributionCountObject['risk']);
  319. unset($this->lang->report->contributionCountObject['qa']);
  320. }
  321. $tips = isset($this->lang->report->tips->contributionCount[$mode]) ? $this->lang->report->tips->contributionCount[$mode] . '<br>' : $this->lang->report->tips->contributionCount['company'] . '<br>';
  322. foreach($this->lang->report->contributionCountObject as $objectTip) $tips .= $objectTip . '<br>';
  323. return $tips;
  324. }
  325. /**
  326. * 获取用户某年的动态数据。
  327. * Get user contributions data in this year.
  328. *
  329. * @param array $accounts
  330. * @param string $year
  331. * @access public
  332. * @return array
  333. */
  334. public function getUserYearContributions($accounts, $year)
  335. {
  336. /* Get required actions for annual report. */
  337. $filterActions = array();
  338. $stmt = $this->dao->select('*')->from(TABLE_ACTION)
  339. ->where('LEFT(date, 4)')->eq($year)
  340. ->andWhere('objectType')->in(array_keys($this->config->report->annualData['contributions']))
  341. ->beginIF($accounts)->andWhere('actor')->in($accounts)->fi()
  342. ->orderBy('objectType,objectID,id')
  343. ->query();
  344. $tplData['project'] = $this->dao->select('id')->from(TABLE_PROJECT)->where('isTpl')->eq('1')->fetchPairs();
  345. $tplData['task'] = $this->dao->select('id')->from(TABLE_TASK)->where('isTpl')->eq('1')->fetchPairs();
  346. while($action = $stmt->fetch())
  347. {
  348. if($action->objectType == 'task' && isset($tplData['task'][$action->objectID])) continue; // 过滤模板任务
  349. if(in_array($action->objectType, array('project', 'execution')) && isset($tplData['project'][$action->objectID])) continue; // 过滤模板项目和执行
  350. if(isset($this->config->report->annualData['contributions'][$action->objectType][strtolower($action->action)])) $filterActions[$action->objectType][$action->objectID][$action->id] = $action;
  351. }
  352. /* Only get undeleted actions. */
  353. $actionGroups = array();
  354. foreach($filterActions as $objectType => $objectActions)
  355. {
  356. $deletedIdList = $this->dao->select('id')->from($this->config->objectTables[$objectType])->where('deleted')->eq('1')->andWhere('id')->in(array_keys($objectActions))->fetchPairs();
  357. foreach($objectActions as $actions)
  358. {
  359. foreach($actions as $action)
  360. {
  361. if(!isset($deletedIdList[$action->id])) $actionGroups[$objectType][$action->id] = $action;
  362. }
  363. }
  364. }
  365. /* Calculate the number of actions . */
  366. $contributions = array();
  367. foreach($actionGroups as $objectType => $actions)
  368. {
  369. foreach($actions as $action)
  370. {
  371. $actionName = $this->config->report->annualData['contributions'][$objectType][strtolower($action->action)];
  372. $type = $actionName == 'svnCommit' || $actionName == 'gitCommit' ? 'repo' : $objectType;
  373. if(!isset($contributions[$type][$actionName])) $contributions[$type][$actionName] = 0;
  374. $contributions[$type][$actionName] += 1;
  375. }
  376. }
  377. $contributions['case']['run'] = $this->dao->select('COUNT(1) AS count')->from(TABLE_TESTRESULT)->alias('t1')
  378. ->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case=t2.id')
  379. ->where('LEFT(t1.date, 4)')->eq($year)
  380. ->andWhere('t2.deleted')->eq('0')
  381. ->beginIF($accounts)->andWhere('t1.lastRunner')->in($accounts)->fi()
  382. ->fetch('count');
  383. return $contributions;
  384. }
  385. /**
  386. * 获取用户某年的待办统计。
  387. * Get user todo stat in this year.
  388. *
  389. * @param array $accounts
  390. * @param string $year
  391. * @access public
  392. * @return object
  393. */
  394. public function getUserYearTodos($accounts, $year)
  395. {
  396. return $this->dao->select("COUNT(1) AS count, sum(if((`status` != 'done'), 1, 0)) AS `undone`, sum(if((`status` = 'done'), 1, 0)) AS `done`")->from(TABLE_TODO)
  397. ->where('LEFT(date, 4)')->eq($year)
  398. ->andWhere('deleted')->eq('0')
  399. ->andWhere('vision')->eq($this->config->vision)
  400. ->beginIF($accounts)->andWhere('account')->in($accounts)->fi()
  401. ->fetch();
  402. }
  403. /**
  404. * 获取用户某年的工时统计。
  405. * Get user effort stat in this year.
  406. *
  407. * @param array $accounts
  408. * @param string $year
  409. * @access public
  410. * @return object
  411. */
  412. public function getUserYearEfforts($accounts, $year)
  413. {
  414. $effort = $this->dao->select('COUNT(1) AS count, SUM(consumed) AS consumed')->from(TABLE_EFFORT)
  415. ->where('LEFT(date, 4)')->eq($year)
  416. ->andWhere('deleted')->eq(0)
  417. ->beginIF($accounts)->andWhere('account')->in($accounts)->fi()
  418. ->fetch();
  419. $effort->consumed = !empty($effort->consumed) ? round($effort->consumed, 2) : 0;
  420. return $effort;
  421. }
  422. /**
  423. * 获取用户某年的产品下创建的需求、计划,创建和关闭的需求数量统计。
  424. * Get count of created story,plan and closed story by accounts every product in this year.
  425. *
  426. * @param array $accounts
  427. * @param string $year
  428. * @access public
  429. * @return array
  430. */
  431. public function getUserYearProducts($accounts, $year)
  432. {
  433. /* Get changed products in this year. */
  434. list($products, $planGroups, $createdStoryStats, $closedStoryStats) = $this->reportTao->getAnnualProductStat($accounts, $year);
  435. /* Merge created plan, created story and closed story in every product. */
  436. foreach($products as $productID => $product)
  437. {
  438. $product->plan = 0;
  439. $product->requirement = 0;
  440. $product->story = 0;
  441. $product->epic = 0;
  442. $product->closed = 0;
  443. $plans = zget($planGroups, $productID, array());
  444. if($plans) $product->plan = count($plans);
  445. $createdStoryStat = zget($createdStoryStats, $productID, '');
  446. if($createdStoryStat)
  447. {
  448. $product->requirement = $createdStoryStat->requirement;
  449. $product->story = $createdStoryStat->story;
  450. $product->epic = $createdStoryStat->epic;
  451. }
  452. $closedStoryStat = zget($closedStoryStats, $productID, '');
  453. if($closedStoryStat) $product->closed = $closedStoryStat->closed;
  454. }
  455. return $products;
  456. }
  457. /**
  458. * 获取用户某年内每次执行的已完成任务、故事和已解决的bug。
  459. * Get count of finished task, story and resolved bug by accounts every executions in a year.
  460. *
  461. * @param array $accounts
  462. * @param string $year
  463. * @access public
  464. * @return array
  465. */
  466. public function getUserYearExecutions($accounts, $year)
  467. {
  468. /* Get changed executions in this year. */
  469. list($executions, $finishedTask, $finishedStory, $resolvedBugs) = $this->reportTao->getAnnualExecutionStat($accounts, $year);
  470. foreach($executions as $executionID => $execution)
  471. {
  472. $execution->task = zget($finishedTask, $executionID, 0);
  473. $execution->story = zget($finishedStory, $executionID, 0);
  474. $execution->bug = zget($resolvedBugs, $executionID, 0);
  475. }
  476. return $executions;
  477. }
  478. /**
  479. * 获取所有时间的状态,包括需求、任务和 bug。
  480. * Get status stat that is all time, include story, task and bug.
  481. *
  482. * @access public
  483. * @return array
  484. */
  485. public function getAllTimeStatusStat()
  486. {
  487. $statusStat = array();
  488. $statusStat['story'] = $this->dao->select('status, count(status) as count')->from(TABLE_STORY)->where('deleted')->eq(0)->andWhere('type')->eq('story')->groupBy('status')->fetchPairs('status', 'count');
  489. $statusStat['task'] = $this->dao->select('status, count(status) as count')->from(TABLE_TASK)->where('deleted')->eq(0)->groupBy('status')->fetchPairs('status', 'count');
  490. $statusStat['bug'] = $this->dao->select('status, count(status) as count')->from(TABLE_BUG)->where('deleted')->eq(0)->groupBy('status')->fetchPairs('status', 'count');
  491. return $statusStat;
  492. }
  493. /**
  494. * 获取年度需求、任务或者 bug 的状态统计。
  495. * Get year object stat, include status and action stat
  496. *
  497. * @param array $accounts
  498. * @param string $year
  499. * @param string $objectType story|task|bug
  500. * @access public
  501. * @return array
  502. */
  503. public function getYearObjectStat($accounts, $year, $objectType)
  504. {
  505. if($objectType == 'story') $table = TABLE_STORY;
  506. if($objectType == 'task') $table = TABLE_TASK;
  507. if($objectType == 'bug') $table = TABLE_BUG;
  508. if(empty($table)) return array();
  509. $objectTypeList = $objectType == 'story' ? array('story', 'requirement', 'epic') : array($objectType);
  510. $months = $this->getYearMonths($year);
  511. $stmt = $this->dao->select('t1.*, t2.status, t2.deleted')->from(TABLE_ACTION)->alias('t1')
  512. ->leftJoin($table)->alias('t2')->on('t1.objectID=t2.id')
  513. ->where('LEFT(t1.date, 4)')->eq($year)
  514. ->andWhere('t1.objectType')->in($objectTypeList)
  515. ->andWhere('t1.action')->in($this->config->report->annualData['monthAction'][$objectType])
  516. ->beginIF($accounts)->andWhere('t1.actor')->in($accounts)->fi()
  517. ->query();
  518. /* Build object action stat and object status stat. */
  519. $actionStat = array();
  520. $statusStat = array();
  521. while($action = $stmt->fetch())
  522. {
  523. /* Story, bug can from feedback and ticket, task can from feedback, change this action down to opened. */
  524. $lowerAction = strtolower($action->action);
  525. if(in_array($lowerAction, array('fromfeedback', 'fromticket'))) $lowerAction = 'opened';
  526. $objectID = $action->objectID;
  527. if($action->deleted == '0' && $lowerAction == 'opened')
  528. {
  529. if(!isset($statusStat[$action->status])) $statusStat[$action->status] = 0;
  530. if(!isset($statedObjectIDList[$objectID])) $statusStat[$action->status] ++;
  531. $statedObjectIDList[$objectID] = $objectID;
  532. }
  533. if(!isset($actionStat[$lowerAction]))
  534. {
  535. foreach($months as $month) $actionStat[$lowerAction][$month] = 0;
  536. }
  537. $month = substr($action->date, 0, 7);
  538. $actionStat[$lowerAction][$month] += 1;
  539. }
  540. return array('statusStat' => $statusStat, 'actionStat' => $actionStat);
  541. }
  542. /**
  543. * 获取年度用例的结果状态和动态统计。
  544. * Get year case stat, include result and action stat.
  545. *
  546. * @param array $accounts
  547. * @param string $year
  548. * @access public
  549. * @return array
  550. */
  551. public function getYearCaseStat($accounts, $year)
  552. {
  553. $actionStat = $resultStat = array();
  554. $months = $this->getYearMonths($year);
  555. foreach($months as $month) $actionStat['opened'][$month] = $actionStat['run'][$month] = $actionStat['createBug'][$month] = 0;
  556. return $this->reportTao->buildAnnualCaseStat($accounts, $year, $actionStat, $resultStat);
  557. }
  558. /**
  559. * 获取年度月份。
  560. * Get year months.
  561. *
  562. * @param string $year
  563. * @access public
  564. * @return array
  565. */
  566. public function getYearMonths($year)
  567. {
  568. $months = array();
  569. for($i = 1; $i <= 12; $i ++) $months[] = $year . '-' . sprintf('%02d', $i);
  570. return $months;
  571. }
  572. /**
  573. * 获取状态总览。
  574. * Get status overview.
  575. *
  576. * @param string $objectType
  577. * @param array $statusStat
  578. * @access public
  579. * @return string
  580. */
  581. public function getStatusOverview($objectType, $statusStat)
  582. {
  583. $allCount = 0;
  584. $undoneCount = 0;
  585. foreach($statusStat as $status => $count)
  586. {
  587. $allCount += $count;
  588. if($objectType == 'story' && $status != 'closed') $undoneCount += $count;
  589. if($objectType == 'task' && $status != 'done' && $status != 'closed' && $status != 'cancel') $undoneCount += $count;
  590. if($objectType == 'bug' && $status == 'active') $undoneCount += $count;
  591. }
  592. $overview = '';
  593. if($objectType == 'story') $overview .= $this->lang->report->annualData->allStory;
  594. if($objectType == 'task') $overview .= $this->lang->report->annualData->allTask;
  595. if($objectType == 'bug') $overview .= $this->lang->report->annualData->allBug;
  596. $overview .= ' &nbsp; ' . $allCount;
  597. $overview .= '<br />';
  598. $overview .= $objectType == 'bug' ? $this->lang->report->annualData->unresolve : $this->lang->report->annualData->undone;
  599. $overview .= ' &nbsp; ' . $undoneCount;
  600. return $overview;
  601. }
  602. /**
  603. * 测试获取项目状态总览。
  604. * Get project status overview.
  605. *
  606. * @param array $accounts
  607. * @access public
  608. * @return array
  609. */
  610. public function getProjectStatusOverview($accounts = array())
  611. {
  612. $projectStatus = $this->dao->select('t1.id,t1.status')->from(TABLE_PROJECT)->alias('t1')
  613. ->leftJoin(TABLE_TEAM)->alias('t2')->on("t1.id=t2.root")
  614. ->where('t1.type')->in('project')
  615. ->andWhere('t2.type')->eq('project')
  616. ->beginIF(!empty($accounts))->andWhere('t2.account')->in($accounts)->fi()
  617. ->andWhere('t1.deleted')->eq(0)
  618. ->fetchPairs();
  619. $statusOverview = array();
  620. foreach($projectStatus as $status)
  621. {
  622. if(!isset($statusOverview[$status])) $statusOverview[$status] = 0;
  623. $statusOverview[$status] ++;
  624. }
  625. return $statusOverview;
  626. }
  627. /**
  628. * 为 API 获取输出的数据。
  629. * Get output data for API.
  630. *
  631. * @param array $accounts
  632. * @param string $year
  633. * @access public
  634. * @return array
  635. */
  636. public function getOutput4API($accounts, $year)
  637. {
  638. $processedOutput = array();
  639. $outputData = $this->reportTao->getOutputData($accounts, $year);
  640. foreach($this->config->report->outputData as $objectType => $actions)
  641. {
  642. if(!isset($outputData[$objectType])) continue;
  643. $objectActions = $outputData[$objectType];
  644. $processedOutput[$objectType]['total'] = array_sum($objectActions);
  645. foreach($actions as $action => $langCode)
  646. {
  647. if(empty($objectActions[$action])) continue;
  648. $processedOutput[$objectType]['actions'][$langCode]['code'] = $langCode;
  649. $processedOutput[$objectType]['actions'][$langCode]['name'] = $this->lang->report->annualData->actionList[$langCode];
  650. $processedOutput[$objectType]['actions'][$langCode]['total'] = $objectActions[$action];
  651. }
  652. }
  653. return $processedOutput;
  654. }
  655. /**
  656. * 获取项目和执行名称。
  657. * Get project and execution name.
  658. *
  659. * @access public
  660. * @return array
  661. */
  662. public function getProjectExecutions()
  663. {
  664. $executions = $this->dao->select('t1.id, t1.name, t2.name as projectname, t1.status, t1.multiple')
  665. ->from(TABLE_EXECUTION)->alias('t1')
  666. ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id')
  667. ->where('t1.deleted')->eq(0)
  668. ->andWhere('t1.type')->in('stage,sprint')
  669. ->fetchAll();
  670. $pairs = array();
  671. foreach($executions as $execution)
  672. {
  673. if($execution->multiple) $pairs[$execution->id] = $execution->projectname . '/' . $execution->name;
  674. if(!$execution->multiple) $pairs[$execution->id] = $execution->projectname;
  675. }
  676. return $pairs;
  677. }
  678. }