* Refactor metric getStatement to dataset.

This commit is contained in:
qixinzhi
2024-01-26 08:43:46 +08:00
parent 04a433bca6
commit d97cb51e89
36 changed files with 499 additions and 735 deletions
@@ -1,166 +0,0 @@
<?php
/**
* [度量项名称]。
* [度量项名称(英文)].
*
* 范围:[范围]
* 对象:[对象]
* 目的:[目的]
* 度量名称:[度量项名称]
* 单位:[单位]
* 描述:[描述度量项的含义]
* 定义:[描述度量项如何定义,计算规则等]
*
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
* @author XXX <XXX@easycorp.ltd>
* @package
* @uses func
* @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @Link https://www.zentao.net
*/
class xxx_of_xxx_in_xxx extends baseCalc
{
/**
* 通用数据源,详情见通用数据源列表。
*/
public $dataset = null;
/**
* 通用数据源对应使用的字段,具体字段根据使用的通用数据源来设置。
*
* 如 public $dataset = "getProjectBugs";
* 涉及的表有 zt_bug t1, zt_product t2, zt_project t3
* 那么$fieldList可以使用 zt_bug表、zt_product表、zt_project表的所有字段;
* 例如 public $fieldList = array('t1.resolvedBy', 't1.resolvedDate', 't2.name as productName', 't3.name as projectName');
*/
public $fieldList = array();
/**
* 度量项计算临时结果。
*
* 如果度量项为单个值, 例如【按全局统计的bug数】, 则为int类型;
* 如果度量项为单个维度, 例如【按产品统计的bug数】, 则为array(productID => value);
* 如果度量项为多个维度 ,例如【按产品统计的每月bug数】,则为array(productID => array(year => array(month => value)));
*/
public $result = array();
/**
* 获取自定义数据源pdo句柄。
*
* 如果设置了通用数据源,该函数将不会被执行;
* 可以使用this->dao进行数据库查询;
* 返回值为PDOStatement。
*/
public function getStatement()
{
/**
* 例如【按全局统计的有效研发需求数】
* return $this->dao->select('count(t1.id) as value')->from(TABLE_STORY)->alias('t1')
* ->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product=t2.id')
* ->where('t1.deleted')->eq(0)
* ->andWhere('t2.deleted')->eq(0)
* ->andWhere('t2.shadow')->eq(0)
* ->andWhere('t1.type')->eq('story')
* ->andWhere('t1.closedReason')->notin('duplicate,willnotdo,bydesign,cancel')
* ->query();
*/
return $this->dao->XXX->query();
}
/**
* 计算度量项。
*
* 对数据源查询得到的数据集进行逐行计算,该函数实现对于一行数据的计算逻辑
* 计算完成后将数据临时记录到$this->result上
*
* @param object $row 数据源的一行数据
*/
public function calculate($row)
{
/**
* 例如【按全局统计的研发需求总数】
* $this->result += 1;
*
* 例如【按全局统计的未关闭Bug数】
* if($row->status != 'closed') $this->result += 1;
*
* 例如【按全局统计的月度修复Bug数】
* $closedDate = $row->closedDate;
* if(empty($closedDate)) return false;
*
* $year = substr($closedDate, 0, 4);
* if($year == '0000') return false;
* $month = substr($closedDate, 5, 2);
*
* if(!isset($this->result[$year])) $this->result[$year] = array();
* if(!isset($this->result[$year][$month])) $this->result[$year][$month] = 0;
* if($row->status == 'closed' and $row->resolution == 'fixed') $this->result[$year][$month] += 1;
*/
}
/**
* 汇总并获取度量项计算结果。
*
* @param array $options 筛选参数,如果不传参,则返回度量项所有数据
* 产品id为5: array('product' => '5')
* 产品id为5,6,7: array('product' => '5,6,7')
* 产品id为5,年份为2023年:array('product' => '5', 'year' => '2023')
*/
public function getResult($options = array())
{
/**
* $this->getRecords($keys) 将 $this->result拍平为
* array(product => 1, year => 2023, month => 03)
* $keys为拍平后的键值数组,需要与$this->result的层级顺序保持一致。
*
* 例如【按全局统计的bug数】
* $this->result = 200;
* $this->getRecords(array('value'));
* 逻辑等同于
* $records = array(array('value' => $this->result = 200));
*
* 例如【按产品统计的bug数】
* $this->result = array(1 => 25, 2 => 33, 5 => 21, ...);
* $this->getRecords(array('product', 'value'));
* 逻辑等同于
* $records = array();
* foreach($this->result as $product => $value)
* {
* $records[] = array('product' => $product, 'value' => $value);
* }
*
* 例如【按产品统计的每月bug数】
* $this->result = array
* (
* 1 => array
* (
* 2023 => array(08 => 21, 12 => 44, ...),
* 2022 => array(08 => 63, 12 => 29, ...),
* ...
* ),
* 2 => array
* (
* 2023 => array(04 => 21, 10 => 44, ...),
* 2022 => array(05 => 63, 07 => 29, ...),
* ...
* ),
* ...
* );
* $this->getRecords(array('product', 'year', 'month', 'value'));
* 逻辑等同于
* $records = array();
* foreach($this->result as $product => $years)
* {
* foreach($years as $year => $months)
* {
* foreach($months as $month => $value)
* {
* $records[] = array('product' => $product, 'year' => $year, 'month' => $month, 'value' => $value);
* }
* }
* }
*/
$records = $this->getRecords(array('value'));
return $this->filterByOptions($records, $options);
}
}
@@ -20,35 +20,33 @@
*/
class rate_of_approved_story_in_product extends baseCalc
{
public $result = array();
public $dataset = 'getDevStoriesWithReview';
public function getStatement()
{
return $this->dao->select("COUNT(t1.result) as total, SUM(CASE WHEN result = 'pass' THEN 1 ELSE 0 END) as pass, t2.product")
->from(TABLE_STORYREVIEW)->alias('t1')
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story=t2.id')
->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t2.product=t3.id')
->where('t2.deleted')->eq(0)
->andWhere('t3.deleted')->eq(0)
->andWhere('t2.type')->eq('story')
->andWhere('t3.shadow')->eq(0)
->andWhere("t3.vision NOT LIKE '%or%'")
->andWhere("t3.vision NOT LIKE '%lite%'")
->groupBy('t2.product')
->query();
}
public $fieldList = array('t2.product', 't1.result');
public $result = array();
public function calculate($row)
{
$total = $row->total;
$pass = $row->pass;
$result = $row->result;
$product = $row->product;
$this->result[$product] = $total == 0 ? 0 : round($pass / $total, 4);
if(!isset($this->result[$product])) $this->result[$product] = array('total' => 0, 'pass' => 0);
$this->result[$product]['total'] += 1;
if($result == 'pass') $this->result[$product]['pass'] += 1;
}
public function getResult($options = array())
{
foreach($this->result as $product => $rate)
{
if(!isset($rate['total']) || !isset($rate['pass'])) continue;
$pass = $rate['pass'];
$total = $rate['total'];
$this->result[$product] = $total == 0 ? 0 : round($pass / $total, 4);
}
$records = $this->getRecords(array('product', 'value'));
return $this->filterByOptions($records, $options);
}
@@ -20,41 +20,33 @@
*/
class case_coverage_of_projected_story_in_product extends baseCalc
{
public $idList = array();
public $dataset = 'getDevStories';
public $fieldList = array('t1.product', 't3.case_count');
public $result = array();
public function getStatement()
{
$caseQuery = $this->dao->select('story, count(DISTINCT id) as case_count')->from(TABLE_CASE)
->groupBy('story')
->get();
return $this->dao->select('t1.product, COUNT(t1.id) as total, SUM(CASE WHEN t3.case_count > 0 THEN 1 ELSE 0 END) as hasCase')->from(TABLE_STORY)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product=t2.id')
->leftJoin("($caseQuery)")->alias('t3')->on('t1.id=t3.story')
->where('t1.stage')->eq('projected')
->andWhere('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->andWhere('t2.shadow')->eq(0)
->andWhere("t1.vision NOT LIKE '%or%'")
->andWhere("t1.vision NOT LIKE '%lite%'")
->groupBy('t1.product')
->query();
}
public function calculate($row)
{
$product = $row->product;
$total = $row->total;
$hasCase = $row->hasCase;
$case = $row->case_count;
$rate = $total ? round($hasCase / $total, 2) : 0;
$this->result[$product] = $rate;
if(!isset($this->result[$product])) $this->result[$product] = array('total' => 0, 'hasCase' => 0);
$this->result[$product]['total'] += 1;
$this->result[$product]['hasCase'] += $case > 0 ? 1 : 0;
}
public function getResult($options = array())
{
foreach($this->result as $product => $rate)
{
if(!isset($rate['total']) || !isset($rate['hasCase'])) continue;
$total = $rate['total'];
$hasCase = $rate['hasCase'];
$this->result[$product] = $total ? round($hasCase / $total, 2) : 0;
}
$records = $this->getRecords(array('product', 'value'));
return $this->filterByOptions($records, $options);
}
@@ -20,19 +20,11 @@
*/
class count_of_annual_created_productplan_in_product extends baseCalc
{
public $result = array();
public $dataset = 'getPlans';
public function getStatement()
{
return $this->dao->select('t1.id,t1.product,t1.createdDate')->from(TABLE_PRODUCTPLAN)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product=t2.id')
->where('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->andWhere('t2.shadow')->eq(0)
->andWhere("t2.vision NOT LIKE '%or%'")
->andWhere("t2.vision NOT LIKE '%lite%'")
->query();
}
public $fieldList = array('t1.product', 't1.createdDate');
public $result = array();
public function calculate($row)
{
@@ -20,19 +20,11 @@
*/
class count_of_annual_finished_productplan_in_product extends baseCalc
{
public $result = array();
public $dataset = 'getPlans';
public function getStatement()
{
return $this->dao->select('t1.id,t1.product,t1.finishedDate')->from(TABLE_PRODUCTPLAN)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product=t2.id')
->where('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->andWhere('t2.shadow')->eq(0)
->andWhere("t2.vision NOT LIKE '%or%'")
->andWhere("t2.vision NOT LIKE '%lite%'")
->query();
}
public $fieldList = array('t1.product', 't1.finishedDate');
public $result = array();
public function calculate($row)
{
@@ -20,32 +20,27 @@
*/
class count_of_delivered_story_in_product extends baseCalc
{
public $result = array();
public $dataset = 'getDevStories';
public function getStatement()
{
return $this->dao->select('t1.product,count(t1.id) as value')->from(TABLE_STORY)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product=t2.id')
->where('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->andWhere('t2.shadow')->eq(0)
->andWhere("t1.vision NOT LIKE '%or%'")
->andWhere("t1.vision NOT LIKE '%lite%'")
->andWhere('t1.stage', true)->eq('released')
->orWhere('t1.closedReason')->eq('done')
->markRight(1)
->groupBy('t1.product')
->query();
}
public $fieldList = array('t1.product', 't1.stage', 't1.closedReason');
public $result = array();
public function calculate($row)
{
$this->result[] = $row;
$stage = $row->stage;
$product = $row->product;
$closedReason = $row->closedReason;
if($stage != 'released' && $closedReason != 'done') return false;
if(!isset($this->result[$row->product])) $this->result[$row->product] = 0;
$this->result[$row->product] += 1;
}
public function getResult($options = array())
{
$records = $this->result;
$records = $this->getRecords(array('product', 'value'));
return $this->filterByOptions($records, $options);
}
}
@@ -20,27 +20,20 @@
*/
class count_of_developed_story_in_product extends baseCalc
{
public $result = array();
public $dataset = 'getDevStories';
public function getStatement()
{
return $this->dao->select('t1.product,count(t1.id) as value')->from(TABLE_STORY)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product=t2.id')
->where('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->andWhere('t2.shadow')->eq(0)
->andWhere('t1.type')->eq('story')
->andWhere("t1.vision NOT LIKE '%or%'")
->andWhere("t1.vision NOT LIKE '%lite%'")
->andWhere('t1.stage', true)->in('developed,testing,tested,verified,released')
->orWhere('t1.closedReason')->eq('done')
->markRight(1)
->groupBy('t1.product')
->query();
}
public $fieldList = array('t1.product', 't1.stage', 't1.closedReason');
public $result = array();
public function calculate($row)
{
$stage = $row->stage;
$product = $row->product;
$closedReason = $row->closedReason;
if(!in_array($stage, array('developed', 'testing', 'tested', 'verified', 'released')) && $closedReason != 'done') return false;
if(!isset($this->result[$row->product])) $this->result[$row->product] = 0;
$this->result[$row->product] += 1;
}
@@ -20,31 +20,26 @@
*/
class count_of_invalid_story_in_product extends baseCalc
{
public $result = array();
public $dataset = 'getDevStories';
public function getStatement()
{
return $this->dao->select('t1.product,count(t1.id) as value')->from(TABLE_STORY)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product=t2.id')
->where('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->andWhere('t1.type')->eq('story')
->andWhere('t2.shadow')->eq(0)
->andWhere('t1.closedReason')->in('duplicate,willnotdo,bydesign,cancel')
->andWhere("t1.vision NOT LIKE '%or%'")
->andWhere("t1.vision NOT LIKE '%lite%'")
->groupBy('t1.product')
->query();
}
public $fieldList = array('t1.product', 't1.closedReason');
public $result = array();
public function calculate($row)
{
$this->result[] = $row;
$product = $row->product;
$closedReason = $row->closedReason;
if(!in_array($closedReason, array('duplicate', 'willnotdo', 'bydesign', 'cancel'))) return false;
if(!isset($this->result[$product])) $this->result[$product] = 0;
$this->result[$product] += 1;
}
public function getResult($options = array())
{
$records = $this->result;
$records = $this->getRecords(array('product', 'value'));
return $this->filterByOptions($records, $options);
}
}
@@ -20,27 +20,21 @@
*/
class count_of_projected_story_in_product extends baseCalc
{
public $result = array();
public $dataset = 'getDevStoriesWithProject';
public function getStatement()
{
return $this->dao->select("COUNT(DISTINCT t1.story) as 'value', t1.product")
->from(TABLE_PROJECTSTORY)->alias('t1')
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story=t2.id')
->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t1.product=t3.id')
->where('t2.deleted')->eq('0')
->andWhere('t3.deleted')->eq('0')
->andWhere("t3.vision NOT LIKE '%or%'")
->andWhere("t3.vision NOT LIKE '%lite%'")
->groupBy('t1.product');
}
public $fieldList = array('t2.id as product', 't3.story');
public $result = array();
public function calculate($row)
{
$product = $row->product;
$value = $row->value;
$story = $row->story;
$this->result[$product] = $value;
if(empty($story)) return false;
if(!isset($this->result[$product])) $this->result[$product] = 0;
$this->result[$product] += 1;
}
public function getResult($options = array())
@@ -20,32 +20,28 @@
*/
class count_of_projected_story_with_case_in_product extends baseCalc
{
public $result = array();
public $dataset = 'getCasesWithStory';
public function getStatement()
{
return $this->dao->select("COUNT(DISTINCT t1.story) as 'value', t1.product")
->from(TABLE_CASE)->alias('t0')
->leftJoin(TABLE_PROJECTSTORY)->alias('t1')->on('t1.story=t0.story')
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story=t2.id')
->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t1.product=t3.id')
->where('t2.deleted')->eq('0')
->andWhere('t3.deleted')->eq('0')
->andWhere("t2.vision NOT LIKE '%or%'")
->andWhere("t2.vision NOT LIKE '%lite%'")
->groupBy('t1.product');
}
public $fieldList = array('t1.product', 't1.story');
public $result = array();
public function calculate($row)
{
$product = $row->product;
$value = $row->value;
$story = $row->story;
$this->result[$product] = $value;
if(!isset($this->result[$product])) $this->result[$product] = array();
$this->result[$product][$story] = $story;
}
public function getResult($options = array())
{
foreach($this->result as $product => $stories)
{
if(!is_array($stories)) continue;
$this->result[$product] = count($stories);
}
$records = $this->getRecords(array('product', 'value'));
return $this->filterByOptions($records, $options);
}
@@ -20,24 +20,19 @@
*/
class count_of_valid_story_in_product extends baseCalc
{
public $result = array();
public $dataset = 'getDevStories';
public function getStatement()
{
return $this->dao->select('t1.product,t1.id')->from(TABLE_STORY)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product=t2.id')
->where('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->andWhere('t2.shadow')->eq(0)
->andWhere('t1.type')->eq('story')
->andWhere('t1.closedReason')->notin('duplicate,willnotdo,bydesign,cancel')
->andWhere("t2.vision NOT LIKE '%or%'")
->andWhere("t2.vision NOT LIKE '%lite%'")
->query();
}
public $fieldList = array('t1.product', 't1.closedReason');
public $result = array();
public function calculate($row)
{
$closedReason = $row->closedReason;
$product = $row->product;
if(in_array($closedReason, array('duplicate', 'willnotdo', 'bydesign', 'cancel'))) return false;
if(!isset($this->result[$row->product])) $this->result[$row->product] = 0;
$this->result[$row->product] += 1;
}
@@ -20,29 +20,22 @@
*/
class ac_of_all_in_waterfall extends baseCalc
{
public $result = array();
public $dataset = 'getProjectEfforts';
public function getStatement()
{
return $this->dao->select('t3.id as project, SUM(t1.consumed) as ac')
->from(TABLE_EFFORT)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.execution=t2.id')
->leftJoin(TABLE_PROJECT)->alias('t3')->on('t2.project=t3.id')
->where('t3.deleted')->eq('0')
->andWhere('t3.type')->eq('project')
->andWhere('t3.model')->in('waterfall,waterfallplus')
->andWhere("t3.vision NOT LIKE '%or%'")
->andWhere("t3.vision NOT LIKE '%lite%'")
->groupBy('t3.id')
->query();
}
public $fieldList = array('t3.id as project', 't1.consumed', 't3.model');
public $result = array();
public function calculate($row)
{
$project = $row->project;
$ac = $row->ac;
$ac = $row->consumed;
$model = $row->model;
if(!isset($this->result[$project])) $this->result[$project] = $ac;
if($model != 'waterfall' && $model != 'waterfallplus') return false;
if(!isset($this->result[$project])) $this->result[$project] = 0;
$this->result[$project] += $ac;
}
public function getResult($options = array())
@@ -20,28 +20,19 @@
*/
class consume_of_all_in_project extends baseCalc
{
public $result = array();
public $dataset = 'getProjectEfforts';
public function getStatement()
{
return $this->dao->select('t3.id as project, SUM(t1.consumed) as consumed')
->from(TABLE_EFFORT)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.execution=t2.id')
->leftJoin(TABLE_PROJECT)->alias('t3')->on('t2.project=t3.id')
->where('t3.deleted')->eq('0')
->andWhere('t3.type')->eq('project')
->andWhere("t3.vision NOT LIKE '%or%'")
->andWhere("t3.vision NOT LIKE '%lite%'")
->groupBy('t3.id')
->query();
}
public $fieldList = array('t3.id as project', 't1.consumed');
public $result = array();
public function calculate($row)
{
$project = $row->project;
$consumed = $row->consumed;
if(!isset($this->result[$project])) $this->result[$project] = $consumed;
if(!isset($this->result[$project])) $this->result[$project] = 0;
$this->result[$project] += $consumed;
}
public function getResult($options = array())
@@ -20,40 +20,29 @@
*/
class day_of_invested_in_project extends baseCalc
{
public $dataset = 'getProjectEfforts';
public $fieldList = array('t3.id as project', 't1.consumed');
public $result = array();
public function getStatement()
{
$defaultHours = $this->dao->select('value')
->from(TABLE_CONFIG)
->where('module')->eq('execution')
->andWhere('key')->eq('defaultWorkhours')
->fetch('value');
if(empty($defaultHours)) $defaultHours = 7;
return $this->dao->select("t3.id as project, SUM(t1.consumed) as consumed, $defaultHours as defaultHours")
->from(TABLE_EFFORT)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.execution=t2.id')
->leftJoin(TABLE_PROJECT)->alias('t3')->on('t2.project=t3.id')
->where('t3.deleted')->eq('0')
->andWhere('t3.type')->eq('project')
->andWhere("t3.vision NOT LIKE '%or%'")
->andWhere("t3.vision NOT LIKE '%lite%'")
->groupBy('t3.id')
->query();
}
public function calculate($row)
{
$project = $row->project;
$consumed = $row->consumed;
$defaultHours = $row->defaultHours;
if(!isset($this->result[$project])) $this->result[$project] = $defaultHours ? round($consumed / $defaultHours, 2) : 0;
if(!isset($this->result[$project])) $this->result[$project] = 0;
$this->result[$project] += $defaultHours ? $consumed / $defaultHours : 0;
}
public function getResult($options = array())
{
foreach($this->result as $project => $days)
{
$this->result[$project] = round($days, 2);
}
$records = $this->getRecords(array('project', 'value'));
return $this->filterByOptions($records, $options);
}
@@ -20,33 +20,12 @@
*/
class ev_of_finished_task_in_waterfall extends baseCalc
{
public $dataset = 'getWaterfallTasks';
public $fieldList = array('t1.id as project', 't2.estimate', 't2.consumed', 't2.`left`');
public $result = array();
public function getStatement()
{
$ev = $this->dao->select('project, SUM(estimate) as estimate, SUM(consumed) as consumed, SUM(`left`) as `left`')
->from(TABLE_TASK)
->where('deleted')->eq('0')
->andWhere('parent')->ne('-1')
->andWhere("vision NOT LIKE '%or%'")
->andWhere("vision NOT LIKE '%lite%'")
->andWhere('status', true)->in('done,closed')
->orWhere('closedReason')->eq('done')
->markRight(1)
->groupBy('project')
->get();
return $this->dao->select('t1.id as project, t2.estimate, t2.consumed, t2.`left`')
->from(TABLE_PROJECT)->alias('t1')
->leftJoin("($ev)")->alias('t2')->on('t1.id=t2.project')
->where('t1.deleted')->eq('0')
->andWhere('t1.type')->eq('project')
->andWhere('t1.model')->in('waterfall,waterfallplus')
->andWhere("t1.vision NOT LIKE '%or%'")
->andWhere("t1.vision NOT LIKE '%lite%'")
->query();
}
public function calculate($row)
{
$project = $row->project;
@@ -20,37 +20,16 @@
*/
class pv_of_task_in_waterfall extends baseCalc
{
public $dataset = 'getWaterfallTasks';
public $fieldList = array('t1.id as project', 't2.estimate');
public $result = array();
public function getStatement()
{
$pv = $this->dao->select('project, SUM(estimate) as estimate')
->from(TABLE_TASK)
->where('deleted')->eq('0')
->andWhere('parent')->ne('-1')
->andWhere("vision NOT LIKE '%or%'")
->andWhere("vision NOT LIKE '%lite%'")
->andWhere('status', true)->in('done,closed')
->orWhere('closedReason')->eq('done')
->markRight(1)
->groupBy('project')
->get();
return $this->dao->select('t1.id as project, t2.estimate as pv')
->from(TABLE_PROJECT)->alias('t1')
->leftJoin("($pv)")->alias('t2')->on('t1.id=t2.project')
->where('t1.deleted')->eq('0')
->andWhere('t1.type')->eq('project')
->andWhere('t1.model')->in('waterfall,waterfallplus')
->andWhere("t1.vision NOT LIKE '%or%'")
->andWhere("t1.vision NOT LIKE '%lite%'")
->query();
}
public function calculate($row)
{
$project = $row->project;
$pv = $row->pv;
$pv = $row->estimate;
if(!isset($this->result[$project])) $this->result[$project] = $pv;
}
@@ -20,41 +20,12 @@
*/
class cv_in_waterfall extends baseCalc
{
public $dataset = 'getWaterfallTasks';
public $fieldList = array('t1.id as project', 't2.estimate', 't2.consumed', 't2.`left`', 't3.consumed as ac');
public $result = array();
public function getStatement()
{
$ev = $this->dao->select('project, SUM(estimate) as estimate, SUM(consumed) as consumed, SUM(`left`) as `left`')
->from(TABLE_TASK)
->where('deleted')->eq('0')
->andWhere('parent')->ne('-1')
->andWhere("vision NOT LIKE '%or%'")
->andWhere("vision NOT LIKE '%lite%'")
->andWhere('status', true)->in('done,closed')
->orWhere('closedReason')->eq('done')
->markRight(1)
->groupBy('project')
->get();
$ac = $this->dao->select('t3.id as project, SUM(t1.consumed) as consumed')
->from(TABLE_EFFORT)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.execution=t2.id')
->leftJoin(TABLE_PROJECT)->alias('t3')->on('t2.project=t3.id')
->where("t3.vision NOT LIKE '%or%'")
->andWhere("t3.vision NOT LIKE '%lite%'")
->groupBy('t3.id')
->get();
return $this->dao->select('t1.id as project, t2.estimate, t2.consumed, t2.`left`, t3.consumed as ac')
->from(TABLE_PROJECT)->alias('t1')
->leftJoin("($ev)")->alias('t2')->on('t1.id=t2.project')
->leftJoin("($ac)")->alias('t3')->on('t1.id=t3.project')
->where('t1.deleted')->eq('0')
->andWhere('t1.type')->eq('project')
->andWhere('t1.model')->in('waterfall,waterfallplus')
->query();
}
public function calculate($row)
{
$project = $row->project;
@@ -20,33 +20,12 @@
*/
class sv_in_waterfall extends baseCalc
{
public $dataset = 'getWaterfallTasks';
public $fieldList = array('t1.id as project', 't2.estimate', 't2.consumed', 't2.`left`');
public $result = array();
public function getStatement()
{
$task = $this->dao->select('project, SUM(estimate) as estimate, SUM(consumed) as consumed, SUM(`left`) as `left`')
->from(TABLE_TASK)
->where('deleted')->eq('0')
->andWhere('parent')->ne('-1')
->andWhere("vision NOT LIKE '%or%'")
->andWhere("vision NOT LIKE '%lite%'")
->andWhere('status', true)->in('done,closed')
->orWhere('closedReason')->eq('done')
->markRight(1)
->groupBy('project')
->get();
return $this->dao->select('t1.id as project, t2.estimate, t2.consumed, t2.`left`')
->from(TABLE_PROJECT)->alias('t1')
->leftJoin("($task)")->alias('t2')->on('t1.id=t2.project')
->where('t1.deleted')->eq('0')
->andWhere('t1.type')->eq('project')
->andWhere('t1.model')->in('waterfall,waterfallplus')
->andWhere("t1.vision NOT LIKE '%or%'")
->andWhere("t1.vision NOT LIKE '%lite%'")
->query();
}
public function calculate($row)
{
$project = $row->project;
@@ -20,32 +20,28 @@
*/
class count_of_user_in_project extends baseCalc
{
public $result = array();
public $dataset = 'getTeamMembers';
public function getStatement()
{
return $this->dao->select('t3.id as project, COUNT(DISTINCT account) as value')
->from(TABLE_TEAM)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t2.id=t1.root')
->leftJoin(TABLE_PROJECT)->alias('t3')->on('t3.id=t2.project')
->where('t1.type')->eq('execution')
->andWhere('t2.deleted')->eq(0)
->andWhere('t3.deleted')->eq(0)
->andWhere("t3.vision NOT LIKE '%or%'")
->andWhere("t3.vision NOT LIKE '%lite%'")
->groupBy('t3.id')
->query();
}
public $fieldList = array('t3.id as project', 't1.account');
public $result = array();
public function calculate($row)
{
$project = $row->project;
$value = $row->value;
$this->result[$project] = $value;
$account = $row->account;
if(!isset($this->result[$project])) $this->result[$project] = array();
$this->result[$project][$account] = $account;
}
public function getResult($options = array())
{
foreach($this->result as $project => $users)
{
if(!is_array($users)) continue;
$this->result[$project] = count($users);
}
$records = $this->getRecords(array('project', 'value'));
return $this->filterByOptions($records, $options);
}
@@ -20,41 +20,20 @@
*/
class consume_of_annual_closed_project extends baseCalc
{
public $dataset = null;
public $dataset = 'getProjectTasks';
public $fieldList = array();
public $fieldList = array('t1.closedDate', 't2.consumed', 't1.id as project', 't1.status');
public $result = array();
public function getStatement()
{
$task = $this->dao->select('SUM(consumed) as consumed, project')
->from(TABLE_TASK)
->where('deleted')->eq('0')
->andWhere('parent')->ne('-1')
->andWhere("vision NOT LIKE '%or%'")
->andWhere("vision NOT LIKE '%lite%'")
->groupBy('project')
->get();
return $this->dao->select('t1.id as project, t1.closedDate, t2.consumed')
->from(TABLE_PROJECT)->alias('t1')
->leftJoin("($task)")->alias('t2')->on('t1.id = t2.project')
->where('t1.type')->eq('project')
->andWhere('t1.status')->eq('closed')
->andWhere('t1.deleted')->eq('0')
->andWhere('t1.closedDate')->notZeroDatetime()
->andWhere("t1.vision NOT LIKE '%or%'")
->andWhere("t1.vision NOT LIKE '%lite%'")
->query();
}
public function calculate($data)
{
$project = $data->project;
$year = substr($data->closedDate, 0, 4);
$consumed = $data->consumed;
$status = $data->status;
if($status != 'closed') return false;
if(empty($year) || $year == '0000') return false;
if(!is_numeric($consumed) || empty($consumed)) return false;
@@ -20,41 +20,20 @@
*/
class consume_of_monthly_closed_project extends baseCalc
{
public $dataset = null;
public $dataset = 'getProjectTasks';
public $fieldList = array();
public $fieldList = array('t1.closedDate', 't2.consumed', 't1.id as project', 't1.status');
public $result = array();
public function getStatement()
{
$task = $this->dao->select('SUM(consumed) as consumed, project')
->from(TABLE_TASK)
->where('deleted')->eq('0')
->andWhere('parent')->ne('-1')
->andWhere("vision NOT LIKE '%or%'")
->andWhere("vision NOT LIKE '%lite%'")
->groupBy('project')
->get();
return $this->dao->select('t1.id as project, t1.closedDate, t2.consumed')
->from(TABLE_PROJECT)->alias('t1')
->leftJoin("($task)")->alias('t2')->on('t1.id = t2.project')
->where('t1.type')->eq('project')
->andWhere('t1.status')->eq('closed')
->andWhere('t1.deleted')->eq('0')
->andWhere('t1.closedDate IS NOT NULL')
->andWhere("t1.vision NOT LIKE '%or%'")
->andWhere("t1.vision NOT LIKE '%lite%'")
->query();
}
public function calculate($data)
{
$project = $data->project;
$year = substr($data->closedDate, 0, 4);
$consumed = $data->consumed;
$status = $data->status;
if($status != 'closed') return false;
if(empty($year) || $year == '0000') return false;
$month = substr($data->closedDate, 5, 2);
@@ -20,62 +20,39 @@
*/
class day_of_annual_closed_project extends baseCalc
{
public $dataset = null;
public $dataset = 'getProjectTasks';
public $fieldList = array();
public $fieldList = array('t1.closedDate', 't2.consumed', 't1.id as project', 't1.status');
public $result = array();
public function getStatement()
{
$task = $this->dao->select('SUM(consumed) as consumed, project')
->from(TABLE_TASK)
->where('deleted')->eq('0')
->andWhere('parent')->ne('-1')
->andWhere("vision NOT LIKE '%or%'")
->andWhere("vision NOT LIKE '%lite%'")
->groupBy('project')
->get();
return $this->dao->select('t1.id as project, t1.closedDate, t2.consumed')
->from(TABLE_PROJECT)->alias('t1')
->leftJoin("($task)")->alias('t2')->on('t1.id = t2.project')
->where('t1.type')->eq('project')
->andWhere('t1.status')->eq('closed')
->andWhere('t1.deleted')->eq('0')
->andWhere('t1.closedDate')->notZeroDatetime()
->andWhere("t1.vision NOT LIKE '%or%'")
->andWhere("t1.vision NOT LIKE '%lite%'")
->query();
}
public function calculate($data)
{
$project = $data->project;
$year = substr($data->closedDate, 0, 4);
$consumed = $data->consumed;
$status = $data->status;
$defaultHours = $data->defaultHours;
if($status != 'closed') return false;
if(empty($year) || $year == '0000') return false;
if(!is_numeric($consumed) || empty($consumed)) return false;
if(!isset($this->result[$year])) $this->result[$year] = array();
if(!isset($this->result[$year][$project])) $this->result[$year][$project] = 0;
$this->result[$year][$project] = round($consumed, 2);
$this->result[$year][$project] += $defaultHours ? $consumed / $defaultHours : 0;
}
public function getResult($options = array())
{
$defaultWorkhours = $this->dao->select('value')->from(TABLE_CONFIG)->where('`key`')->eq('defaultWorkhours')->fetch();
$records = array();
foreach($this->result as $year => $projects)
{
foreach($projects as $project => $value)
foreach($projects as $project => $days)
{
$value = $defaultWorkhours ? round($value / $defaultWorkhours->value, 4) : 0;
$records[] = array('project' => $project, 'year' => $year, 'value' => $value);
$this->result[$year][$project] = round($days, 4);
}
}
$records = getRecords(array('year', 'project', 'value'));
return $this->filterByOptions($records, $options);
}
}
@@ -20,27 +20,19 @@
*/
class day_of_annual_effort extends baseCalc
{
public $dataset = 'getEfforts';
public $fieldList = array('t1.date', 't1.consumed');
public $result = array();
public function getStatement()
{
$defaultHours = $this->dao->select('value')
->from(TABLE_CONFIG)
->where('module')->eq('execution')
->andWhere('key')->eq('defaultWorkhours')
->fetch('value');
if(empty($defaultHours)) $defaultHours = 7;
return $this->dao->select("`date`, `consumed`, $defaultHours as defaultHours")
->from(TABLE_EFFORT)
->where('deleted')->eq('0')
->andWhere('date')->notZeroDate()
->query();
}
public function calculate($row)
{
$year = substr($row->date, 0, 4);
if(empty($row->date)) return false;
$year = substr($row->date, 0, 4);
if($year == '0000') return false;
$consumed = $row->consumed;
$defaultHours = $row->defaultHours;
@@ -20,28 +20,20 @@
*/
class day_of_daily_effort extends baseCalc
{
public $dataset = 'getEfforts';
public $fieldList = array('t1.date', 't1.consumed');
public $result = array();
public function getStatement()
{
$defaultHours = $this->dao->select('value')
->from(TABLE_CONFIG)
->where('module')->eq('execution')
->andWhere('key')->eq('defaultWorkhours')
->fetch('value');
if(empty($defaultHours)) $defaultHours = 7;
return $this->dao->select("`date`, `consumed`, $defaultHours as defaultHours")
->from(TABLE_EFFORT)
->where('deleted')->eq('0')
->andWhere('date')->notZeroDate()
->query();
}
public function calculate($row)
{
$date = $row->date;
$year = substr($date, 0, 4);
$date = $row->date;
if(empty($date)) return false;
$year = substr($date, 0, 4);
if($year == '0000') return false;
$month = substr($date, 5, 2);
$day = substr($date, 8, 2);
$consumed = $row->consumed;
@@ -20,21 +20,20 @@
*/
class hour_of_annual_effort extends baseCalc
{
public $result = array();
public $dataset = 'getEfforts';
public function getStatement()
{
return $this->dao->select("`date`, `consumed`")
->from(TABLE_EFFORT)
->where('deleted')->eq('0')
->andWhere('date')->notZeroDate()
->query();
}
public $fieldList = array('t1.date', 't1.consumed');
public $result = array();
public function calculate($row)
{
$year = substr($row->date, 0, 4);
$consumed = $row->consumed;
if(empty($row->date)) return false;
$year = substr($row->date, 0, 4);
if($year == '0000') return false;
$consumed = $row->consumed;
if(!isset($this->result[$year])) $this->result[$year] = 0;
$this->result[$year] += $consumed;
@@ -20,21 +20,22 @@
*/
class hour_of_daily_effort extends baseCalc
{
public $result = array();
public $dataset = 'getEfforts';
public function getStatement()
{
return $this->dao->select("`date`, `consumed`")
->from(TABLE_EFFORT)
->where('deleted')->eq('0')
->andWhere('date')->notZeroDate()
->query();
}
public $fieldList = array('t1.date', 't1.consumed');
public $result = array();
public function calculate($row)
{
$date = $row->date;
$year = substr($date, 0, 4);
$date = $row->date;
if(empty($date)) return false;
$year = substr($date, 0, 4);
if($year == '0000') return false;
$month = substr($date, 5, 2);
$day = substr($date, 8, 2);
$consumed = $row->consumed;
@@ -20,21 +20,11 @@
*/
class count_of_daily_run_case extends baseCalc
{
public $result = array();
public $dataset = 'getTestResults';
public function getStatement()
{
return $this->dao->select('t1.`date` as `date`, t1.id')
->from(TABLE_TESTRESULT)->alias('t1')
->leftJoin(TABLE_CASE)->alias('t2')->on('t1.`case`=t2.id')
->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t2.product=t3.id')
->where('t2.deleted')->eq('0')
->andWhere('t3.deleted')->eq('0')
->andWhere('t1.date')->notZeroDatetime()
->andWhere("t3.vision NOT LIKE '%or%'")
->andWhere("t3.vision NOT LIKE '%lite%'")
->query();
}
public $fieldList = array('t1.id', 't1.`date`');
public $result = array();
public function calculate($row)
{
@@ -20,24 +20,18 @@
*/
class count_of_invalid_story extends baseCalc
{
public $result = 0;
public $dataset = 'getAllDevStories';
public function getStatement()
{
return $this->dao->select('count(t1.id) as value')->from(TABLE_STORY)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product=t2.id')
->where('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->andWhere('t1.type')->eq('story')
->andWhere('t1.closedReason')->in('duplicate,willnotdo,bydesign')
->andWhere("t1.vision NOT LIKE '%or%'")
->andWhere("t1.vision NOT LIKE '%lite%'")
->query();
}
public $fieldList = array('t1.id', 't1.closedReason');
public $result = 0;
public function calculate($data)
{
$this->result = $data->value;
$closedReason = $data->closedReason;
if(!in_array($closedReason, array('duplicate', 'willnotdo', 'bydesign'))) return false;
$this->result += 1;
}
public function getResult($options = array())
@@ -20,24 +20,19 @@
*/
class count_of_valid_story extends baseCalc
{
public $result = 0;
public $dataset = 'getAllDevStories';
public function getStatement()
{
return $this->dao->select('count(t1.id) as value')->from(TABLE_STORY)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product=t2.id')
->where('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->andWhere('t1.type')->eq('story')
->andWhere('t1.closedReason')->notin('duplicate,willnotdo,bydesign,cancel')
->andWhere("t1.vision NOT LIKE '%or%'")
->andWhere("t1.vision NOT LIKE '%lite%'")
->query();
}
public $fieldList = array('t1.id', 't1.closedReason');
public $result = 0;
public function calculate($row)
{
$this->result = $row->value;
$closedReason = $row->closedReason;
if(in_array($closedReason, array('duplicate', 'willnotdo', 'bydesign', 'cancel'))) return false;
$this->result += 1;
}
public function getResult($options = array())
@@ -20,23 +20,17 @@
*/
class count_of_assigned_case_in_user extends baseCalc
{
public $result = array();
public $dataset = 'getTestRuns';
public function getStatement()
{
return $this->dao->select('t1.assignedTo')->from(TABLE_TESTRUN)->alias('t1')
->leftJoin(TABLE_CASE)->alias('t2')->on('t1.`case` = t2.id')
->leftJoin(TABLE_TESTTASK)->alias('t3')->on('t1.task = t3.id')
->where('t3.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->andWhere('t3.status')->ne('done')
->query();
}
public $fieldList = array('t1.assignedTo', 't3.status');
public $result = array();
public function calculate($row)
{
$assignedTo = $row->assignedTo;
if($row->status == 'done') return false;
if(empty($assignedTo) || $assignedTo == 'closed') return false;
if(!isset($this->result[$assignedTo])) $this->result[$assignedTo] = 0;
@@ -20,31 +20,23 @@
*/
class count_of_reviewing_story_in_user extends baseCalc
{
public $result = array();
public $dataset = 'getDevStoriesWithReview';
public function getStatement()
{
return $this->dao->select('t3.reviewer, t3.story, t3.version')
->from(TABLE_STORY)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product=t2.id')
->leftJoin(TABLE_STORYREVIEW)->alias('t3')->on('t1.id=t3.story and t1.version=t3.version')
->where('t1.deleted')->eq('0')
->andWhere('t2.deleted')->eq('0')
->andWhere('t1.type')->eq('story')
->andWhere('t1.status')->in('reviewing,changing')
->andWhere('t3.result')->eq('')
->andWhere("t2.vision NOT LIKE '%or%'")
->andWhere("t2.vision NOT LIKE '%lite%'")
->query();
}
public $fieldList = array('t1.reviewer', 't1.story', 't1.version', 't2.status', 't1.result');
public $result = array();
public function calculate($row)
{
$reviewer = $row->reviewer;
$story = $row->story;
$version = $row->version;
$status = $row->status;
$result = $row->result;
if(empty($reviewer)) return false;
if($status != 'reviewing' and $status != 'changing') return false;
if(!empty($result)) return false;
if(!isset($this->result[$story]))
{
+230 -4
View File
@@ -172,6 +172,8 @@ class dataset
->where('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->andWhere('t2.shadow')->eq(0)
->andWhere("t2.vision NOT LIKE '%or%'")
->andWhere("t2.vision NOT LIKE '%lite%'")
->query();
}
@@ -352,7 +354,6 @@ class dataset
->where('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->andWhere('t1.type')->eq('story')
->andWhere('t2.shadow')->eq(0)
->andWhere('t4.deleted')->eq(0)
->andWhere('t4.type')->eq('project')
->andWhere("t1.vision NOT LIKE '%or%'")
@@ -370,9 +371,15 @@ class dataset
*/
public function getDevStories($fieldList)
{
$caseQuery = $this->dao->select('story, count(DISTINCT id) as case_count')
->from(TABLE_CASE)
->groupBy('story')
->get();
return $this->dao->select($fieldList)
->from(TABLE_STORY)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product=t2.id')
->leftJoin("($caseQuery)")->alias('t3')->on('t1.id=t3.story')
->where('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->andWhere('t1.type')->eq('story')
@@ -466,6 +473,28 @@ class dataset
->query();
}
/**
* 获取关联用例的研发需求数据。
* Get story list with case.
*
* @param string $fieldList
* @access public
* @return PDOStatement
*/
public function getCasesWithStory($fieldList)
{
return $this->dao->select($fieldList)
->from(TABLE_CASE)->alias('t0')
->leftJoin(TABLE_PROJECTSTORY)->alias('t1')->on('t1.story=t0.story')
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story=t2.id')
->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t1.product=t3.id')
->where('t2.deleted')->eq('0')
->andWhere('t3.deleted')->eq('0')
->andWhere("t2.vision NOT LIKE '%or%'")
->andWhere("t2.vision NOT LIKE '%lite%'")
->query();
}
/**
* 获取产品数据。
* Get product list.
@@ -693,10 +722,10 @@ class dataset
}
/**
* 统计mr信息。
* Get merge request data.
* 统计合并请求信息。
* Get merge requests.
*
* @param string $fieldList
* @param string $fieldList
* @access public
* @return PDOStatement
*/
@@ -708,4 +737,201 @@ class dataset
->andWhere('t2.deleted')->eq('0')
->query();
}
/**
* 统计团队成员信息。
* Get team members.
*
* @param string $fieldList
* @access public
* @return PDOStatement
*/
public function getTeamMembers($fieldList)
{
return $this->dao->select($fieldList)
->from(TABLE_TEAM)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t2.id=t1.root')
->leftJoin(TABLE_PROJECT)->alias('t3')->on('t3.id=t2.project')
->where('t1.type')->eq('execution')
->andWhere('t2.deleted')->eq(0)
->andWhere('t3.deleted')->eq(0)
->andWhere("t3.vision NOT LIKE '%or%'")
->andWhere("t3.vision NOT LIKE '%lite%'")
->query();
}
/**
* 统计日志信息。
* Get effort.
*
* @param string $fieldList
* @access public
* @return PDOStatement
*/
public function getEfforts($fieldList)
{
$defaultHours = $this->dao->select('value')
->from(TABLE_CONFIG)
->where('module')->eq('execution')
->andWhere('key')->eq('defaultWorkhours')
->fetch('value');
if(empty($defaultHours)) $defaultHours = 7;
return $this->dao->select("$fieldList, $defaultHours as defaultHours")
->from(TABLE_EFFORT)->alias('t1')
->where('t1.deleted')->eq('0')
->query();
}
/**
* 统计项目日志信息。
* Get project effort.
*
* @param string $fieldList
* @access public
* @return PDOStatement
*/
public function getProjectEfforts($fieldList)
{
$defaultHours = $this->dao->select('value')
->from(TABLE_CONFIG)
->where('module')->eq('execution')
->andWhere('key')->eq('defaultWorkhours')
->fetch('value');
if(empty($defaultHours)) $defaultHours = 7;
return $this->dao->select("$fieldList, $defaultHours as defaultHours")
->from(TABLE_EFFORT)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.execution=t2.id')
->leftJoin(TABLE_PROJECT)->alias('t3')->on('t2.project=t3.id')
->where('t3.deleted')->eq('0')
->andWhere('t3.type')->eq('project')
->andWhere("t3.vision NOT LIKE '%or%'")
->andWhere("t3.vision NOT LIKE '%lite%'")
->query();
}
/**
* 统计瀑布项目任务信息。
* Get waterfall tasks.
*
* @param string $fieldList
* @access public
* @return PDOStatement
*/
public function getWaterfallTasks($fieldList)
{
$task = $this->dao->select('project, SUM(estimate) as estimate, SUM(consumed) as consumed, SUM(`left`) as `left`')
->from(TABLE_TASK)
->where('deleted')->eq('0')
->andWhere('parent')->ne('-1')
->andWhere("vision NOT LIKE '%or%'")
->andWhere("vision NOT LIKE '%lite%'")
->andWhere('status', true)->in('done,closed')
->orWhere('closedReason')->eq('done')
->markRight(1)
->groupBy('project')
->get();
$effort = $this->dao->select('t3.id as project, SUM(t1.consumed) as consumed')
->from(TABLE_EFFORT)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.execution=t2.id')
->leftJoin(TABLE_PROJECT)->alias('t3')->on('t2.project=t3.id')
->where("t3.vision NOT LIKE '%or%'")
->andWhere("t3.vision NOT LIKE '%lite%'")
->groupBy('t3.id')
->get();
return $this->dao->select($fieldList)
->from(TABLE_PROJECT)->alias('t1')
->leftJoin("($task)")->alias('t2')->on('t1.id=t2.project')
->leftJoin("($effort)")->alias('t3')->on('t1.id=t3.project')
->where('t1.deleted')->eq('0')
->andWhere('t1.type')->eq('project')
->andWhere('t1.model')->in('waterfall,waterfallplus')
->andWhere("t1.vision NOT LIKE '%or%'")
->andWhere("t1.vision NOT LIKE '%lite%'")
->query();
}
/**
* 统计测试用例结果信息。
* Get test results.
*
* @param string $fieldList
* @access public
* @return PDOStatement
*/
public function getTestresults($fieldList)
{
return $this->dao->select($fieldList)
->from(TABLE_TESTRESULT)->alias('t1')
->leftJoin(TABLE_CASE)->alias('t2')->on('t1.`case`=t2.id')
->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t2.product=t3.id')
->where('t2.deleted')->eq('0')
->andWhere('t3.deleted')->eq('0')
->andWhere("t3.vision NOT LIKE '%or%'")
->andWhere("t3.vision NOT LIKE '%lite%'")
->query();
}
/**
* 统计研发需求评审信息。
*
* @param string $fieldList
* @access public
* @return PDOStatement
*/
public function getDevStoriesWithReview($fieldList)
{
return $this->dao->select($fieldList)
->from(TABLE_STORYREVIEW)->alias('t1')
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story=t2.id')
->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t2.product=t3.id')
->where('t2.deleted')->eq(0)
->andWhere('t3.deleted')->eq(0)
->andWhere('t2.type')->eq('story')
->andWhere("t3.vision NOT LIKE '%or%'")
->andWhere("t3.vision NOT LIKE '%lite%'")
->query();
}
public function getProjectTasks($fieldList)
{
$defaultHours = $this->dao->select('value')
->from(TABLE_CONFIG)
->where('module')->eq('execution')
->andWhere('key')->eq('defaultWorkhours')
->fetch('value');
if(empty($defaultHours)) $defaultHours = 7;
$task = $this->dao->select('SUM(consumed) as consumed, project')
->from(TABLE_TASK)
->where('deleted')->eq('0')
->andWhere('parent')->ne('-1')
->andWhere("vision NOT LIKE '%or%'")
->andWhere("vision NOT LIKE '%lite%'")
->groupBy('project')
->get();
return $this->dao->select("$fieldList, $defaultHours as defaultHours")
->from(TABLE_PROJECT)->alias('t1')
->leftJoin("($task)")->alias('t2')->on('t1.id = t2.project')
->where('t1.type')->eq('project')
->andWhere('t1.deleted')->eq('0')
->andWhere("t1.vision NOT LIKE '%or%'")
->andWhere("t1.vision NOT LIKE '%lite%'")
->query();
}
public function getTestRuns($fieldList)
{
return $this->dao->select($fieldList)
->from(TABLE_TESTRUN)->alias('t1')
->leftJoin(TABLE_CASE)->alias('t2')->on('t1.`case` = t2.id')
->leftJoin(TABLE_TESTTASK)->alias('t3')->on('t1.task = t3.id')
->where('t3.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->query();
}
}
@@ -8,8 +8,8 @@ timeout=0
cid=1
- 测试分组数 @5
- 测试产品1已开发的需求数第0条的value属性 @1
- 测试产品3已开发的需求数第0条的value属性 @1
- 测试产品1已开发的需求数第0条的value属性 @80
- 测试产品3已开发的需求数第0条的value属性 @80
- 测试已删除产品4已开发的需求数第0条的value属性 @0
- 测试不存在的产品下的需求数 @0
@@ -24,7 +24,7 @@ $metric = new metricTest();
$calc = $metric->calcMetric(__FILE__);
r(count($calc->getResult())) && p('') && e('5'); // 测试分组数
r($calc->getResult(array('product' => '1'))) && p('0:value') && e('1'); // 测试产品1已开发的需求数
r($calc->getResult(array('product' => '3'))) && p('0:value') && e('1'); // 测试产品3已开发的需求数
r($calc->getResult(array('product' => '1'))) && p('0:value') && e('80'); // 测试产品1已开发的需求数
r($calc->getResult(array('product' => '3'))) && p('0:value') && e('80'); // 测试产品3已开发的需求数
r($calc->getResult(array('product' => '4'))) && p('0:value') && e('0'); // 测试已删除产品4已开发的需求数
r($calc->getResult(array('product' => '9999'))) && p('') && e('0'); // 测试不存在的产品下的需求数
@@ -14,6 +14,7 @@ include dirname(__FILE__, 7) . '/test/lib/init.php';
include dirname(__FILE__, 4) . '/calc.class.php';
zdTable('product')->config('product', true, 4)->gen(10);
zdTable('project')->config('project', true, 4)->gen(10);
zdTable('story')->config('story_status_closedreason', true, 4)->gen(1000);
zdTable('projectstory')->config('projectstory', true, 4)->gen(1000);
@@ -8,7 +8,7 @@ timeout=0
cid=1
- 测试分组数。 @4
- 测试用户dev。第0条的value属性 @18
- 测试用户dev。第0条的value属性 @39
*/
include dirname(__FILE__, 7) . '/test/lib/init.php';
@@ -22,4 +22,4 @@ $calc = $metric->calcMetric(__FILE__);
r(count($calc->getResult())) && p('') && e('4'); // 测试分组数。
r($calc->getResult(array('user' => 'dev'))) && p('0:value') && e('18'); // 测试用户dev。
r($calc->getResult(array('user' => 'dev'))) && p('0:value') && e('39'); // 测试用户dev。
@@ -14,16 +14,16 @@ cid=1
- 第count_of_unclosed_story_in_project条的dataset属性 @getDevStoriesWithProject
- 第count_of_unclosed_story_in_project条的id属性 @205
- 测试count_of_user_in_project的数据源和编号
- 第count_of_user_in_project条的dataset属性 @~~
- 第count_of_user_in_project条的dataset属性 @getTeamMembers
- 第count_of_user_in_project条的id属性 @228
- 测试count_of_valid_story_in_project的数据源和编号
- 第count_of_valid_story_in_project条的dataset属性 @getDevStoriesWithProject
- 第count_of_valid_story_in_project条的id属性 @208
- 测试consume_of_all_in_project的数据源和编号
- 第consume_of_all_in_project条的dataset属性 @~~
- 第consume_of_all_in_project条的dataset属性 @getProjectEfforts
- 第consume_of_all_in_project条的id属性 @229
- 测试ac_of_all_in_waterfall的数据源和编号
- 第ac_of_all_in_waterfall条的dataset属性 @~~
- 第ac_of_all_in_waterfall条的dataset属性 @getProjectEfforts
- 第ac_of_all_in_waterfall条的id属性 @231
- 测试count_of_pending_story_in_user的数据源和编号
- 第count_of_pending_story_in_user条的dataset属性 @getAllDevStories
@@ -39,8 +39,8 @@ $metric = new metricTest();
r($metric->getCalcInstanceList()) && p('count_of_task_in_project:dataset,id') && e('getTasks,213'); // 测试count_of_task_in_project的数据源和编号
r($metric->getCalcInstanceList()) && p('count_of_unclosed_story_in_project:dataset,id') && e('getDevStoriesWithProject,205'); // 测试count_of_unclosed_story_in_project的数据源和编号
r($metric->getCalcInstanceList()) && p('count_of_user_in_project:dataset,id') && e('~~,228'); // 测试count_of_user_in_project的数据源和编号
r($metric->getCalcInstanceList()) && p('count_of_user_in_project:dataset,id') && e('getTeamMembers,228'); // 测试count_of_user_in_project的数据源和编号
r($metric->getCalcInstanceList()) && p('count_of_valid_story_in_project:dataset,id') && e('getDevStoriesWithProject,208'); // 测试count_of_valid_story_in_project的数据源和编号
r($metric->getCalcInstanceList()) && p('consume_of_all_in_project:dataset,id') && e('~~,229'); // 测试consume_of_all_in_project的数据源和编号
r($metric->getCalcInstanceList()) && p('ac_of_all_in_waterfall:dataset,id') && e('~~,231'); // 测试ac_of_all_in_waterfall的数据源和编号
r($metric->getCalcInstanceList()) && p('consume_of_all_in_project:dataset,id') && e('getProjectEfforts,229'); // 测试consume_of_all_in_project的数据源和编号
r($metric->getCalcInstanceList()) && p('ac_of_all_in_waterfall:dataset,id') && e('getProjectEfforts,231'); // 测试ac_of_all_in_waterfall的数据源和编号
r($metric->getCalcInstanceList()) && p('count_of_pending_story_in_user:dataset,id') && e('getAllDevStories,251'); // 测试count_of_pending_story_in_user的数据源和编号