znt/module/report/tao.php

259 lines
12 KiB
PHP

<?php
declare(strict_types=1);
/**
* The tao file of report module of ZenTaoPMS.
*
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
* @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Mengyi Liu <liumengyi@easycorp.ltd>
* @package report
* @link https://www.zentao.net
*/
class reportTao extends reportModel
{
/**
* 获取某年的年度产品数据。
* Get annual product stat.
*
* @param array $accounts
* @param string $year
* @access public
* @return array
*/
protected function getAnnualProductStat(array $accounts, string $year): array
{
/* Get created plans, created stories and closed stories in this year. */
$planGroups = $this->dao->select('t1.id,t1.product')->from(TABLE_PRODUCTPLAN)->alias('t1')
->leftJoin(TABLE_ACTION)->alias('t2')->on("t1.id=t2.objectID and t2.objectType='productplan'")
->where('t1.deleted')->eq(0)
->andWhere('LEFT(t2.date, 4)')->eq($year)
->beginIF($accounts)->andWhere('t2.actor')->in($accounts)->fi()
->andWhere('t2.action')->eq('opened')
->fetchGroup('product', 'id');
$createdStoryStats = $this->dao->select("product,sum(if((type = 'requirement'), 1, 0)) as requirement, sum(if((type = 'story'), 1, 0)) as story, sum(if((type = 'epic'), 1, 0)) as epic")->from(TABLE_STORY)
->where('deleted')->eq(0)
->andWhere('LEFT(openedDate, 4)')->eq($year)
->beginIF($accounts)->andWhere('openedBy')->in($accounts)->fi()
->groupBy('product')
->fetchAll('product');
$closedStoryStats = $this->dao->select("product,sum(if((status = 'closed'), 1, 0)) as closed")->from(TABLE_STORY)
->where('deleted')->eq(0)
->andWhere('LEFT(closedDate, 4)')->eq($year)
->beginIF($accounts)->andWhere('closedBy')->in($accounts)->fi()
->groupBy('product')
->fetchAll('product');
/* Get products created or operated in this year. */
$products = $this->dao->select('id,name')->from(TABLE_PRODUCT)
->where('deleted')->eq(0)
->andWhere('LEFT(createdDate, 4)', true)->eq($year)
->beginIF($accounts)
->andWhere('createdBy', true)->in($accounts)
->orWhere('PO')->in($accounts)
->orWhere('QD')->in($accounts)
->orWhere('RD')->in($accounts)
->markRight(1)
->fi()
->orWhere('id')->in(array_merge(array_keys($planGroups), array_keys($createdStoryStats), array_keys($closedStoryStats)))
->markRight(1)
->andWhere('shadow')->eq(0)
->fetchAll('id');
return array($products, $planGroups, $createdStoryStats, $closedStoryStats);
}
/**
* 获取某年的年度执行数据。
* Get annual execution stat.
*
* @param array $accounts
* @param string $year
* @access public
* @return array
*/
protected function getAnnualExecutionStat(array $accounts, string $year): array
{
/* Get count of finished task and stories. */
$finishedMultiTasks = $this->dao->select('distinct t1.root')->from(TABLE_TEAM)->alias('t1')
->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.root=t2.id')
->where('t1.type')->eq('execution')
->beginIF($accounts)->andWhere('account')->in($accounts)->fi()
->andWhere('t2.multiple')->eq('1')
->andWhere('LEFT(`join`, 4)')->eq($year)
->fetchPairs();
$taskStats = $this->dao->select('execution, COUNT(1) AS finishedTask')->from(TABLE_TASK)
->where('deleted')->eq(0)
->andWhere('(finishedBy', true)->ne('')
->andWhere('LEFT(finishedDate, 4)')->eq($year)
->beginIF($accounts)->andWhere('finishedBy')->in($accounts)->fi()
->markRight(1)
->orWhere('id')->in($finishedMultiTasks)
->markRight(1)
->groupBy('execution')
->fetchAll('execution');
$finishedTask = array();
if(!empty($taskStats)) foreach($taskStats as $executionID => $taskStat) $finishedTask[$executionID] = $taskStat->finishedTask;
/* Get changed executions in this year. */
$executions = $this->dao->select('id,name')->from(TABLE_EXECUTION)->where('deleted')->eq(0)
->andwhere('type')->eq('sprint')
->andwhere('multiple')->eq('1')
->andWhere('LEFT(`begin`, 4)', true)->eq($year)
->orWhere('LEFT(`end`, 4)')->eq($year)
->markRight(1)
->beginIF($accounts)
->andWhere('openedBy', true)->in($accounts)
->orWhere('PO')->in($accounts)
->orWhere('PM')->in($accounts)
->orWhere('QD')->in($accounts)
->orWhere('RD')->in($accounts)
->orWhere('id')->in(array_keys($taskStats))
->markRight(1)
->fi()
->orderBy('`order` desc')
->fetchAll('id');
$finishedStory = $this->dao->select('t1.project, COUNT(1) as count')->from(TABLE_PROJECTSTORY)->alias('t1')
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id')
->where('t1.project')->in(array_keys($executions))
->andWhere('t2.stage', true)->in(array('verified', 'released'))
->orWhere('t2.closedReason')->eq('done')
->markRight(1)
->groupBy('t1.project')
->fetchPairs();
/* Get resolved bugs in this year. */
$resolvedBugs = $this->dao->select('execution, COUNT(1) AS count')->from(TABLE_BUG)
->where('deleted')->eq(0)
->andWhere('status')->eq('closed')
->andWhere('resolution')->eq('fixed')
->andWhere('execution')->in(array_keys($executions))
->andWhere('LEFT(resolvedDate, 4)')->eq($year)
->beginIF($accounts)->andWhere('resolvedBy')->in($accounts)->fi()
->groupBy('execution')
->fetchPairs();
return array($executions, $finishedTask, $finishedStory, $resolvedBugs);
}
/**
* 构建年度报告的用例数据。
* Build annual case stat.
*
* @param array $accounts
* @param string $year
* @param array $actionStat
* @param array $resultStat
* @access protected
* @return array
*/
protected function buildAnnualCaseStat(array $accounts, string $year, array $actionStat, array $resultStat): array
{
/* Build create case stat. */
$stmt = $this->dao->select('t1.*')->from(TABLE_ACTION)->alias('t1')
->leftJoin(TABLE_CASE)->alias('t2')->on('t1.objectID=t2.id')
->where('t1.objectType')->eq('case')
->andWhere('t2.deleted')->eq(0)
->andWhere('t1.action')->eq('opened')
->andWhere('LEFT(t1.date, 4)')->eq($year)
->beginIF($accounts)->andWhere('t1.actor')->in($accounts)->fi()
->query();
while($action = $stmt->fetch())
{
$month = substr($action->date, 0, 7);
$actionStat['opened'][$month] += 1;
}
/* Build testcase result stat and run case stat. */
$stmt = $this->dao->select('*')->from(TABLE_CASE)
->where('LEFT(lastRunDate, 4)')->eq($year)
->andWhere('deleted')->eq('0')
->beginIF($accounts)->andWhere('lastRunner')->in($accounts)->fi()
->query();
while($testResult = $stmt->fetch())
{
if(!isset($resultStat[$testResult->lastRunResult])) $resultStat[$testResult->lastRunResult] = 0;
$resultStat[$testResult->lastRunResult] += 1;
$month = substr($testResult->lastRunDate, 0, 7);
$actionStat['run'][$month] += 1;
}
/* Build testcase create bug stat. */
$stmt = $this->dao->select('t1.*')->from(TABLE_ACTION)->alias('t1')
->leftJoin(TABLE_BUG)->alias('t2')->on('t1.objectID=t2.id')
->where('t1.objectType')->eq('bug')
->andWhere('t2.deleted')->eq(0)
->andWhere('LEFT(t1.date, 4)')->eq($year)
->andWhere('t1.action')->eq('opened')
->andWhere('t2.case')->ne('0')
->beginIF($accounts)->andWhere('t1.actor')->in($accounts)->fi()
->query();
while($action = $stmt->fetch())
{
$month = substr($action->date, 0, 7);
$actionStat['createBug'][$month] += 1;
}
return array('resultStat' => $resultStat, 'actionStat' => $actionStat);
}
/**
* 获取要输出的数据。
* Get output data.
*
* @param array $accounts
* @param string $year
* @access protected
* @return array
*/
protected function getOutputData(array $accounts, string $year): array
{
/* Get output actions. */
$outputData = $actionGroup = $objectIdList = array();
$stmt = $this->dao->select('id,objectType,objectID,action,extra')->from(TABLE_ACTION)
->where('objectType')->in(array_keys($this->config->report->outputData))
->andWhere('LEFT(date, 4)')->eq($year)
->beginIF($accounts)->andWhere('actor')->in($accounts)->fi()
->query();
while($action = $stmt->fetch())
{
if($action->objectType == 'release' && $action->action == 'changestatus')
{
if($action->extra == 'terminate') $action->action = 'stoped';
if($action->extra == 'normal') $action->action = 'activated';
}
unset($action->extra);
if(!isset($this->config->report->outputData[$action->objectType][$action->action])) continue;
if(!isset($outputData[$action->objectType][$action->action])) $outputData[$action->objectType][$action->action] = 0;
$objectIdList[$action->objectType][$action->objectID] = $action->objectID;
$actionGroup[$action->objectType][$action->id] = $action;
}
foreach($actionGroup as $objectType => $actions)
{
$deletedIdList = $this->dao->select('id')->from($this->config->objectTables[$objectType])->where('deleted')->eq(1)->andWhere('id')->in($objectIdList[$objectType])->fetchPairs('id', 'id');
foreach($actions as $action)
{
if(!isset($deletedIdList[$action->objectID])) $outputData[$action->objectType][$action->action] += 1;
}
}
/* Get output case data. */
$outputData['case']['createBug'] = $this->dao->select('count(t2.id) as count')->from(TABLE_ACTION)->alias('t1')
->leftJoin(TABLE_BUG)->alias('t2')->on('t1.objectID=t2.id')
->where('t1.objectType')->eq('bug')
->andWhere('t2.deleted')->eq(0)
->andWhere('LEFT(t1.date, 4)')->eq($year)
->andWhere('t1.action')->eq('opened')
->andWhere('t2.case')->ne('0')
->beginIF($accounts)->andWhere('t1.actor')->in($accounts)->fi()
->fetch('count');
$outputData['case']['run'] = $this->dao->select('COUNT(1) AS count')->from(TABLE_TESTRESULT)->alias('t1')
->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case=t2.id')
->where('LEFT(t1.date, 4)')->eq($year)
->andWhere('t2.deleted')->eq(0)
->beginIF($accounts)->andWhere('t1.lastRunner')->in($accounts)->fi()
->fetch('count');
return $outputData;
}
}