This commit is contained in:
holan20180123
2020-08-20 14:56:53 +08:00
24 changed files with 980 additions and 17 deletions
+2 -1
View File
@@ -191,13 +191,14 @@ if(!defined('TABLE_LANG')) define('TABLE_LANG', '`' . $config->db-
if(!defined('TABLE_STAGE')) define('TABLE_STAGE', '`' . $config->db->prefix . 'stage`');
if(!defined('TABLE_DESIGN')) define('TABLE_DESIGN', '`' . $config->db->prefix . 'design`');
if(!defined('TABLE_DESIGNSPEC')) define('TABLE_DESIGNSPEC', '`' . $config->db->prefix . 'designspec`');
if(!defined('TABLE_ISSUE')) define('TABLE_ISSUE', '`' . $config->db->prefix . 'issue`');
if(!defined('TABLE_ISSUE')) define('TABLE_ISSUE', '`' . $config->db->prefix . 'issue`');
if(!defined('TABLE_RISK')) define('TABLE_RISK', '`' . $config->db->prefix . 'risk`');
if(!defined('TABLE_PROJECTSPEC')) define('TABLE_PROJECTSPEC', '`' . $config->db->prefix . 'projectspec`');
if(!defined('TABLE_WORKESTIMATION')) define('TABLE_WORKESTIMATION', '`' . $config->db->prefix . 'workestimation`');
if(!defined('TABLE_DURATIONESTIMATION')) define('TABLE_DURATIONESTIMATION', '`' . $config->db->prefix . 'durationestimation`');
if(!defined('TABLE_BUDGET')) define('TABLE_BUDGET', '`' . $config->db->prefix . 'budget`');
if(!defined('TABLE_HOLIDAY')) define('TABLE_HOLIDAY', '`' . $config->db->prefix . 'holiday`');
if(!defined('TABLE_WEEKLYREPORT')) define('TABLE_WEEKLYREPORT', '`' . $config->db->prefix . 'weeklyreport`');
$config->objectTables['product'] = TABLE_PRODUCT;
$config->objectTables['story'] = TABLE_STORY;
+23 -7
View File
@@ -97,7 +97,7 @@ CREATE TABLE `zt_designspec` (
-- DROP TABLE IF EXISTS `zt_issue`;
CREATE TABLE `zt_issue` (
`id` mediumint(8) UNSIGNED NOT NULL,
`id` mediumint(8) UNSIGNED NOT NULL AUTO_INCREMENT,
`resolvedBy` varchar(30) NOT NULL,
`program` varchar(255) NOT NULL,
`title` varchar(255) NOT NULL,
@@ -262,10 +262,26 @@ ADD `product` mediumint(8) unsigned NOT NULL DEFAULT '0' AFTER `project`;
-- DROP TABLE IF EXISTS `zt_taskspec`;
CREATE TABLE `zt_taskspec` (
`task` mediumint(8) NOT NULL,
`version` smallint(6) NOT NULL,
`name` varchar(255) NOT NULL,
`estStarted` date NOT NULL,
`deadline` date NOT NULL,
UNIQUE KEY `task` (`task`,`version`)
`task` mediumint(8) NOT NULL,
`version` smallint(6) NOT NULL,
`name` varchar(255) NOT NULL,
`estStarted` date NOT NULL,
`deadline` date NOT NULL,
UNIQUE KEY `task` (`task`,`version`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_weeklyreport`(
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`program` mediumint(8) unsigned NOT NULL,
`weekStart` date NOT NULL,
`pv` float(9,2) NOT NULL,
`ev` float(9,2) NOT NULL,
`ac` float(9,2) NOT NULL,
`sv` float(9,2) NOT NULL,
`cv` float(9,2) NOT NULL,
`staff` smallint(5) unsigned NOT NULL,
`progress` varchar(255) NOT NULL,
`workload` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `week` (`program`,`weekStart`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+126 -3
View File
@@ -990,7 +990,26 @@ class block extends control
*/
public function printCmmiReportBlock()
{
$this->view->program = $this->loadModel('project')->getByID($this->session->program);
$program = $this->loadModel('project')->getByID($this->session->program);
$today = date('Y-m-d', strtotime(helper::today()));
$date = date('Ymd', strtotime($this->loadModel('weekly')->getThisMonday($today)));
$begin = $program->begin;
$weeks = $this->weekly->getWeekPairs($begin);
$current = zget($weeks, $date, '');
$task = $this->dao->select("sum(consumed) as totalConsumed, sum(if(status != 'cancel' and status != 'closed', `left`, 0)) as totalLeft")->from(TABLE_TASK)->where('program')->eq($this->session->program)
->andWhere('deleted')->eq(0)
->andWhere('parent')->lt(1)
->fetch();
$this->view->pv = $this->weekly->getPV($this->session->program, $today);
$this->view->ev = $this->weekly->getEV($this->session->program, $today);
$this->view->ac = $this->weekly->getAC($this->session->program, $today);
$this->view->sv = $this->weekly->getSV($this->view->ev, $this->view->pv);
$this->view->cv = $this->weekly->getCV($this->view->ev, $this->view->ac);
$this->view->current = $current;
$this->view->progress = ($task->totalConsumed || $task->totalLeft) ? round($task->totalConsumed / ($task->totalConsumed + $task->totalLeft), 2) * 100 : 0;
}
/**
@@ -1012,7 +1031,10 @@ class block extends control
*/
public function printCmmiIssueBlock()
{
$this->view->program = $this->loadModel('project')->getByID($this->session->program);
$uri = $this->app->getURI(true);
$this->session->set('riskList', $uri);
if(preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die();
$this->view->issues = $this->loadModel('issue')->getBlockIssues($this->params->type, $this->viewType == 'json' ? 0 : (int)$this->params->num, null, $this->params->orderBy);
}
/**
@@ -1034,7 +1056,15 @@ class block extends control
*/
public function printCmmiEstimateBlock()
{
$this->view->program = $this->loadModel('project')->getByID($this->session->program);
$this->app->loadLang('durationestimation');
$programID = $this->session->program;
$members = $this->loadModel('project')->getTeamMemberPairs($programID);
$budget = $this->loadModel('workestimation')->getBudget($programID);
if(empty($budget)) $budget = new stdclass();
$this->view->people = $this->dao->select('sum(people) as people')->from(TABLE_DURATIONESTIMATION)->where('program')->eq($this->session->program)->fetch('people');
$this->view->members = count($members) ? count($members) : '';
$this->view->budget = $budget;
}
/**
@@ -1368,4 +1398,97 @@ class block extends control
$this->loadModel('setting')->setItem("{$this->app->user->account}.$module.block.initVersion", $this->config->block->version);
}
}
/**
* Print srcum project block.
*
* @access public
* @return void
*/
public function printScrumoverallBlock()
{
$this->view->program = $this->loadModel('project')->getByID($this->session->program);
}
/**
* Print srcum progress block.
*
* @access public
* @return void
*/
public function printScrumprogressBlock()
{
$this->view->program = $this->loadModel('project')->getByID($this->session->program);
}
/**
* Print srcum road map block.
*
* @access public
* @return void
*/
public function printScrumroadmapBlock()
{
$this->view->program = $this->loadModel('project')->getByID($this->session->program);
}
/**
* Print srcum road map block.
*
* @access public
* @return void
*/
public function printScrumtestBlock()
{
$this->view->program = $this->loadModel('project')->getByID($this->session->program);
$this->session->set('testtaskList', $this->app->getURI(true));
if(preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die();
$this->app->loadLang('testtask');
$this->view->testtasks = $this->dao->select('t1.*,t2.name as productName,t3.name as buildName,t4.name as projectName')->from(TABLE_TESTTASK)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product=t2.id')
->leftJoin(TABLE_BUILD)->alias('t3')->on('t1.build=t3.id')
->leftJoin(TABLE_PROJECT)->alias('t4')->on('t1.project=t4.id')
->leftJoin(TABLE_PROJECTPRODUCT)->alias('t5')->on('t1.project=t5.project')
->where('t1.deleted')->eq('0')
->beginIF(!$this->app->user->admin)->andWhere('t1.product')->in($this->app->user->view->products)->fi()
->andWhere('t1.product = t5.product')
->beginIF($this->params->type != 'all')->andWhere('t1.status')->eq($this->params->type)->fi()
->orderBy('t1.id desc')
->beginIF($this->viewType != 'json')->limit((int)$this->params->num)->fi()
->fetchAll();
}
/**
* Print srcum product block.
*
* @access public
* @return void
*/
public function printScrumproductBlock()
{
$this->view->program = $this->loadModel('project')->getByID($this->session->program);
}
/**
* Print srcum project block.
*
* @access public
* @return void
*/
public function printScrumprojectBlock()
{
$this->view->program = $this->loadModel('project')->getByID($this->session->program);
}
/**
* Print srcum dynamic block.
*
* @access public
* @return void
*/
public function printScrumdynamicBlock()
{
$this->view->program = $this->loadModel('project')->getByID($this->session->program);
}
}
+36
View File
@@ -84,6 +84,10 @@ $lang->block->default['cmmi']['program']['5']['title'] = '项目问题';
$lang->block->default['cmmi']['program']['5']['block'] = 'cmmiissue';
$lang->block->default['cmmi']['program']['5']['grid'] = 8;
$lang->block->default['cmmi']['program']['5']['params']['type'] = 'all';
$lang->block->default['cmmi']['program']['5']['params']['num'] = '15';
$lang->block->default['cmmi']['program']['5']['params']['orderBy'] = 'id_desc';
$lang->block->default['cmmi']['program']['6']['title'] = '最新动态';
$lang->block->default['cmmi']['program']['6']['block'] = 'dynamic';
$lang->block->default['cmmi']['program']['6']['grid'] = 4;
@@ -93,6 +97,38 @@ $lang->block->default['cmmi']['program']['7']['title'] = '项目风险';
$lang->block->default['cmmi']['program']['7']['block'] = 'cmmirisk';
$lang->block->default['cmmi']['program']['7']['grid'] = 8;
$lang->block->default['cmmi']['program']['7']['params']['type'] = 'all';
$lang->block->default['cmmi']['program']['7']['params']['num'] = '15';
$lang->block->default['cmmi']['program']['7']['params']['orderBy'] = 'id_desc';
$lang->block->default['scrum']['program']['1']['title'] = '项目整体情况';
$lang->block->default['scrum']['program']['1']['block'] = 'scrumoverall';
$lang->block->default['scrum']['program']['1']['grid'] = 8;
$lang->block->default['scrum']['program']['2']['title'] = '进行中的迭代';
$lang->block->default['scrum']['program']['2']['block'] = 'scrumprogress';
$lang->block->default['scrum']['program']['2']['grid'] = 8;
$lang->block->default['scrum']['program']['3']['title'] = '产品路线图';
$lang->block->default['scrum']['program']['3']['block'] = 'scrumroadmap';
$lang->block->default['scrum']['program']['3']['grid'] = 8;
$lang->block->default['scrum']['program']['4']['title'] = '待测版本';
$lang->block->default['scrum']['program']['4']['block'] = 'scrumtest';
$lang->block->default['scrum']['program']['4']['grid'] = 8;
$lang->block->default['scrum']['program']['5']['title'] = '产品总览';
$lang->block->default['scrum']['program']['5']['block'] = 'scrumproduct';
$lang->block->default['scrum']['program']['5']['grid'] = 4;
$lang->block->default['scrum']['program']['6']['title'] = '迭代总览';
$lang->block->default['scrum']['program']['6']['block'] = 'scrumproject';
$lang->block->default['scrum']['program']['6']['grid'] = 4;
$lang->block->default['scrum']['program']['7']['title'] = '最新动态';
$lang->block->default['scrum']['program']['7']['block'] = 'scrumoverview';
$lang->block->default['scrum']['program']['7']['grid'] = 4;
$lang->block->default['product']['1']['title'] = $lang->productCommon . '统计';
$lang->block->default['product']['1']['block'] = 'statistic';
$lang->block->default['product']['1']['grid'] = 8;
@@ -0,0 +1,19 @@
<style> .block-cmmiestimate table{margin-bottom: 15px} </style>
<table class='table table-data'>
<tr>
<th class='w-100px'><?php echo $lang->durationestimation->people;?></th>
<td><?php echo $people;?></td>
<th class='w-80px'><?php echo $lang->durationestimation->members;?></th>
<td><?php echo $members;?></td>
</tr>
<tr>
<th><?php echo $lang->workestimation->duration;?></th>
<td><?php echo zget($budget, 'duration', 0) . ' ' . $lang->workestimation->hour;?></td>
<th><?php echo $lang->workestimation->consumed;?></th>
<td><?php echo zget($budget, 'productivity', '') . ' ' . $lang->workestimation->hour;?></td>
</tr>
<tr>
<th><?php echo $lang->workestimation->totalLaborCost;?></th>
<td><?php echo '¥' . zget($budget, 'totalLaborCost', 0);?></td>
</tr>
</table>
+49
View File
@@ -0,0 +1,49 @@
<?php if(empty($issues)): ?>
<div class='empty-tip'><?php echo $lang->block->emptyTip;?></div>
<?php else:?>
<style>
.block-issues .c-id {width: 55px;}
.block-issues .c-pri {width: 45px;text-align: center;}
.block-issues .c-estimate {width: 60px;}
.block-issues .c-deadline {width: 95px;}
.block-issues .c-status {width: 80px;}
.block-issues.block-sm .c-status {text-align: center;}
</style>
<div class='panel-body has-table scrollbar-hover'>
<table class='table table-borderless table-hover table-fixed table-fixed-head tablesorter block-issues <?php if(!$longBlock) echo 'block-sm';?>'>
<thead>
<tr>
<th class='c-id'><?php echo $lang->idAB;?></th>
<th class='w-100px'><?php echo $lang->issue->type;?></th>
<th class='c-name'> <?php echo $lang->issue->name;?></th>
<?php if($longBlock):?>
<th class='c-severity'><?php echo $lang->issue->severity;?></th>
<th class='c-pri'><?php echo $lang->issue->pri;?></th>
<?php endif;?>
<th class='w-120px'><?php echo $lang->issue->assignedTo;?></th>
<th class='w-80px'><?php echo $lang->issue->status;?></th>
</tr>
</thead>
<tbody>
<?php foreach($issues as $issue):?>
<?php
$viewLink = $this->createLink('issue', 'view', "issueID={$issue->id}");
?>
<tr>
<td class='c-id-xs'><?php echo sprintf('%03d', $issue->id);?></td>
<td class='c-type'><?php echo zget($lang->issue->typeList, $issue->type);?></td>
<td class='c-name' title='<?php echo $issue->name?>'><?php echo $issue->name?></td>
<?php if($longBlock):?>
<td class='c-severity'><?php echo zget($lang->issue->severityList, $issue->severity, $issue->severity)?></td>
<td class='c-pri'><span class='label-pri label-pri-<?php echo $issue->pri;?>' title='<?php echo zget($lang->issue->priList, $issue->pri, $issue->pri)?>'><?php echo zget($lang->issue->priList, $issue->pri, $issue->pri)?></span></td>
<?php endif;?>
<td><?php echo zget($users, $issue->assignedTo, $issue->assignedTo)?></td>
<td class='c-status'>
<span class="status-issue status-<?php echo $issue->status?>"><?php echo zget($lang->issue->statusList, $issue->status);?></span>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
</div>
<?php endif;?>
+31 -5
View File
@@ -3,22 +3,48 @@
.block-cmmireport .col-right{width: 75%;}
.block-cmmireport .panel-body{padding-top: 0px;}
.block-cmmireport .table-row{margin-bottom: 20px;}
.progress {position: absolute; left: 22px; top: 90px; right: 8px;}
.block-cmmireport .stage{position: absolute; top: 14px; left: 90px;}
.block-cmmireport .col-right .tiles { padding: 10px 0 0 16px; }
.block-cmmireport .col-right .tile { width: 20%;}
.block-cmmireport .col-right .tile .tile-title{font-weight: 700;}
.progress {position: absolute; left: 45px; top: 90px; right: 40px;}
.progress-num{font-size: 34px; font-weight: 700}
</style>
<div class="panel-move-handler"></div>
<div class="panel-move-handler"><span class='stage text-muted'><?php echo $current;?></span></div>
<div class="panel-body conatiner-fluid">
<div class='table-row'>
<div class="col col-left hide-in-sm">
<h4>项目进度</h4>
<span class='progress-num'>70%</span>
<h4><?php echo $lang->program->progress;?></h4>
<span class='progress-num'><?php echo $progress . '%';?></span>
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="70" aria-valuemin="0" aria-valuemax="100" style="width: 70%">
<div class="progress-bar" role="progressbar" aria-valuenow="<?php echo $progress;?>" aria-valuemin="0" aria-valuemax="100" style="width: <?php echo $progress;?>%">
</div>
</div>
</div>
<div class='col-right'>
<div class='row tiles'>
<div class="col tile">
<div class="tile-title">PV</div>
<div class="tile-amount"><?php echo $pv == 0 ? 0 : $pv;?></div>
</div>
<div class="col tile">
<div class="tile-title">EV</div>
<div class="tile-amount"><?php echo $ev == 0 ? 0 : $ev;?></div>
</div>
<div class="col tile">
<div class="tile-title">AC</div>
<div class="tile-amount"><?php echo $ac == 0 ? 0 : $ac;?></div>
</div>
<div class="col tile">
<div class="tile-title">SV%</div>
<div class="tile-amount"><?php echo $sv . '%';?></div>
</div>
<div class="col tile">
<div class="tile-title">CV%</div>
<div class="tile-amount"><?php echo $cv . '%';?></div>
</div>
</div>
</div>
</div>
</div>
+54
View File
@@ -0,0 +1,54 @@
<?php
/**
* The testtask block view file of block module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Yidong Wang <yidong@cnezsoft.com>
* @package block
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php if(empty($testtasks)): ?>
<div class='empty-tip'><?php echo $lang->block->emptyTip;?></div>
<?php else:?>
<div class='panel-body has-table scrollbar-hover'>
<table class='table table-borderless table-hover table-fixed-head tablesorter block-testtask table-fixed'>
<thead>
<tr class='text-center'>
<?php if($longBlock):?>
<th class='w-id'><?php echo $lang->idAB?></th>
<th class='text-left'><?php echo $lang->testtask->product;?></th>
<?php endif;?>
<th class='text-left'><?php echo $lang->testtask->name;?></th>
<?php if($longBlock):?>
<th class='text-left'><?php echo $lang->testtask->project . '/' . $lang->testtask->build;?></th>
<?php endif;?>
<th class='w-date'><?php echo $lang->testtask->begin;?></th>
<th class='w-date'><?php echo $lang->testtask->end;?></th>
</tr>
</thead>
<tbody>
<?php foreach($testtasks as $testtask):?>
<?php
$appid = isset($_GET['entry']) ? "class='app-btn' data-id='{$this->get->entry}'" : '';
$viewLink = $this->createLink('testtask', 'view', "testtaskID={$testtask->id}");
?>
<tr class='text-center' data-url='<?php echo empty($sso) ? $viewLink : $sso . $sign . 'referer=' . base64_encode($viewLink); ?>' <?php echo $appid?>>
<?php if($longBlock):?>
<td><?php echo sprintf('%03d', $testtask->id);?></td>
<td class='text-left' title='<?php echo $testtask->productName?>'><?php echo $testtask->productName?></td>
<?php endif;?>
<td class='text-left' title='<?php echo $testtask->name?>'><?php echo $testtask->name?></td>
<?php if($longBlock):?>
<td class='text-left' title='<?php echo $testtask->projectName . '/' . $testtask->buildName?>'><?php echo $testtask->projectName . '/' . $testtask->buildName?></td>
<?php endif;?>
<td><?php echo $testtask->begin?></td>
<td><?php echo $testtask->end?></td>
</tr>
<?php endforeach;?>
</tbody>
</table>
</div>
<?php endif;?>
+4
View File
@@ -1118,6 +1118,10 @@ $lang->menu->cmmi->issue = '问题|issue|browse|';
$lang->menu->cmmi->risk = '风险|risk|browse|';
$lang->menu->cmmi->list = array('link' => '更多|workestimation|index|program={PROGRAM}', 'class' => 'dropdown dropdown-hover cmmi-list', 'subModule' => 'stakeholder,workestimation,durationestimation,budget,pssp,stakeholder');
/* Srcum menu. */
$lang->menu->srcum = new stdclass();
$lang->menu->srcum->programindex = array('link' => '仪表盘|program|index|program={PROGRAM}');
$lang->cmmi = new stdclass();
$lang->cmmi->subMenu = new stdclass();
$lang->cmmi->subMenu->list = new stdclass();
+2 -1
View File
@@ -6,7 +6,8 @@ $lang->durationestimation->stage = '阶段';
$lang->durationestimation->workloadRate = '工作量占比';
$lang->durationestimation->workload = '工作量';
$lang->durationestimation->worktimeRate = '全时率';
$lang->durationestimation->people = '投入人数';
$lang->durationestimation->people = '估算人数';
$lang->durationestimation->members = '投入人数';
$lang->durationestimation->startDate = '开始日期';
$lang->durationestimation->endDate = '结束日期';
$lang->durationestimation->setting = '设置';
+12
View File
@@ -83,6 +83,18 @@ class issueModel extends model
return $issueList;
}
public function getBlockIssues($browseType = 'all', $limit = 15, $orderBy = 'id_desc')
{
$issueList = $this->dao->select('*')->from(TABLE_ISSUE)
->where('program')->eq($this->session->program)
->andWhere('deleted')->eq('0')
->orderBy($orderBy)
->limit($limit)
->fetchAll();
return $issueList;
}
/**
* Delete a question.
*
+1
View File
@@ -25,6 +25,7 @@ class program extends control
$this->view->title = $this->lang->program->common . $this->lang->colon . $this->lang->program->index;
$this->view->position[] = $this->lang->program->index;
$this->view->program = $this->project->getByID($programID);
$this->display();
}
+1
View File
@@ -46,6 +46,7 @@ $lang->program->mine = '我参与的';
$lang->program->setPlanduration = '设置工期';
$lang->program->privway = '权限控制';
$lang->program->durationEstimation = '工作量估算';
$lang->program->progress = '项目进度';
$lang->program->unitList[''] = '';
$lang->program->unitList['yuan'] = '元';
+47
View File
@@ -0,0 +1,47 @@
<?php
/**
* The control file of weekly of ChanzhiEPS.
*
* @copyright Copyright 2009-2010 QingDao Nature Easy Soft Network Technology Co,LTD (www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv11.html)
* @author Xiying Guan <guanxiying@xirangit.com>
* @package weekly
* @version $Id$
* @link http://www.chanzhi.org
*/
class weekly extends control
{
public function __construct()
{
parent::__construct();
$this->view->users = $this->loadModel('user')->getPairs('noletter');
}
public function index($program, $date = '')
{
if(!$date) $date = helper::today();
$date = date('Y-m-d', strtotime($date));
$this->view->title = $this->lang->weekly->common;
$this->view->pv = $this->weekly->getPV($program, $date);
$this->view->ev = $this->weekly->getEV($program, $date);
$this->view->ac = $this->weekly->getAC($program, $date);
$this->view->sv = $this->weekly->getSV($this->view->ev, $this->view->pv);
$this->view->cv = $this->weekly->getCV($this->view->ev, $this->view->ac);
$this->view->program = $this->loadModel('project')->getByID($program);
$this->view->weekSN = $this->weekly->getWeekSN($this->view->program->begin, $date);
$this->view->monday = $this->weekly->getThisMonday($date);
$this->view->lastDay = $this->weekly->getLastDay($date);
$this->view->staff = $this->weekly->getStaff($program);
$this->view->finished = $this->weekly->getFinished($program);
$this->view->postponed = $this->weekly->getPostponed($program);
$this->view->nextWeek = $this->weekly->getTasksOfNextWeek($program, $date);
$this->view->workload = $this->weekly->getWorkloadByType($program, $date);
$this->weekly->save($program, $this->view, $date);
$this->lang->modulePageNav = $this->weekly->getPageNav($this->view->program, $date);
$this->display();
}
}
+29
View File
@@ -0,0 +1,29 @@
<?php
$lang->weekly->common = '项目周报';
$lang->weekly->index = '周报总览';
$lang->weekly->progress = '完成百分比';
$lang->weekly->workload = '工作量';
$lang->weekly->total = '合计';
$lang->weekly->reportTtitle = '项目: %s 周报(第 %s 周)';
$lang->weekly->summary = '项目进展状况';
$lang->weekly->finished = '本周工作完成情况(100%完成的工作)';
$lang->weekly->postponed = '本周未完成工作';
$lang->weekly->nextWeek = '下周工作计划';
$lang->weekly->workloadByType = '工作量统计';
$lang->weekly->term = '报告周期';
$lang->weekly->program = '项目名称';
$lang->weekly->master = '项目经理 ';
$lang->weekly->staff = '本周投入人数';
$lang->weekly->weekDesc = '第 %s 周( %s ~ %s)';
$lang->weekly->progress = '项目当前进展状况';
$lang->weekly->analysisResult = '分析结果';
$lang->weekly->cost = '项目成本';
$lang->weekly->pv = '计划完成的工作(PV)';
$lang->weekly->ev = '实际完成的工作(EV)';
$lang->weekly->ac = '实际花费的成本(AC)';
$lang->weekly->sv = '进度偏差率(SV%)';
$lang->weekly->cv = '成本偏差率(CV%)';
+356
View File
@@ -0,0 +1,356 @@
<?php
/**
* The model file of weekly module of ChanzhiEPS.
*
* @copyright Copyright 2009-2010 QingDao Nature Easy Soft Network Technology Co,LTD (www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv11.html)
* @author Xiying Guan <guanxiying@xirangit.com>
* @package weekly
* @version $Id$
* @link http://www.chanzhi.org
*/
class weeklyModel extends model
{
public function getPageNav($program, $date)
{
$date = date('Ymd', strtotime($this->getThisMonday($date)));
$begin = $program->begin;
$weeks = $this->getWeekPairs($begin);
$current = zget($weeks, $date, '');
$selectHtml = "<div class='btn-group angle-btn'>";
$selectHtml .= html::a('###', $this->lang->weekly->common . $this->lang->colon . $program->name, '', "class='btn'");
$selectHtml .= '</div>';
$selectHtml .= "<div class='btn-group angle-btn'>";
$selectHtml .= "<div class='btn-group'>";
$selectHtml .= "<a data-toggle='dropdown' class='btn' title=$current>" . $current . " <span class='caret'></span></a>";
$selectHtml .= "<ul class='dropdown-menu'>";
foreach($weeks as $day => $title)
{
$selectHtml .= '<li>' . html::a(helper::createLink('weekly', 'index', "program={$program->id}&date=$day"), $title) . '</li>';
}
$selectHtml .='</ul></div></div>';
return $selectHtml;
}
public function getWeekPairs($begin)
{
$sn = $this->getWeekSN($begin, date('Y-m-d'));
$weeks = array();
for($i = 0; $i <= $sn; $i++)
{
$monday = $this->getThisMonday($begin);
$sunday = $this->getThisSunday($begin);
$begin = date('Y-m-d', strtotime("$begin +7 days"));
$key = date('Ymd', strtotime($monday));
$weeks[$key] = sprintf($this->lang->weekly->weekDesc, $i + 1, $monday, $sunday);
}
krsort($weeks);
return $weeks;
}
public function getFromDB($program, $date)
{
$monday = $this->getThisMonday($date);
return $this->dao->select('*')
->from(TABLE_WEEKLYREPORT)
->where('weekStart')->eq($monday)
->andWhere('program')->eq($program)
->fetch();
}
public function save($program, $data, $date)
{
$report = new stdclass;
$report->pv = zget($data, 'pv', '');
$report->ev = zget($data, 'ev', '');
$report->ac = zget($data, 'ac', '');
$report->sv = zget($data, 'sv', '');
$report->cv = zget($data, 'cv', '');
$report->program = $program;
$report->weekStart = $this->getThisMonday($date);
$report->staff = zget($data, 'staff', '');
$report->progress = zget($data, 'progress', '');
$report->workload = json_encode(zget($data, 'workload', ''));
$this->dao->replace(TABLE_WEEKLYREPORT)->data($report)->exec();
}
public function getWeekSN($begin, $date)
{
return ceil((strtotime($date) - strtotime($begin)) / 7 / 86400);
}
public function getThisMonday($date)
{
$day = date('w', strtotime($date));
if($day == 0) $day = 7;
$days = $day - 1;
return date('Y-m-d', strtotime("$date - $days days"));
}
public function getThisSunday($date)
{
$monday = $this->getThisMonday($date);
return date('Y-m-d', strtotime("$monday +6 days"));
}
public function getLastDay($date)
{
$this->loadModel('project');
$weekend = zget($this->config->project, 'weekend', 2);
$monday = $this->getThisMonday($date);
$sunday = $this->getThisSunday($date);
$workdays = $this->loadModel('holiday')->getActualWorkingDays($monday, $sunday);
return end($workdays);
}
public function getStaff($program, $date = '')
{
if(!$date) $date = date('Y-m-d');
$monday = $this->getThisMonday($date);
$sunday = $this->getThisSunday($date);
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $type = 'project', $program);
$projectIdList = array_keys($projects);
return $this->dao->select('count(distinct account) as count')
->from(TABLE_EFFORT)
->where('objectType')->eq('task')
->andWhere('project')->in($projectIdList)
->andWhere('date')->ge($monday)
->andWhere('date')->le($sunday)
->fetch('count');
}
public function getFinished($program, $date = '', $pager = null)
{
if(!$date) $date = date('Y-m-d');
$monday = $this->getThisMonday($date);
$sunday = $this->getThisSunday($date);
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $type = 'project', $program);
$projectIdList = array_keys($projects);
$tasks = $this->dao->select('*')
->from(TABLE_TASK)
->where('project')->in($projectIdList)
->andWhere("(status='done' or closedReason= 'done')")
->andWhere('finishedDate')->ge($monday)
->andWhere('finishedDate')->le($sunday)
->fetchAll();
return $this->loadModel('task')->processTasks($tasks);
}
public function getPostponed($program, $date = '')
{
if(!$date) $date = date('Y-m-d');
$monday = $this->getThisMonday($date);
$sunday = $this->getThisSunday($date);
$nextMonday = date('Y-m-d', strtotime("$sunday +1 days"));
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $type = 'project', $program);
$projectIdList = array_keys($projects);
$unFinished = $this->dao->select('*')
->from(TABLE_TASK)
->where('project')->in($projectIdList)
->andWhere('status')->in('wait,doing,pause')
->andWhere('deadline')->ge($monday)
->andWhere('deadline')->le($sunday)
->fetchAll('id');
$postponed = $this->dao->select('*')
->from(TABLE_TASK)
->where('project')->in($projectIdList)
->andWhere('finishedDate')->gt($nextMonday)
->andWhere('deadline')->ge($monday)
->andWhere('deadline')->lt($nextMonday)
->fetchAll('id');
$tasks = array_merge($unFinished, $postponed);
return $this->loadModel('task')->processTasks($tasks);
}
public function getTasksOfNextWeek($program, $date = '')
{
if(!$date) $date = date('Y-m-d');
$sunday = $this->getThisSunday($date);
$nextMonday = date('Y-m-d', strtotime("$sunday +1 days"));
$sencondMondy = date('Y-m-d', strtotime("$sunday +8 days"));
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $type = 'project', $program);
$projectIdList = array_keys($projects);
$tasks = $this->dao->select('*')
->from(TABLE_TASK)
->where('project')->in($projectIdList)
->andWhere("((deadline > '$nextMonday' and deadline < '$sencondMondy') or (estStarted > '$nextMonday' and estStarted < '$sencondMondy'))")
->fetchAll('id');
return $this->loadModel('task')->processTasks($tasks);
}
public function getWorkloadByType($program, $date = '')
{
if(!$date) $date = date('Y-m-d');
$sunday = $this->getThisSunday($date);
$nextMonday = date('Y-m-d', strtotime("$sunday +1 days"));
$sencondMondy = date('Y-m-d', strtotime("$sunday +8 days"));
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $type = 'project', $program);
$projectIdList = array_keys($projects);
return $this->dao->select('type, sum(cast(estimate as decimal(10,2))) as workload')
->from(TABLE_TASK)
->where('project')->in($projectIdList)
->groupBy('type')
->fetchPairs();
}
public function getPlanedTaskByWeek($program, $date = '')
{
if(!$date) $date = date('Y-m-d');
$monday = $this->getThisMonday($date);
$nextMonday = date('Y-m-d', strtotime("$monday +7 days"));
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $type = 'project', $program);
$projectIdList = array_keys($projects);
return $this->dao->select('*')
->from(TABLE_TASK)
->where('project')->in($projectIdList)
->andWhere('deadline')->ge($monday)
->fetchAll('id');
}
public function getPV($program, $date = '')
{
$report = $this->getFromDB($program, $date);
if(!empty($report)) return $report->pv;
$program = $this->loadModel('project')->getByID($program);
if(!$date) $date = date('Y-m-d');
$monday = $this->getThisMonday($date);
$sunday = $this->getThisSunday($date);
$lastDay = $this->getLastDay($date);
$nextMonday = date('Y-m-d', strtotime("$sunday +1 days"));
$workdays = $this->loadModel('holiday')->getActualWorkingDays($monday, $sunday);
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $type = 'project', $program->id);
$projectIdList = array_keys($projects);
$tasks = $this->dao->select('*')->from(TABLE_TASK)
->where('project')->in($projectIdList)
->andWhere("(estStarted < '$nextMonday' or estStarted='0000-00-00')")
->fetchAll('id');
$PV = 0;
foreach($tasks as $task)
{
if($task->estStarted == '0000-00-00') $task->estStarted = date('Y-m-d', strtotime($task->openedDate));
if($task->deadline < $nextMonday)
{
$PV += $task->estimate;
continue;
}
$fullDays = $this->loadModel('holiday')->getActualWorkingDays($task->estStarted, $task->deadline);
$passedDays = $this->loadModel('holiday')->getActualWorkingDays($task->estStarted, $sunday);
$PV += count($passedDays) * $task->estimate / count($fullDays);
}
return round($PV, 2);
}
public function getEV($program, $date = '')
{
$report = $this->getFromDB($program, $date);
if(!empty($report)) return $report->ev;
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $type = 'project', $program);
$projectIdList = array_keys($projects);
if(!$date) $date = date('Y-m-d');
$monday = $this->getThisMonday($date);
$sunday = $this->getThisSunday($date);
$lastDay = $this->getLastDay($date);
$nextMonday = date('Y-m-d', strtotime("$sunday +1 days"));
$tasks = $this->dao->select('*')
->from(TABLE_TASK)
->where('project')->in($projectIdList)
->andWhere('consumed')->gt(0)
->andWhere('status')->ne('cancel')
->fetchAll('id');
$EV = 0;
foreach($tasks as $task)
{
if($task->status == 'done' or $task->closedReason == 'done')
{
$EV += $task->estimate;
}
else
{
$task->progress = round($task->consumed / ($task->consumed + $task->left), 2) * 100;
$EV += $task->estimate * $task->progress / 100;
}
}
return round($EV, 2);
}
public function getAC($program, $date = '')
{
$report = $this->getFromDB($program, $date);
if(!empty($report)) return $report->ac;
if(!$date) $date = date('Y-m-d');
$monday = $this->getThisMonday($date);
$nextMonday = date('Y-m-d', strtotime("$monday +7 days"));
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $type = 'project', $program);
$projectIdList = array_keys($projects);
$AC = $this->dao->select('sum(consumed) as consumed')
->from(TABLE_EFFORT)
->where('objectType')->eq('task')
->andWhere('project')->in($projectIdList)
->andWhere('date')->ge($monday)
->andWhere('date')->lt($nextMonday)
->fetch('consumed');
return round($AC, 2);
}
public function getSV($ev, $pv)
{
if($pv == 0) return 0;
$sv = -1 * (1- ($ev / $pv));
return number_format($sv * 100, 2);
}
public function getCV($ev, $ac)
{
if($ac == 0) return 0;
$cv = -1 * (1 - ($ev / $ac));
return number_format($cv * 100, 2);
}
public function getTips($type = 'progress', $data = 0)
{
$this->app->loadConfig('custom');
if($type == 'progress') $tipsConfig = isset($this->config->custom->SV->progressTip) ? $this->config->custom->SV->progressTip : '';
if($type == 'cost') $tipsConfig = isset($this->config->custom->CV->costTip) ? $this->config->custom->CV->costTip : '';
if(empty($tipsConfig)) return '';
$tipsConfig = json_decode($tipsConfig);
foreach($tipsConfig as $tipConfig)
{
if($tipConfig->min <= $data and $tipConfig->max >= $data) return $tipConfig->tip;
}
return '';
}
}
+186
View File
@@ -0,0 +1,186 @@
<?php
/**
* The html template file of index method of index module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package ZenTaoPMS
* @version $Id: index.html.php 5094 2013-07-10 08:46:15Z chencongzhi520@gmail.com $
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id="mainMenu" class="clearfix text-center">
<div id='mainContent' >
<div class='main-table'>
<table class='table table-bordered'>
<tr>
<td><?php echo $lang->weekly->term;?></td>
<td><?php echo $monday . ' ~ ' . $lastDay?></td>
<td><?php echo $lang->weekly->master;?></td>
<td><?php echo zget($users, $program->PM, '');?></td>
</tr>
<tr>
<td><?php echo $lang->weekly->program;?></td>
<td><?php echo $program->name;?></td>
<td><?php echo $lang->weekly->staff;?></td>
<td><?php echo $staff;?></td>
</tr>
</table>
<div class='page-title'><h4><?php echo $lang->weekly->summary;?></h4></div>
<table class='table table-bordered'>
<tr>
<td><?php echo $lang->weekly->progress;?></td>
<td></td>
<td><?php echo $lang->weekly->analysisResult;?></td>
<td></td>
</tr>
<tr>
<td><?php echo $lang->weekly->pv;?></td>
<td><?php echo $pv;?></td>
<td rowspan='4'><?php echo $lang->weekly->progress;?></td>
<td rowspan='4'><?php echo $this->weekly->getTips('progress', $sv);?></td>
</tr>
<tr>
<td><?php echo $lang->weekly->ev;?></td>
<td><?php echo $ev;?></td>
</tr>
<tr>
<td><?php echo $lang->weekly->ac;?></td>
<td><?php echo $ac;?></td>
</tr>
<tr>
<td><?php echo $lang->weekly->sv;?></td>
<td><?php echo $sv ? $sv . '%' : '';?></td>
</tr>
<tr>
<td><?php echo $lang->weekly->cv;?></td>
<td><?php echo $cv ? $cv . '%' : '';?></td>
<td><?php echo $lang->weekly->cost;?></td>
<?php $projectCost = zget($this->config->custom, 'cost', 1);?>
<td><?php echo empty($projectCost) ? 0 : $ac * $projectCost;?></td>
</tr>
</table>
<div class='page-title'><h4><?php echo $lang->weekly->finished;?></h4></div>
<table class='table has-sort-head table-fixed'>
<thead>
<tr>
<th class='c-id'><?php echo $lang->idAB;?></th>
<th class='text-left'><?php echo $lang->task->name;?></th>
<th class='text-left w-120px'><?php echo $lang->task->estStarted;?></th>
<th class='text-left w-120px'><?php echo $lang->task->deadline;?></th>
<th class='text-left w-120px'><?php echo $lang->task->realStarted;?></th>
<th class='text-left w-100px'><?php echo $lang->task->finishedBy;?></th>
</tr>
</thead>
<tbody>
<?php foreach($finished as $task):?>
<tr data-id='<?php echo $task->id ?>'>
<td class='c-id'>
<?php printf('%03d', $task->id);?>
</td>
<td class='text-left' title='<?php echo $task->name?>'>
<?php echo html::a($this->createLink('task', 'view', 'id=' . $task->id), $task->name); ?>
</td>
<td class='text-left'><?php echo $task->estStarted;?></td>
<td class='text-left'><?php echo $task->deadline;?></td>
<td class='text-left'><?php echo $task->realStarted;?></td>
<td class='text-left'><?php echo zget($users, $task->finishedBy);?></td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<div class='page-title'><h4><?php echo $lang->weekly->postponed;?></h4></div>
<table class='table has-sort-head table-fixed'>
<thead>
<tr>
<th class='c-id'><?php echo $lang->idAB;?></th>
<th class='text-left'><?php echo $lang->task->name;?></th>
<th class='text-left w-100px'><?php echo $lang->task->assignedTo;?></th>
<th class='text-left w-120px'><?php echo $lang->task->estStarted;?></th>
<th class='text-left w-120px'><?php echo $lang->task->deadline;?></th>
<th class='text-left w-120px'><?php echo $lang->task->realStarted;?></th>
<th class='text-left w-100px'><?php echo $lang->task->progress;?></th>
</tr>
</thead>
<tbody>
<?php foreach($postponed as $task):?>
<tr data-id='<?php echo $task->id ?>'>
<td class='c-id'>
<?php printf('%03d', $task->id);?>
</td>
<td class='text-left' title='<?php echo $task->name?>'>
<?php echo html::a($this->createLink('task', 'view', 'id=' . $task->id), $task->name); ?>
</td>
<td class='text-left'><?php echo zget($users, $task->assignedTo);?></td>
<td class='text-left'><?php echo $task->estStarted;?></td>
<td class='text-left'><?php echo $task->deadline;?></td>
<td class='text-left'><?php echo $task->realStarted;?></td>
<td class='text-left'><?php echo $task->progress;?>%</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<div class='page-title'><h4><?php echo $lang->weekly->nextWeek;?></h4></div>
<table class='table has-sort-head table-fixed'>
<thead>
<tr>
<th class='c-id'><?php echo $lang->idAB;?></th>
<th class='text-left'><?php echo $lang->task->name;?></th>
<th class='text-left w-100px'><?php echo $lang->task->assignedTo;?></th>
<th class='text-left tw-120px'><?php echo $lang->task->estStarted;?></th>
<th class='text-left w-120px'><?php echo $lang->task->deadline;?></th>
</tr>
</thead>
<tbody>
<?php foreach($nextWeek as $task):?>
<tr data-id='<?php echo $task->id ?>'>
<td class='c-id'>
<?php printf('%03d', $task->id);?>
</td>
<td class='text-left' title='<?php echo $task->name?>'>
<?php echo html::a($this->createLink('task', 'view', 'id=' . $task->id), $task->name); ?>
</td>
<td class='text-left'><?php echo zget($users, $task->assignedTo);?></td>
<td class='text-left'><?php echo $task->estStarted;?></td>
<td class='text-left'><?php echo $task->deadline;?></td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<div class='page-title'><h4><?php echo $lang->weekly->workloadByType;?></h4></div>
<table class='table has-sort-head table-fixed'>
<thead>
<tr>
<th><?php echo $lang->task->type;?></th>
<?php foreach($lang->task->typeList as $type => $name):?>
<?php if(!$name) continue;?>
<th><?php echo $name;?></th>
<?php endforeach;?>
<th><?php echo $lang->weekly->total;?></th>
</tr>
</thead>
<tbody class='sortable' id='taskTableList'>
<tr>
<th><?php echo $lang->weekly->workload;?></th>
<?php $total = 0;?>
<?php foreach($lang->task->typeList as $type => $name):?>
<?php if(!$name) continue;?>
<?php $worktimes = zget($workload, $type, 0);?>
<td><?php echo $worktimes;?></td>
<?php $total += $worktimes;?>
<?php if(!$name) continue;?>
<?php endforeach;?>
<td><?php echo $total;?></td>
</tr>
</tbody>
</table>
</div>
</div>
<style>
.main-table tbody>tr:nth-child(odd){ background-color:#fff;}
</style>
<?php include '../../common/view/footer.html.php';?>
+2
View File
@@ -1,5 +1,6 @@
<?php
$lang->workestimation->common = '工作量估算';
$lang->workestimation->budget = '估算';
$lang->workestimation->index = '总览';
$lang->workestimation->scale = '规模';
$lang->workestimation->productivity = '生产率';
@@ -8,6 +9,7 @@ $lang->workestimation->unitLaborCost = '单位人工成本';
$lang->workestimation->totalLaborCost = '估算人工成本';
$lang->workestimation->dayHour = '每日工时';
$lang->workestimation->hour = '工时';
$lang->workestimation->consumed = '已消耗工时';
$lang->workestimation->programScaleTip = "当前项目实际规模:<strong>%s{$lang->hourCommon}</strong> <a href='###' id='useScale' class='btn btn-xs'>使用</span>";