From de3c53ec94222426cb621f8ff56b8f2e4318dc8c Mon Sep 17 00:00:00 2001
From: Yagami <976204163@qq.com>
Date: Thu, 20 Aug 2020 11:09:23 +0800
Subject: [PATCH 1/4] * Add blocks.
---
config/zentaopms.php | 3 +-
db/update20.0.sql | 28 +-
module/block/control.php | 36 +-
module/block/lang/zh-cn.php | 8 +
module/block/view/cmmiestimateblock.html.php | 19 +
module/block/view/cmmiissueblock.html.php | 49 +++
module/block/view/cmmireportblock.html.php | 36 +-
module/durationestimation/lang/zh-cn.php | 3 +-
module/issue/model.php | 12 +
module/program/lang/zh-cn.php | 1 +
module/weekly/control.php | 47 +++
module/weekly/lang/zh-cn.php | 29 ++
module/weekly/model.php | 356 +++++++++++++++++++
module/weekly/view/index.html.php | 186 ++++++++++
module/workestimation/lang/zh-cn.php | 2 +
15 files changed, 799 insertions(+), 16 deletions(-)
create mode 100644 module/weekly/control.php
create mode 100644 module/weekly/lang/zh-cn.php
create mode 100644 module/weekly/model.php
create mode 100644 module/weekly/view/index.html.php
diff --git a/config/zentaopms.php b/config/zentaopms.php
index 8b9c05222d..527d4c87fa 100644
--- a/config/zentaopms.php
+++ b/config/zentaopms.php
@@ -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;
diff --git a/db/update20.0.sql b/db/update20.0.sql
index 6024f6404c..5e06cbc15a 100644
--- a/db/update20.0.sql
+++ b/db/update20.0.sql
@@ -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;
diff --git a/module/block/control.php b/module/block/control.php
index e778970060..c0a463d030 100644
--- a/module/block/control.php
+++ b/module/block/control.php
@@ -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;
}
/**
diff --git a/module/block/lang/zh-cn.php b/module/block/lang/zh-cn.php
index 73eb0241cf..f23dba8fde 100644
--- a/module/block/lang/zh-cn.php
+++ b/module/block/lang/zh-cn.php
@@ -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,10 @@ $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['product']['1']['title'] = $lang->productCommon . '统计';
$lang->block->default['product']['1']['block'] = 'statistic';
$lang->block->default['product']['1']['grid'] = 8;
diff --git a/module/block/view/cmmiestimateblock.html.php b/module/block/view/cmmiestimateblock.html.php
index e69de29bb2..162bbd283b 100644
--- a/module/block/view/cmmiestimateblock.html.php
+++ b/module/block/view/cmmiestimateblock.html.php
@@ -0,0 +1,19 @@
+
+
-
项目进度
-
70%
+
program->progress;?>
+
diff --git a/module/durationestimation/lang/zh-cn.php b/module/durationestimation/lang/zh-cn.php
index 84fda83577..ca14a4ac9c 100644
--- a/module/durationestimation/lang/zh-cn.php
+++ b/module/durationestimation/lang/zh-cn.php
@@ -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 = '设置';
diff --git a/module/issue/model.php b/module/issue/model.php
index 932b1aca98..1a4f56ebac 100644
--- a/module/issue/model.php
+++ b/module/issue/model.php
@@ -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.
*
diff --git a/module/program/lang/zh-cn.php b/module/program/lang/zh-cn.php
index 4104d58604..dce172f3dc 100644
--- a/module/program/lang/zh-cn.php
+++ b/module/program/lang/zh-cn.php
@@ -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'] = '元';
diff --git a/module/weekly/control.php b/module/weekly/control.php
new file mode 100644
index 0000000000..cd392a4b39
--- /dev/null
+++ b/module/weekly/control.php
@@ -0,0 +1,47 @@
+
+ * @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();
+ }
+}
diff --git a/module/weekly/lang/zh-cn.php b/module/weekly/lang/zh-cn.php
new file mode 100644
index 0000000000..b21a2a2fd0
--- /dev/null
+++ b/module/weekly/lang/zh-cn.php
@@ -0,0 +1,29 @@
+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%)';
diff --git a/module/weekly/model.php b/module/weekly/model.php
new file mode 100644
index 0000000000..4f8a7df181
--- /dev/null
+++ b/module/weekly/model.php
@@ -0,0 +1,356 @@
+
+ * @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 = "
";
+ $selectHtml .= html::a('###', $this->lang->weekly->common . $this->lang->colon . $program->name, '', "class='btn'");
+ $selectHtml .= '
';
+
+ $selectHtml .= "
';
+ 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 '';
+ }
+}
diff --git a/module/weekly/view/index.html.php b/module/weekly/view/index.html.php
new file mode 100644
index 0000000000..f745dbd3b2
--- /dev/null
+++ b/module/weekly/view/index.html.php
@@ -0,0 +1,186 @@
+
+ * @package ZenTaoPMS
+ * @version $Id: index.html.php 5094 2013-07-10 08:46:15Z chencongzhi520@gmail.com $
+ */
+?>
+
+
+
+
+
+
+ | weekly->term;?> |
+ |
+ weekly->master;?> |
+ PM, '');?> |
+
+
+ | weekly->program;?> |
+ name;?> |
+ weekly->staff;?> |
+ |
+
+
+
weekly->summary;?>
+
+
+ | weekly->progress;?> |
+ |
+ weekly->analysisResult;?> |
+ |
+
+
+ | weekly->pv;?> |
+ |
+ weekly->progress;?> |
+ weekly->getTips('progress', $sv);?> |
+
+
+ | weekly->ev;?> |
+ |
+
+
+ | weekly->ac;?> |
+ |
+
+
+ | weekly->sv;?> |
+ |
+
+
+ | weekly->cv;?> |
+ |
+ weekly->cost;?> |
+ config->custom, 'cost', 1);?>
+ |
+
+
+
weekly->finished;?>
+
+
+
+ | idAB;?> |
+ task->name;?> |
+ task->estStarted;?> |
+ task->deadline;?> |
+ task->realStarted;?> |
+ task->finishedBy;?> |
+
+
+
+
+
+ |
+ id);?>
+ |
+
+ createLink('task', 'view', 'id=' . $task->id), $task->name); ?>
+ |
+ estStarted;?> |
+ deadline;?> |
+ realStarted;?> |
+ finishedBy);?> |
+
+
+
+
+
+
weekly->postponed;?>
+
+
+
+ | idAB;?> |
+ task->name;?> |
+ task->assignedTo;?> |
+ task->estStarted;?> |
+ task->deadline;?> |
+ task->realStarted;?> |
+ task->progress;?> |
+
+
+
+
+
+ |
+ id);?>
+ |
+
+ createLink('task', 'view', 'id=' . $task->id), $task->name); ?>
+ |
+ assignedTo);?> |
+ estStarted;?> |
+ deadline;?> |
+ realStarted;?> |
+ progress;?>% |
+
+
+
+
+
+
weekly->nextWeek;?>
+
+
+
+ | idAB;?> |
+ task->name;?> |
+ task->assignedTo;?> |
+ task->estStarted;?> |
+ task->deadline;?> |
+
+
+
+
+
+ |
+ id);?>
+ |
+
+ createLink('task', 'view', 'id=' . $task->id), $task->name); ?>
+ |
+ assignedTo);?> |
+ estStarted;?> |
+ deadline;?> |
+
+
+
+
+
+
weekly->workloadByType;?>
+
+
+
+ | task->type;?> |
+ task->typeList as $type => $name):?>
+
+ |
+
+ weekly->total;?> |
+
+
+
+
+ | weekly->workload;?> |
+
+ task->typeList as $type => $name):?>
+
+
+ |
+
+
+
+ |
+
+
+
+
+
+
+
diff --git a/module/workestimation/lang/zh-cn.php b/module/workestimation/lang/zh-cn.php
index 701f61f99b..17889a4a82 100644
--- a/module/workestimation/lang/zh-cn.php
+++ b/module/workestimation/lang/zh-cn.php
@@ -1,5 +1,6 @@
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 = "当前项目实际规模:
%s{$lang->hourCommon} 使用";
From a39e00876e08cf5be6ece0a2bc44243ad2f4080f Mon Sep 17 00:00:00 2001
From: leiyong <1549684884@qq.com>
Date: Thu, 20 Aug 2020 11:13:07 +0800
Subject: [PATCH 2/4] * Merger code.
---
db/update20.0.sql | 2 +-
module/block/control.php | 93 +++++++++++++++++++
module/block/lang/zh-cn.php | 29 ++++++
module/block/view/scrumdynamicblock.html.php | 0
module/block/view/scrumoverallblock.html.php | 0
module/block/view/scrumproductblock.html.php | 0
module/block/view/scrumprogressblock.html.php | 0
module/block/view/scrumprojectblock.html.php | 0
module/block/view/scrumroadmapblock.html.php | 0
module/block/view/scrumtestblock.html.php | 54 +++++++++++
module/common/lang/zh-cn.php | 4 +
module/program/control.php | 1 +
12 files changed, 182 insertions(+), 1 deletion(-)
create mode 100644 module/block/view/scrumdynamicblock.html.php
create mode 100644 module/block/view/scrumoverallblock.html.php
create mode 100644 module/block/view/scrumproductblock.html.php
create mode 100644 module/block/view/scrumprogressblock.html.php
create mode 100644 module/block/view/scrumprojectblock.html.php
create mode 100644 module/block/view/scrumroadmapblock.html.php
create mode 100644 module/block/view/scrumtestblock.html.php
diff --git a/db/update20.0.sql b/db/update20.0.sql
index 5e06cbc15a..bdf5405cfd 100644
--- a/db/update20.0.sql
+++ b/db/update20.0.sql
@@ -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,
diff --git a/module/block/control.php b/module/block/control.php
index c0a463d030..1ce25ab946 100644
--- a/module/block/control.php
+++ b/module/block/control.php
@@ -1398,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);
+ }
}
diff --git a/module/block/lang/zh-cn.php b/module/block/lang/zh-cn.php
index f23dba8fde..4993f75515 100644
--- a/module/block/lang/zh-cn.php
+++ b/module/block/lang/zh-cn.php
@@ -101,6 +101,35 @@ $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;
+>>>>>>> Stashed changes
+
$lang->block->default['product']['1']['title'] = $lang->productCommon . '统计';
$lang->block->default['product']['1']['block'] = 'statistic';
$lang->block->default['product']['1']['grid'] = 8;
diff --git a/module/block/view/scrumdynamicblock.html.php b/module/block/view/scrumdynamicblock.html.php
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/module/block/view/scrumoverallblock.html.php b/module/block/view/scrumoverallblock.html.php
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/module/block/view/scrumproductblock.html.php b/module/block/view/scrumproductblock.html.php
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/module/block/view/scrumprogressblock.html.php b/module/block/view/scrumprogressblock.html.php
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/module/block/view/scrumprojectblock.html.php b/module/block/view/scrumprojectblock.html.php
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/module/block/view/scrumroadmapblock.html.php b/module/block/view/scrumroadmapblock.html.php
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/module/block/view/scrumtestblock.html.php b/module/block/view/scrumtestblock.html.php
new file mode 100644
index 0000000000..b4327a7afb
--- /dev/null
+++ b/module/block/view/scrumtestblock.html.php
@@ -0,0 +1,54 @@
+
+ * @package block
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+
+block->emptyTip;?>
+
+
+
+
+
+
+ | idAB?> |
+ testtask->product;?> |
+
+ testtask->name;?> |
+
+ testtask->project . '/' . $lang->testtask->build;?> |
+
+ testtask->begin;?> |
+ testtask->end;?> |
+
+
+
+
+ get->entry}'" : '';
+ $viewLink = $this->createLink('testtask', 'view', "testtaskID={$testtask->id}");
+ ?>
+ >
+
+ | id);?> |
+ productName?> |
+
+ name?> |
+
+ buildName?>'>projectName . '/' . $testtask->buildName?> |
+
+ begin?> |
+ end?> |
+
+
+
+
+
+
diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php
index 619acf0265..306de7d789 100755
--- a/module/common/lang/zh-cn.php
+++ b/module/common/lang/zh-cn.php
@@ -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();
diff --git a/module/program/control.php b/module/program/control.php
index de0afec313..8a41d17aea 100644
--- a/module/program/control.php
+++ b/module/program/control.php
@@ -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();
}
From ad0f2a65a9e21a5570e2c8f3ab7201a6b4d6a8d0 Mon Sep 17 00:00:00 2001
From: leiyong <1549684884@qq.com>
Date: Thu, 20 Aug 2020 11:15:31 +0800
Subject: [PATCH 3/4] * Merger code.
---
module/block/lang/zh-cn.php | 1 -
1 file changed, 1 deletion(-)
diff --git a/module/block/lang/zh-cn.php b/module/block/lang/zh-cn.php
index 4993f75515..4fa18ec0bd 100644
--- a/module/block/lang/zh-cn.php
+++ b/module/block/lang/zh-cn.php
@@ -128,7 +128,6 @@ $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;
->>>>>>> Stashed changes
$lang->block->default['product']['1']['title'] = $lang->productCommon . '统计';
$lang->block->default['product']['1']['block'] = 'statistic';
From d4950444ad3568c277e5909a89c012be265b41ba Mon Sep 17 00:00:00 2001
From: leiyong <1549684884@qq.com>
Date: Thu, 20 Aug 2020 13:36:25 +0800
Subject: [PATCH 4/4] * Adjust sql.
---
db/update20.0.sql | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/db/update20.0.sql b/db/update20.0.sql
index bdf5405cfd..c86ef8bd2d 100644
--- a/db/update20.0.sql
+++ b/db/update20.0.sql
@@ -272,16 +272,16 @@ CREATE TABLE `zt_taskspec` (
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,
+ `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,
+ `progress` varchar(255) NOT NULL,
+ `workload` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `week` (`program`,`weekStart`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;