diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index 61ba0959fd..5d9fedcf32 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -924,7 +924,7 @@ $lang->menu->scrum->ci = '代码|repo|browse'; $lang->menu->scrum->projectbuild = array('link' => '版本|projectbuild|browse|project={PROJECT}'); $lang->menu->scrum->projectrelease = array('link' => '发布|projectrelease|browse'); $lang->menu->scrum->other = array('link' => '其他|project|other', 'class' => 'dropdown dropdown-hover waterfall-list', 'subModule' => 'issue,risk,stakeholder'); -$lang->menu->scrum->projectsetting = array('link' => '设置|project|setting', 'class' => 'dropdown dropdown-hover waterfall-list'); +$lang->menu->scrum->projectsetting = array('link' => '设置|program|prjview|project={PROJECT}'); $lang->scrum = new stdclass(); $lang->scrum->subMenu = new stdclass(); @@ -933,8 +933,8 @@ $lang->scrum->subMenu->other->issue = array('link' => '问题|issue|browse $lang->scrum->subMenu->other->risk = array('link' => '风险|risk|browse|', 'subModule' => 'risk'); $lang->scrum->subMenu->other->stakeholder = array('link' => '干系人|stakeholder|browse|', 'subModule' => 'stakeholder'); -$lang->scrum->subMenu->projectsetting = new stdclass(); -$lang->scrum->subMenu->projectsetting->program = '项目|program|PRJEdit|'; +$lang->scrum->setMenu = new stdclass(); +$lang->scrum->setMenu->view = array('link' => '概况|program|prjview|project={PROJECT}'); /* Waterfall menu. */ $lang->menu->waterfall = new stdclass(); @@ -950,7 +950,7 @@ $lang->menu->waterfall->qa = '测试|qa|index'; $lang->menu->waterfall->projectrelease = array('link' => '发布|projectrelease|browse'); $lang->menu->waterfall->projectbuild = array('link' => '版本|projectbuild|browse|project={PROJECT}'); $lang->menu->waterfall->other = array('link' => '其他|project|other', 'class' => 'dropdown dropdown-hover waterfall-list', 'subModule' => 'issue,risk,stakeholder,nc'); -$lang->menu->waterfall->projectsetting = array('link' => '设置|project|setting', 'class' => 'dropdown dropdown-hover waterfall-list', 'subModule' => 'workestimation,durationestimation,budget,pssp'); +$lang->menu->waterfall->projectsetting = array('link' => '设置|program|prjview|project={PROJECT}', 'subModule' => 'workestimation,durationestimation,budget,pssp'); $lang->waterfall = new stdclass(); $lang->waterfall->subMenu = new stdclass(); @@ -959,9 +959,11 @@ $lang->waterfall->subMenu->other->issue = array('link' => '问题|issue|browse|' $lang->waterfall->subMenu->other->risk = array('link' => '风险|risk|browse|', 'subModule' => 'risk'); $lang->waterfall->subMenu->other->stakeholder = array('link' => '干系人|stakeholder|browse|', 'subModule' => 'stakeholder'); -$lang->waterfall->subMenu->projectsetting = new stdclass(); -$lang->waterfall->subMenu->projectsetting->workestimation = array('link' => '估算|workestimation|index|program=%s', 'subModule' => 'durationestimation,budget'); -$lang->waterfall->subMenu->projectsetting->program = '项目|program|PRJEdit|'; +$lang->waterfall->setMenu = new stdclass(); +$lang->waterfall->setMenu->view = array('link' => '概况|program|prjview|project={PROJECT}'); +$lang->waterfall->setMenu->workestimation = '工作量估算|workestimation|index|project={PROJECT}'; +$lang->waterfall->setMenu->duration = array('link' => '工期估算|durationestimation|index|project={PROJECT}', 'subModule' => 'durationestimation'); +$lang->waterfall->setMenu->budget = array('link' => '费用估算|budget|summary|', 'subModule' => 'budget'); $lang->waterfallproduct = new stdclass(); $lang->workestimation = new stdclass(); @@ -998,16 +1000,13 @@ $lang->waterfallproduct->menu = new stdclass(); $lang->durationestimation->menu = new stdclass(); $lang->projectstory->menu = new stdclass(); +$lang->workestimation->menu = $lang->waterfall->setMenu; +$lang->durationestimation->menu = $lang->waterfall->setMenu; +$lang->budget->menu = $lang->waterfall->setMenu; + $lang->stakeholder->menu->list = array('link' => '干系人列表|stakeholder|browse|', 'alias' => 'create,edit,view,batchcreate'); $lang->stakeholder->menu->issue = array('link' => '问题管理|stakeholder|issue|'); -$lang->workestimation->menu->index = '工作量估算|workestimation|index|project={PROJECT}'; -$lang->workestimation->menu->duration = array('link' => '工期估算|durationestimation|index|project={PROJECT}', 'subModule' => 'durationestimation'); -$lang->workestimation->menu->budget = array('link' => '费用估算|budget|summary|', 'subModule' => 'budget'); - -$lang->durationestimation->menu = $lang->workestimation->menu; -$lang->budget->menu = $lang->workestimation->menu; - $lang->programplan->menu->gantt = array('link' => '甘特图|programplan|browse|programID={PROJECT}&productID={PRODUCT}&type=gantt'); $lang->programplan->menu->lists = array('link' => '阶段列表|programplan|browse|programID={PROJECT}&productID={PRODUCT}&type=lists', 'alias' => 'create'); diff --git a/module/common/model.php b/module/common/model.php index bf672888f3..2cdcbc65b5 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -631,6 +631,12 @@ class commonModel extends model /* If program, return.*/ if($moduleName == 'program' and strpos($methodName, 'prj') !== false) $lang->program->menu = $lang->PRJ->menu; + if($moduleName == 'program' and $methodName == 'prjview') + { + $moduleIndex = array_search('program', $lang->noMenuModule); + if($moduleIndex !== false) unset($lang->noMenuModule[$moduleIndex]); + $lang->navGroup->program = 'project'; + } if($moduleName == 'product' and $methodName == 'create') return; /* Set the main main menu. */ @@ -696,25 +702,7 @@ class commonModel extends model if(isset($subMenuItem->link['vars'])) $subParams = $subMenuItem->link['vars']; $subLink = helper::createLink($subModule, $subMethod, $subParams); - if($subMenuItem->name == 'program') - { - /* Print program sub menu.*/ - global $dbh; - $program = $dbh->query("SELECT * FROM " . TABLE_PROJECT . " WHERE `id` = '{$app->session->PRJ}'")->fetch(); - $subActive .= 'dropdown-submenu'; - $subLink = 'javascript:;'; - $subProgram .= ""; - } - if($currentModule == strtolower($subModule) && $currentMethod == strtolower($subMethod)) $subActive = 'active'; - $subMenu .= "
  • " . html::a($subLink, $subLabel) . $subProgram . '
  • '; } @@ -725,7 +713,7 @@ class commonModel extends model } /* Disable links to more buttons. */ - if($menuItem->name == 'projectsetting' || $menuItem->name == 'other') $link='javascript:void(0);'; + if($menuItem->name == 'other') $link='javascript:void(0);'; $menuItemHtml = "
  • " . html::a($link, $label, $target) . $subMenu . "
  • \n"; @@ -779,7 +767,7 @@ class commonModel extends model $moduleName = $app->rawModule; $methodName = $app->rawMethod; $mainMenu = $moduleName; - if($moduleName == 'program') return; + if($moduleName == 'program' and $methodName != 'prjview') return; if(isset($lang->menugroup->$moduleName)) $mainMenu = $lang->menugroup->$moduleName; /* Set main menu by group. */ @@ -787,7 +775,7 @@ class commonModel extends model if($moduleName == 'admin') return; if($group == 'repo' || $group == 'ops' || $group == 'feedback') return; if($group == 'my') self::getMyModuleMenu($moduleName, $methodName); - if($group == 'project') self::getProgramModuleMenu($moduleName); + if($group == 'project') self::getProgramModuleMenu($moduleName, $methodName); if($group == 'product') { $lang->product->menu = $lang->product->setMenu; @@ -1744,7 +1732,7 @@ EOD; $method = strtolower($method); /* More menus do not require permission control. */ - if($module == 'project' && ($method == 'other' || $method == 'setting')) return true; + if($module == 'project' && $method == 'other') return true; /* Check the parent object is closed. */ if(!empty($method) and strpos('close|batchclose', $method) === false and !commonModel::canBeChanged($module, $object)) return false; @@ -2418,21 +2406,24 @@ EOD; * Get program module menu by model. * * @param varchar $moduleName + * @param varchar $methodName * @static * @access public * @return string */ - public static function getProgramModuleMenu($moduleName) + public static function getProgramModuleMenu($moduleName, $methodName) { global $app, $lang, $dbh; $program = $dbh->query("SELECT * FROM " . TABLE_PROJECT . " WHERE `id` = '{$app->session->PRJ}'")->fetch(); if(empty($program)) return; if($program->model == 'waterfall') { + if($moduleName == 'program' and $methodName == 'prjview') $lang->program->menu = $lang->waterfall->setMenu; $lang->$moduleName->menu = self::processMenuVars($lang->$moduleName->menu); } if($program->model == 'scrum') { + if($moduleName == 'program' and $methodName == 'prjview') $lang->program->menu = $lang->scrum->setMenu; unset($lang->stakeholder->menu->issue); unset($lang->stakeholder->menu->plan); unset($lang->stakeholder->menu->expectation); diff --git a/module/product/model.php b/module/product/model.php index 2420ee0daa..13bffd140b 100644 --- a/module/product/model.php +++ b/module/product/model.php @@ -323,7 +323,7 @@ class productModel extends model */ public function getProductsByProject($projectID, $status = 'all') { - return $this->dao->select('t2.*') + return $this->dao->select('t1.branch, t1.plan, t2.*') ->from(TABLE_PROJECTPRODUCT)->alias('t1') ->leftJoin(TABLE_PRODUCT)->alias('t2') ->on('t1.product = t2.id') diff --git a/module/program/config.php b/module/program/config.php index d19cbe3621..13fefe21ce 100644 --- a/module/program/config.php +++ b/module/program/config.php @@ -16,6 +16,7 @@ $config->program->editor->prjclose = array('id' => 'comment', 'tools' => 'sim $config->program->editor->prjsuspend = array('id' => 'comment', 'tools' => 'simpleTools'); $config->program->editor->prjstart = array('id' => 'comment', 'tools' => 'simpleTools'); $config->program->editor->prjactivate = array('id' => 'comment', 'tools' => 'simpleTools'); +$config->program->editor->prjview = array('id' => 'comment', 'tools' => 'simpleTools'); $config->program->list = new stdclass(); $config->program->list->exportFields = 'id,name,code,template,product,status,begin,end,budget,PM,end,desc'; diff --git a/module/program/control.php b/module/program/control.php index 26964cf0eb..bb93d9c6b0 100644 --- a/module/program/control.php +++ b/module/program/control.php @@ -1023,6 +1023,40 @@ class program extends control $this->display(); } + /** + * View a project. + * + * @param int $projectID + * @access public + * @return void + */ + public function PRJView($projectID = 0) + { + $this->lang->navGroup->program = 'project'; + $this->app->loadLang('bug'); + + $products = $this->loadModel('product')->getProductsByProject($projectID);; + $linkedBranches = array(); + foreach($products as $product) + { + if($product->branch) $linkedBranches[$product->branch] = $product->branch; + } + + $this->view->title = $this->lang->program->PRJView; + $this->view->position = $this->lang->program->PRJView; + $this->view->projectID = $projectID; + $this->view->project = $this->program->getPRJByID($projectID); + $this->view->products = $products; + $this->view->actions = $this->loadModel('action')->getList('project', $projectID); + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + $this->view->statData = $this->program->getPRJStatData($projectID); + $this->view->workhour = $this->program->getPRJWorkhour($projectID); + $this->view->planGroup = $this->loadModel('project')->getPlans($products);; + $this->view->branchGroups = $this->loadModel('branch')->getByProducts(array_keys($products), '', $linkedBranches); + + $this->display(); + } + /** * Project browse groups. * diff --git a/module/program/css/prjview.css b/module/program/css/prjview.css new file mode 100644 index 0000000000..7f83fa80fa --- /dev/null +++ b/module/program/css/prjview.css @@ -0,0 +1 @@ +.row > .col-sm-12:first-child {padding-bottom: 20px;} diff --git a/module/program/lang/zh-cn.php b/module/program/lang/zh-cn.php index a004d49276..8f2e4a9990 100644 --- a/module/program/lang/zh-cn.php +++ b/module/program/lang/zh-cn.php @@ -5,6 +5,7 @@ $lang->program->PRJIndex = '项目仪表盘'; $lang->program->PRJHome = '项目主页'; $lang->program->PRJCreate = '创建项目'; $lang->program->PRJEdit = '编辑项目'; +$lang->program->PRJView = '项目概况'; $lang->program->PRJBatchEdit = '批量编辑'; $lang->program->PRJBrowse = '项目列表'; $lang->program->PRJAll = '所有项目'; diff --git a/module/program/model.php b/module/program/model.php index 09091cc9dc..7d3354779a 100644 --- a/module/program/model.php +++ b/module/program/model.php @@ -810,7 +810,7 @@ class programModel extends model */ public function getPRJSwitcher($projectID, $currentModule, $currentMethod) { - if($currentModule == 'program' && $currentMethod != 'index') return; + if($currentModule == 'program' && ($currentMethod != 'index' && $currentMethod != 'prjview')) return; $this->loadModel('project'); $currentProjectName = $this->lang->program->common; @@ -838,7 +838,7 @@ class programModel extends model */ public function getPRJMainAction($module, $method) { - if($module == 'program' and $method != 'index') return ''; + if($module == 'program' and ($method != 'index' and $method != 'prjview')) return ''; return common::hasPriv('program', 'prjbrowse') ? html::a(helper::createLink('program', 'prjbrowse'), $this->lang->moreLink, '', "class='btn btn-link'") : ''; } @@ -1136,6 +1136,69 @@ class programModel extends model return $stats; } + /** + * Get project workhour info. + * + * @param int $projectID + * @access public + * @return void + */ + public function getPRJWorkhour($projectID) + { + $executions = $this->loadModel('project')->getExecutionPairs($projectID); + + $total = $this->dao->select(' + ROUND(SUM(estimate), 2) AS totalEstimate, + ROUND(SUM(consumed), 2) AS totalConsumed, + ROUND(SUM(`left`), 2) AS totalLeft') + ->from(TABLE_TASK) + ->where('project')->in(array_keys($executions)) + ->andWhere('deleted')->eq(0) + ->andWhere('parent')->lt(1) + ->fetch(); + $closedTotalLeft = $this->dao->select('ROUND(SUM(`left`), 2) AS totalLeft')->from(TABLE_TASK) + ->where('project')->in(array_keys($executions)) + ->andWhere('deleted')->eq(0) + ->andWhere('parent')->lt(1) + ->andWhere('status')->in('closed,cancel') + ->fetch('totalLeft'); + + $workhour = new stdclass(); + $workhour->totalHours = $this->dao->select('sum(days * hours) AS totalHours')->from(TABLE_TEAM)->where('root')->in(array_keys($executions))->andWhere('type')->eq('project')->fetch('totalHours'); + $workhour->totalEstimate = round($total->totalEstimate, 1); + $workhour->totalConsumed = round($total->totalConsumed, 1); + $workhour->totalLeft = round($total->totalLeft - $closedTotalLeft, 1); + + return $workhour; + } + + /** + * Get project stat data . + * + * @param int $projectID + * @access public + * @return void + */ + public function getPRJStatData($projectID) + { + $executions = $this->loadModel('project')->getExecutionPairs($projectID); + $storyCount = $this->dao->select('count(t2.story) as storyCount')->from(TABLE_STORY)->alias('t1') + ->leftJoin(TABLE_PROJECTSTORY)->alias('t2')->on('t1.id = t2.story') + ->where('t2.project')->eq($projectID) + ->andWhere('t1.deleted')->eq(0) + ->fetch('storyCount'); + + $taskCount = $this->dao->select('count(id) as taskCount')->from(TABLE_TASK)->where('project')->in(array_keys($executions))->andWhere('deleted')->eq(0)->fetch('taskCount'); + $bugCount = $this->dao->select('count(id) as bugCount')->from(TABLE_BUG)->where('project')->in(array_keys($executions))->andWhere('deleted')->eq(0)->fetch('bugCount'); + + $statData = new stdclass(); + $statData->storyCount = $storyCount; + $statData->taskCount = $taskCount; + $statData->bugCount = $bugCount; + + return $statData; + } + /** * Get project pairs. * diff --git a/module/program/view/prjview.html.php b/module/program/view/prjview.html.php new file mode 100644 index 0000000000..063d79b8bb --- /dev/null +++ b/module/program/view/prjview.html.php @@ -0,0 +1,166 @@ + + * @package project + * @version $Id: view.html.php 4594 2013-03-13 06:16:02Z wyd621@gmail.com $ + * @link http://www.zentao.net + */ +?> + + +
    +
    +
    +
    +
    +
    +

    id;?> code;?> name;?>

    +
    +

    desc;?>

    +

    + deleted):?> + project->deleted;?> + + program->PRJLifeTimeList, $project->lifetime);?> + delay)):?> + project->delayed;?> + + processStatus('project', $project);?> + +

    +
    +
    +
    +
    + project->manageProducts;?> + id", '', '', "class='btn btn-link pull-right muted'");?> +
    +
    +
    + $product):?> + branch]) ? '/' . $branchGroups[$productID][$product->branch] : '';?> +
    + createLink('product', 'browse', "productID=$productID&branch=$product->branch"), " " . $product->name . $branchName);?> +
    + +
    +
    +
    +
    +
    project->linkPlan;?>
    +
    +
    + $product):?> + plan])):?> +
    createLink('productplan', 'view', "planID={$product->plan}"), $product->name . '/' . $planGroups[$productID][$product->plan]);?>
    + + +
    +
    +
    +
    +
    project->lblStats;?>
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + totalConsumed + $workhour->totalLeft) ? floor($workhour->totalConsumed / ($workhour->totalConsumed + $workhour->totalLeft) * 1000) / 1000 * 100 : 0;?> + project->progress;?> percent;?>   +
    +
    +
    +
    project->begin;?>begin;?>project->totalEstimate;?>totalEstimate . $lang->hourCommon;?>
    project->end;?>end;?>project->totalConsumed;?>totalConsumed . $lang->hourCommon;?>
    project->totalDays;?>days;?>project->totalLeft;?>totalLeft . $lang->hourCommon;?>
    project->totalHours;?>totalHours . $lang->hourCommon;?>
    +
    +
    +
    +
    project->basicInfo;?>
    +
    + + + + + + + + + + + +
    story->common;?>storyCount;?>task->common;?>taskCount;?>bug->common;?>bugCount;?>
    +
    +
    +
    +
    project->acl;?>
    +
    +

    project->aclList[$project->acl];?>

    +
    +
    + printExtendFields($project, 'div', "position=right&inForm=0&inCell=1");?> +
    +
    +
    + + createLink('action', 'comment', "objectType=project&objectID=$project->id");?> + +
    +
    +
    +
    + id"; + common::printBack(inlink('prjbrowse')); + if(!$project->deleted) + { + echo "
    "; + common::printIcon('project', 'start', "projectID=$project->id", $project, 'button', '', '', 'iframe', true); + common::printIcon('project', 'activate', "projectID=$project->id", $project, 'button', '', '', 'iframe', true); + common::printIcon('project', 'putoff', "projectID=$project->id", $project, 'button', '', '', 'iframe', true); + common::printIcon('project', 'suspend', "projectID=$project->id", $project, 'button', '', '', 'iframe', true); + common::printIcon('project', 'close', "projectID=$project->id", $project, 'button', '', '', 'iframe', true); + + echo $this->buildOperateMenu($project, 'view'); + + echo "
    "; + common::printIcon('project', 'edit', $params, $project); + common::printIcon('project', 'delete', $params, $project, 'button', 'trash', 'hiddenwin'); + } + ?> +
    +
    +
    +
    + +
    + +