+add & * fix for task #411 #412

This commit is contained in:
wangyidong
2011-04-13 08:26:44 +00:00
parent f99d8b23ff
commit 161041e2de
8 changed files with 406 additions and 1 deletions
+1
View File
@@ -22,6 +22,7 @@
</div>
<div class='f-right'>
<?php echo html::export2csv($lang->exportCSV, $lang->setFileName);?>
<?php common::printLink('story', 'report', "productID=$productID&browseType=$browseType&moduleID=$moduleID", $lang->story->report->common); ?>
<?php if(common::hasPriv('story', 'create')) echo html::a($this->createLink('story', 'create', "productID=$productID&moduleID=$moduleID"), $lang->story->create); ?>
</div>
</div>
+40
View File
@@ -505,4 +505,44 @@ class story extends control
$this->loadModel('mail')->send($toList, $productName . ':' . 'STORY #' . $story->id . $this->lang->colon . $story->title, $mailContent, $ccList);
if($this->mail->isError()) echo js::error($this->mail->getError());
}
/**
* The report page.
*
* @param int $productID
* @param string $browseType
* @param int $moduleID
* @access public
* @return void
*/
public function report($productID, $browseType, $moduleID)
{
$this->loadModel('report');
$this->view->charts = array();
$this->view->renderJS = '';
if(!empty($_POST))
{
foreach($this->post->charts as $chart)
{
$chartFunc = 'getDataOf' . $chart;
$chartData = $this->story->$chartFunc();
$chartOption = $this->lang->story->report->$chart;
$this->story->mergeChartOption($chart);
$chartXML = $this->report->createSingleXML($chartData, $chartOption->graph);
$this->view->charts[$chart] = $this->report->createJSChart($chartOption->swf, $chartXML, $chartOption->width, $chartOption->height);
$this->view->datas[$chart] = $this->report->computePercent($chartData);
}
$this->view->renderJS = $this->report->renderJsCharts(count($this->view->charts));
}
$this->products = $this->product->getPairs();
$this->product->setMenu($this->products, $productID);
$this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->story->common;
$this->view->productID = $productID;
$this->view->browseType = $browseType;
$this->view->moduleID = $moduleID;
$this->view->checkedCharts = $this->post->charts ? join(',', $this->post->charts) : '';
$this->display();
}
}
+1
View File
@@ -0,0 +1 @@
.side span {display:block}
+20
View File
@@ -0,0 +1,20 @@
/* Select All. */
function checkAll()
{
var checkOBJ = $('input');
for(var i = 0; i < checkOBJ.length; i++)
{
checkOBJ.get(i).checked = true;
}
}
/* Check reverse. */
function checkReverse()
{
var checkOBJ = $('input');
for(var i = 0; i < checkOBJ.length; i++)
{
checkOBJ.get(i).checked = !checkOBJ.get(i).checked;
}
return;
}
+54 -1
View File
@@ -114,6 +114,7 @@ $lang->story->legendProjectAndTask = 'Project & task';
$lang->story->legendLinkStories = 'Related story';
$lang->story->legendChildStories = 'Child story';
$lang->story->legendSpec = 'Spec';
$lang->story->legendVerify = 'Verified standard';
$lang->story->legendHistory = 'History';
$lang->story->legendVersion = 'Versions';
$lang->story->legendMisc = 'Misc';
@@ -142,4 +143,56 @@ $lang->story->action->closed = array('main' => '$date, Closed by <s
$lang->story->action->linked2plan = array('main' => '$date, Linked to plan <strong>$extra</strong> by <strong>$actor</strong>.');
$lang->story->action->unlinkedfromplan = array('main' => '$date, Removed from <stong>$extra></strong> by <strong>$actor</strong>');
$lang->story->action->linked2project = array('main' => '$date, Linked to project <strong>$extra</strong> by <strong>$actor</strong>.');
$lang->story->action->unlinkedfromproject = array('main' => '$date, Removed from project <strontg>$extra</strong> by <strong>$actor</strong>.');
$lang->story->action->unlinkedfromproject = array('main' => '$date, Removed from project <strontg>$extra</strong> by <strong>$actor</strong>.');
/* Report*/
$lang->story->report->common = 'Report';
$lang->story->report->select = 'Select';
$lang->story->report->create = 'Creat';
$lang->story->report->selectAll = 'All';
$lang->story->report->selectReverse = 'Reverse';
$lang->story->report->charts['storysPerProduct'] = 'Product storys';
$lang->story->report->charts['storysPerModule'] = 'Module storys';
$lang->story->report->charts['storysPerPlan'] = 'Plan storys';
$lang->story->report->charts['storysPerStatus'] = 'Sotrys of status';
$lang->story->report->charts['storysPerStage'] = 'Storys of stage';
$lang->story->report->charts['storysPerPri'] = 'Storys of priority';
$lang->story->report->charts['storysPerEstimate'] = 'Storys of Estimate';
$lang->story->report->charts['storysPerOpenedBy'] = 'Opened by user';
$lang->story->report->charts['storysPerAssignedTo'] = 'Assigned to user';
$lang->story->report->charts['storysPerClosedReason'] = 'Storys for reason';
$lang->story->report->charts['storysPerChange'] = 'Storys of change';
$lang->story->report->options->swf = 'pie2d';
$lang->story->report->options->width = 'auto';
$lang->story->report->options->height = 300;
$lang->story->report->options->graph->baseFontSize = 12;
$lang->story->report->options->graph->showNames = 1;
$lang->story->report->options->graph->formatNumber = 1;
$lang->story->report->options->graph->decimalPrecision = 0;
$lang->story->report->options->graph->animation = 0;
$lang->story->report->options->graph->rotateNames = 0;
$lang->story->report->options->graph->yAxisName = 'COUNT';
$lang->story->report->options->graph->pieRadius = 100; // 饼图直径。
$lang->story->report->options->graph->showColumnShadow = 0; // 是否显示柱状图阴影。
$lang->story->report->storysPerProduct->graph->xAxisName = 'Product';
$lang->story->report->storysPerModule->graph->xAxisName = 'Module';
$lang->story->report->storysPerPlan->graph->xAxisName = 'Plan';
$lang->story->report->storysPerStatus->graph->xAxisName = 'Status';
$lang->story->report->storysPerStage->graph->xAxisName = 'Stage';
$lang->story->report->storysPerPri->graph->xAxisName = 'Priority';
$lang->story->report->storysPerOpenedBy->graph->xAxisName = 'Opened by';
$lang->story->report->storysPerAssignedTo->graph->xAxisName = 'Assigned to';
$lang->story->report->storysPerClosedReason->graph->xAxisName = 'Closed reason';
$lang->story->report->storysPerEstimate->swf = 'column2d';
$lang->story->report->storysPerEstimate->height = 400;
$lang->story->report->storysPerEstimate->graph->xAxisName = 'Estimate';
$lang->story->report->storysPerEstimate->graph->rotateNames = 1;
$lang->story->report->storysPerChange->swf = 'column2d';
$lang->story->report->storysPerChange->height = 400;
$lang->story->report->storysPerChange->graph->xAxisName = 'Change';
$lang->story->report->storysPerChange->graph->rotateNames = 1;
+52
View File
@@ -144,3 +144,55 @@ $lang->story->action->linked2plan = array('main' => '$date, 由 <strong>
$lang->story->action->unlinkedfromplan = array('main' => '$date, 由 <strong>$actor</strong> 从计划 <strong>$extra</strong> 移除。');
$lang->story->action->linked2project = array('main' => '$date, 由 <strong>$actor</strong> 关联到项目 <strong>$extra</strong>。');
$lang->story->action->unlinkedfromproject = array('main' => '$date, 由 <strong>$actor</strong> 从项目 <strong>$extra</strong> 移除。');
/* 统计报表。*/
$lang->story->report->common = '统计报表';
$lang->story->report->select = '请选择报表类型';
$lang->story->report->create = '生成报表';
$lang->story->report->selectAll = '全选';
$lang->story->report->selectReverse = '反选';
$lang->story->report->charts['storysPerProduct'] = '产品需求数量';
$lang->story->report->charts['storysPerModule'] = '模块需求数量';
$lang->story->report->charts['storysPerPlan'] = '计划进行统计';
$lang->story->report->charts['storysPerStatus'] = '状态进行统计';
$lang->story->report->charts['storysPerStage'] = '所处阶段进行统计';
$lang->story->report->charts['storysPerPri'] = '优先级进行统计';
$lang->story->report->charts['storysPerEstimate'] = '预计工时进行统计';
$lang->story->report->charts['storysPerOpenedBy'] = '由谁创建来进行统计';
$lang->story->report->charts['storysPerAssignedTo'] = '当前指派来进行统计';
$lang->story->report->charts['storysPerClosedReason'] = '关闭原因来进行统计';
$lang->story->report->charts['storysPerChange'] = '变更次数来进行统计';
$lang->story->report->options->swf = 'pie2d';
$lang->story->report->options->width = 'auto';
$lang->story->report->options->height = 300;
$lang->story->report->options->graph->baseFontSize = 12;
$lang->story->report->options->graph->showNames = 1;
$lang->story->report->options->graph->formatNumber = 1;
$lang->story->report->options->graph->decimalPrecision = 0;
$lang->story->report->options->graph->animation = 0;
$lang->story->report->options->graph->rotateNames = 0;
$lang->story->report->options->graph->yAxisName = 'COUNT';
$lang->story->report->options->graph->pieRadius = 100; // 饼图直径。
$lang->story->report->options->graph->showColumnShadow = 0; // 是否显示柱状图阴影。
$lang->story->report->storysPerProduct->graph->xAxisName = '产品';
$lang->story->report->storysPerModule->graph->xAxisName = '模块';
$lang->story->report->storysPerPlan->graph->xAxisName = '产品计划';
$lang->story->report->storysPerStatus->graph->xAxisName = '状态';
$lang->story->report->storysPerStage->graph->xAxisName = '所处阶段';
$lang->story->report->storysPerPri->graph->xAxisName = '优先级';
$lang->story->report->storysPerOpenedBy->graph->xAxisName = '由谁创建';
$lang->story->report->storysPerAssignedTo->graph->xAxisName = '当前指派';
$lang->story->report->storysPerClosedReason->graph->xAxisName = '关闭原因';
$lang->story->report->storysPerEstimate->swf = 'column2d';
$lang->story->report->storysPerEstimate->height = 400;
$lang->story->report->storysPerEstimate->graph->xAxisName = '预计时间';
$lang->story->report->storysPerEstimate->graph->rotateNames = 1;
$lang->story->report->storysPerChange->swf = 'column2d';
$lang->story->report->storysPerChange->height = 400;
$lang->story->report->storysPerChange->graph->xAxisName = '变更次数';
$lang->story->report->storysPerChange->graph->rotateNames = 1;
+176
View File
@@ -705,4 +705,180 @@ class storyModel extends model
if(!empty($story->lastEditedBy)) $accounts[] = $story->lastEditedBy;
return array_unique($accounts);
}
/**
* Merge the default chart settings and the settings of current chart.
*
* @param string $chartType
* @access public
* @return void
*/
public function mergeChartOption($chartType)
{
$chartOption = $this->lang->story->report->$chartType;
$commonOption = $this->lang->story->report->options;
$chartOption->graph->caption = $this->lang->story->report->charts[$chartType];
if(!isset($chartOption->swf)) $chartOption->swf = $commonOption->swf;
if(!isset($chartOption->width)) $chartOption->width = $commonOption->width;
if(!isset($chartOption->height)) $chartOption->height = $commonOption->height;
/* 合并配置。*/
foreach($commonOption->graph as $key => $value) if(!isset($chartOption->graph->$key)) $chartOption->graph->$key = $value;
}
/**
* Get report data of storys per product
*
* @access public
* @return array
*/
public function getDataOfStorysPerProduct()
{
$datas = $this->dao->select('product as name, count(product) as value')->from(TABLE_STORY)->where('deleted')->eq(0)->groupBy('product')->orderBy('value DESC')->fetchAll('name');
if(!$datas) return array();
$products = $this->loadModel('product')->getPairs();
foreach($datas as $productID => $data) $data->name = isset($products[$productID]) ? $products[$productID] : $this->lang->report->undefined;
return $datas;
}
/**
* Get report data of storys per module
*
* @access public
* @return array
*/
public function getDataOfStorysPerModule()
{
$datas = $this->dao->select('module as name, count(module) as value')->from(TABLE_STORY)->where('deleted')->eq(0)->groupBy('module')->orderBy('value DESC')->fetchAll('name');
if(!$datas) return array();
$modules = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in(array_keys($datas))->fetchPairs();
foreach($datas as $moduleID => $data) $data->name = isset($modules[$moduleID]) ? $modules[$moduleID] : '/';
return $datas;
}
/**
* Get report data of storys per plan
*
* @access public
* @return array
*/
public function getDataOfStorysPerPlan()
{
$datas = $this->dao->select('plan as name, count(plan) as value')->from(TABLE_STORY)
->where('deleted')->eq(0)
->andWhere('plan')->ne(0)
->groupBy('plan')->orderBy('value DESC')->fetchAll('name');
if(!$datas) return array();
$plans = $this->dao->select('id, title')->from(TABLE_PRODUCTPLAN)->where('id')->in(array_keys($datas))->fetchPairs();
foreach($datas as $planID => $data) $data->name = isset($plans[$planID]) ? $plans[$planID] : $this->lang->report->undefined;
return $datas;
}
/**
* Get report data of storys per status
*
* @access public
* @return array
*/
public function getDataOfStorysPerStatus()
{
$datas = $this->dao->select('status as name, count(status) as value')->from(TABLE_STORY)->where('deleted')->eq(0)->groupBy('status')->orderBy('value DESC')->fetchAll('name');
if(!$datas) return array();
foreach($datas as $status => $data) if(isset($this->lang->story->statusList[$status])) $data->name = $this->lang->story->statusList[$status];
return $datas;
}
/**
* Get report data of storys per stage
*
* @access public
* @return array
*/
public function getDataOfStorysPerStage()
{
$datas = $this->dao->select('stage as name, count(stage) as value')->from(TABLE_STORY)
->where('deleted')->eq(0)
->andWhere('stage')->ne('')
->groupBy('stage')->orderBy('value DESC')->fetchAll('name');
if(!$datas) return array();
foreach($datas as $stage => $data) if(isset($this->lang->story->stageList[$stage])) $data->name = $this->lang->story->stageList[$stage];
return $datas;
}
/**
* Get report data of storys per pri
*
* @access public
* @return array
*/
public function getDataOfStorysPerPri()
{
$datas = $this->dao->select('pri as name, count(pri) as value')->from(TABLE_STORY)->where('deleted')->eq(0)->groupBy('pri')->orderBy('value DESC')->fetchAll('name');
if(!$datas) return array();
foreach($datas as $pri => $data) $data->name = $this->lang->story->priList[$pri] != '' ? $this->lang->story->priList[$pri] : $this->lang->report->undefined;
return $datas;
}
/**
* Get report data of storys per estimate
*
* @access public
* @return array
*/
public function getDataOfStorysPerEstimate()
{
return $this->dao->select('estimate as name, count(estimate) as value')->from(TABLE_STORY)->where('deleted')->eq(0)->groupBy('estimate')->orderBy('value')->fetchAll();
}
/**
* Get report data of storys per openedBy
*
* @access public
* @return array
*/
public function getDataOfStorysPerOpenedBy()
{
$datas = $this->dao->select('openedBy as name, count(openedBy) as value')->from(TABLE_STORY)->where('deleted')->eq(0)->groupBy('openedBy')->orderBy('value DESC')->fetchAll('name');
if(!$datas) return array();
if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter');
foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account];
return $datas;
}
/**
* Get report data of storys per assignedTo
*
* @access public
* @return array
*/
public function getDataOfStorysPerAssignedTo()
{
$datas = $this->dao->select('assignedTo as name, count(assignedTo) as value')->from(TABLE_STORY)
->where('deleted')->eq(0)
->andWhere('assignedTo')->ne('')
->groupBy('assignedTo')->orderBy('value DESC')->fetchAll('name');
if(!$datas) return array();
if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter');
foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account];
return $datas;
}
/**
* Get report data of storys per closedReason
*
* @access public
* @return array
*/
public function getDataOfStorysPerClosedReason()
{
$datas = $this->dao->select('closedReason as name, count(closedReason) as value')->from(TABLE_STORY)
->where('deleted')->eq(0)
->andWhere('closedReason')->ne('')
->groupBy('closedReason')->orderBy('value DESC')->fetchAll('name');
if(!$datas) return array();
foreach($datas as $reason => $data) if(isset($this->lang->story->reasonList[$reason])) $data->name = $this->lang->story->reasonList[$reason];
return $datas;
}
/**
* Get report data of storys per change
*
* @access public
* @return array
*/
public function getDataOfStorysPerChange()
{
return $this->dao->select('(version-1) as name, count(*) as value')->from(TABLE_STORY)->where('deleted')->eq(0)->groupBy('version')->orderBy('value')->fetchAll();
}
}
+62
View File
@@ -0,0 +1,62 @@
<?php
/**
* The report view file of product module of ZenTaoPMS.
*
* @copyright Copyright 2009-2010 QingDao Nature Easy Soft Network Technology Co,LTD (www.cnezsoft.com)
* @license LGPL (http://www.gnu.org/licenses/lgpl.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package product
* @version $Id: report.html.php 1594 2011-03-13 07:27:55Z wwccss $
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id='featurebar'>
<div class='f-left'><?php echo $lang->story->report->common;?></div>
<div class='f-right'><?php common::printLink('product', 'browse', "productID=$productID&browseType=$browseType&moduleID=$moduleID", $lang->goback); ?></div>
</div>
<table class='cont-lt1'>
<tr valign='top'>
<td class='side'>
<div class='box-title'><?php echo $lang->story->report->select;?></div>
<div class='box-content'>
<form method='post'>
<?php echo html::checkBox('charts', $lang->story->report->charts, $checkedCharts);?>
<input type='button' value='<?php echo $lang->story->report->selectAll;?>' onclick='checkAll()' />
<input type='button' value='<?php echo $lang->story->report->selectReverse;?>' onclick='checkReverse()' />
<br /><br />
<?php echo html::submitButton($lang->story->report->create);?>
</div>
</td>
<td class='divider'></td>
<td>
<table class='table-1'>
<caption><?php echo $lang->story->report->common;?></caption>
<?php foreach($charts as $chartType => $chartContent):?>
<tr valign='top'>
<td><?php echo $chartContent;?></td>
<td width='300'>
<table class='table-1'>
<tr>
<th><?php echo $lang->report->item;?></th>
<th><?php echo $lang->report->value;?></th>
<th><?php echo $lang->report->percent;?></th>
</tr>
<?php foreach($datas[$chartType] as $key => $data):?>
<tr class='a-center'>
<td><?php echo $data->name;?></td>
<td><?php echo $data->value;?></td>
<td><?php echo ($data->percent * 100) . '%';?></td>
</tr>
<?php endforeach;?>
</table>
</td>
</tr>
<?php endforeach;?>
</table>
</td>
</tr>
</table>
<?php echo $renderJS;?>
<?php include '../../common/view/footer.html.php';?>