diff --git a/config/zentaopms.php b/config/zentaopms.php index 94c4e33c72..082f797671 100644 --- a/config/zentaopms.php +++ b/config/zentaopms.php @@ -138,6 +138,7 @@ define('TABLE_STORY', '`' . $config->db->prefix . 'story`'); define('TABLE_STORYSPEC', '`' . $config->db->prefix . 'storyspec`'); define('TABLE_STORYREVIEW', '`' . $config->db->prefix . 'storyreview`'); define('TABLE_STORYSTAGE', '`' . $config->db->prefix . 'storystage`'); +define('TABLE_STORYESTIMATE', '`' . $config->db->prefix . 'storyestimate`'); define('TABLE_PRODUCTPLAN', '`' . $config->db->prefix . 'productplan`'); define('TABLE_PLANSTORY', '`' . $config->db->prefix . 'planstory`'); define('TABLE_RELEASE', '`' . $config->db->prefix . 'release`'); diff --git a/db/update15.0.sql b/db/update15.0.sql index 3a2a4cfdc2..e5c4f709dd 100644 --- a/db/update15.0.sql +++ b/db/update15.0.sql @@ -8,6 +8,16 @@ CREATE TABLE IF NOT EXISTS `zt_storyreview` ( UNIQUE KEY `story` (`story`,`version`,`reviewer`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; +-- DROP TABLE IF EXISTS `zt_storyestimate`; +CREATE TABLE IF NOT EXISTS `zt_storyestimate` ( + `story` mediumint(9) NOT NULL, + `round` smallint(6) NOT NULL, + `estimate` text NOT NULL, + `average` float(10,2) NOT NULL, + `openedBy` varchar(30) NOT NULL, + `openedDate` datetime NOT NULL, + UNIQUE KEY `story` (`story`,`round`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; ALTER TABLE `zt_project` CHANGE `lifetime` `lifetime` char(30) NOT NULL DEFAULT ''; ALTER TABLE `zt_story` ADD `category` varchar(30) NOT NULL DEFAULT 'feature' AFTER `type`; diff --git a/db/zentao.sql b/db/zentao.sql index fbc177d8aa..b518be2281 100644 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -872,6 +872,16 @@ CREATE TABLE IF NOT EXISTS `zt_storyreview` ( `reviewDate` datetime NOT NULL, UNIQUE KEY `story` (`story`,`version`,`reviewer`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; +-- DROP TABLE IF EXISTS `zt_storyestimate`; +CREATE TABLE IF NOT EXISTS `zt_storyestimate` ( + `story` mediumint(9) NOT NULL, + `round` smallint(6) NOT NULL, + `estimate` text NOT NULL, + `average` float(10,2) NOT NULL, + `openedBy` varchar(30) NOT NULL, + `openedDate` datetime NOT NULL, + UNIQUE KEY `story` (`story`,`round`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; -- DROP TABLE IF EXISTS `zt_storystage`; CREATE TABLE IF NOT EXISTS `zt_storystage` ( `story` mediumint(8) unsigned NOT NULL, diff --git a/module/action/model.php b/module/action/model.php index 5a2b109230..f7353f69fe 100755 --- a/module/action/model.php +++ b/module/action/model.php @@ -65,6 +65,13 @@ class actionModel extends model $action->project = ($actionType == 'unlinkedfromproject' or $actionType == 'linked2project') ? (int)$extra : (int)$relation['project']; $action->execution = ($actionType == 'unlinkedfromexecution' or $actionType == 'linked2execution') ? (int)$extra : (int)$relation['execution']; + if($objectType == 'story' and ($actionType == 'linked2build' or $actionType == 'unlinkedfrombuild')) + { + $build = $this->dao->select('project,execution')->from(TABLE_BUILD)->where('id')->eq((int)$extra)->fetch(); + $action->project = $build->project; + $action->execution = $build->execution; + } + if($objectType == 'whitelist' and $extra == 'product') $action->product = $objectID; if($objectType == 'whitelist' and $extra == 'project') $action->project = $objectID; if($objectType == 'whitelist' and ($extra == 'sprint' or $extra == 'stage')) $action->execution = $objectID; @@ -181,7 +188,7 @@ class actionModel extends model } /* Only process these object types. */ - if(strpos(',story,productplan,release,task,build,bug,case,testtask,doc,issue,risk,repo,team,', ",{$objectType},") !== false) + if(strpos(',story,productplan,release,task,build,bug,case,testtask,doc,issue,risk,team,', ",{$objectType},") !== false) { if(!isset($this->config->objectTables[$objectType])) return $emptyRecord; @@ -196,11 +203,7 @@ class actionModel extends model $record = $this->dao->select($fields)->from($this->config->objectTables[$objectType])->where('id')->eq($objectID)->fetch(); /* Process story, release and task. */ - if($objectType == 'story') - { - $record->project = $this->dao->select('project')->from(TABLE_PROJECTSTORY)->where('story')->eq($objectID)->orderBy('project_desc')->limit(1)->fetch('project'); - $record->execution = $this->dao->select('project')->from(TABLE_PROJECTSTORY)->where('story')->eq($objectID)->orderBy('project_desc')->limit(1)->fetch('project'); - } + if($objectType == 'story') $record->project = $this->dao->select('project')->from(TABLE_PROJECTSTORY)->where('story')->eq($objectID)->orderBy('project_desc')->limit(1)->fetch('project'); if($objectType == 'release') $record->project = $this->dao->select('project')->from(TABLE_BUILD)->where('id')->eq($record->build)->fetch('project'); if($objectType == 'team') { diff --git a/module/execution/control.php b/module/execution/control.php index 1ccc85d81e..158d6b2638 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -2694,6 +2694,36 @@ class execution extends control } } + /** + * Story estimate. + * + * @param int $executionID + * @param int $storyID + * @param int $round + * @access public + * @return void + */ + public function storyEstimate($executionID, $storyID, $round = 0) + { + $this->loadModel('story'); + + if($_POST) + { + $this->story->saveEstimateInfo($storyID); + $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('execution', 'storyEstimate', "executionID=$executionID&storyID=$storyID"))); + } + $estimateInfo = $this->story->getEstimateInfo($storyID, $round); + + $this->view->estimateInfo = $estimateInfo; + $this->view->round = !empty($estimateInfo->round) ? $estimateInfo->round : 0; + $this->view->rounds = $this->story->getEstimateRounds($storyID); + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + $this->view->team = $this->execution->getTeamMembers($executionID); + $this->view->executionID = $executionID; + $this->view->storyID = $storyID; + $this->display(); + } + /** * All execution. * diff --git a/module/execution/js/storyestimate.js b/module/execution/js/storyestimate.js new file mode 100644 index 0000000000..a34bfb9a40 --- /dev/null +++ b/module/execution/js/storyestimate.js @@ -0,0 +1,36 @@ +$('.new-estimate input').keyup(function() +{ + computeAverage(); +}) + +function computeAverage() +{ + var summary = 0; + var count = 0; + var average = 0; + $('.new-estimate').each(function() + { + var value = $(this).find('input').val(); + if(!value) return false; + value = parseFloat(value); + if(isNaN(value)) value = 0; + summary += value; + count += 1; + }) + + if(count) average = summary / count; + $('#average').val(average.toFixed(2)); + $('#showAverage').html(average.toFixed(2)); +} + +function showNewEstimate() +{ + $('.th-new-estimate').removeClass('hide'); + $('.new-estimate').removeClass('hide'); + $('.form-actions').removeClass('hide'); +} + +function selectRound(round) +{ + location.href = createLink('execution', 'storyEstimate', 'executionID=' + executionID + '&storyID=' + storyID + '&round=' + round); +} diff --git a/module/execution/lang/de.php b/module/execution/lang/de.php index 87ed04529d..b0e44956c8 100644 --- a/module/execution/lang/de.php +++ b/module/execution/lang/de.php @@ -80,6 +80,11 @@ $lang->execution->product = $lang->execution->products; $lang->execution->readjustTime = 'Start und Ende anpassen'; $lang->execution->readjustTask = 'Fälligkeit der Aufgabe anpassen'; $lang->execution->effort = 'Aufwand'; +$lang->execution->storyEstimate = 'Story Estimate'; +$lang->execution->newEstimate = 'New Estimate'; +$lang->execution->reestimate = 'Reestimate'; +$lang->execution->selectRound = 'Select Round'; +$lang->execution->average = 'Average'; $lang->execution->relatedMember = 'Teammitglieder'; $lang->execution->watermark = 'Exported by ZenTao'; $lang->execution->burnXUnit = '(Date)'; diff --git a/module/execution/lang/en.php b/module/execution/lang/en.php index f68dd5d4bb..347830d1b7 100644 --- a/module/execution/lang/en.php +++ b/module/execution/lang/en.php @@ -80,6 +80,11 @@ $lang->execution->product = $lang->execution->products; $lang->execution->readjustTime = "Adjust {$lang->executionCommon} Begin and End"; $lang->execution->readjustTask = 'Adjust Task Begin and End'; $lang->execution->effort = 'Effort'; +$lang->execution->storyEstimate = 'Story Estimate'; +$lang->execution->newEstimate = 'New Estimate'; +$lang->execution->reestimate = 'Reestimate'; +$lang->execution->selectRound = 'Select Round'; +$lang->execution->average = 'Average'; $lang->execution->relatedMember = 'Team'; $lang->execution->watermark = 'Exported by ZenTao'; $lang->execution->burnXUnit = '(Date)'; diff --git a/module/execution/lang/fr.php b/module/execution/lang/fr.php index 70eb03758b..2c52374fcb 100644 --- a/module/execution/lang/fr.php +++ b/module/execution/lang/fr.php @@ -80,6 +80,11 @@ $lang->execution->product = $lang->execution->products; $lang->execution->readjustTime = "Ajuster Début et Fin du {$lang->executionCommon}"; $lang->execution->readjustTask = 'Ajuster Début et Fin de la Tâche'; $lang->execution->effort = 'Effort'; +$lang->execution->storyEstimate = 'Story Estimate'; +$lang->execution->newEstimate = 'New Estimate'; +$lang->execution->reestimate = 'Reestimate'; +$lang->execution->selectRound = 'Select Round'; +$lang->execution->average = 'Average'; $lang->execution->relatedMember = 'Equipe'; $lang->execution->watermark = 'Exporté par ZenTao'; $lang->execution->burnXUnit = '(Date)'; diff --git a/module/execution/lang/vi.php b/module/execution/lang/vi.php index cdd7cb6076..60dc6326c8 100644 --- a/module/execution/lang/vi.php +++ b/module/execution/lang/vi.php @@ -80,6 +80,11 @@ $lang->execution->product = $lang->execution->products; $lang->execution->readjustTime = "Điều chỉnh {$lang->executionCommon} Thời gian"; $lang->execution->readjustTask = 'Điều chỉnh nhiệm vụ Thời gian'; $lang->execution->effort = 'Chấm công'; +$lang->execution->storyEstimate = 'Story Estimate'; +$lang->execution->newEstimate = 'New Estimate'; +$lang->execution->reestimate = 'Reestimate'; +$lang->execution->selectRound = 'Select Round'; +$lang->execution->average = 'Average'; $lang->execution->relatedMember = 'Đội nhóm'; $lang->execution->watermark = 'Đã xuất bởi ZenTao'; $lang->execution->burnXUnit = '(Date)'; diff --git a/module/execution/lang/zh-cn.php b/module/execution/lang/zh-cn.php index 503582f9aa..fd1c351c39 100644 --- a/module/execution/lang/zh-cn.php +++ b/module/execution/lang/zh-cn.php @@ -80,6 +80,11 @@ $lang->execution->product = $lang->execution->products; $lang->execution->readjustTime = "调整{$lang->executionCommon}起止时间"; $lang->execution->readjustTask = '顺延任务的起止时间'; $lang->execution->effort = '日志'; +$lang->execution->storyEstimate = '需求估算'; +$lang->execution->newEstimate = '新一轮估算'; +$lang->execution->reestimate = '重新估算'; +$lang->execution->selectRound = '选择轮次'; +$lang->execution->average = '平均值'; $lang->execution->relatedMember = '相关成员'; $lang->execution->watermark = '由禅道导出'; $lang->execution->burnXUnit = '(日期)'; diff --git a/module/execution/view/story.html.php b/module/execution/view/story.html.php index a3f7e33d25..2dd48cd640 100644 --- a/module/execution/view/story.html.php +++ b/module/execution/view/story.html.php @@ -196,7 +196,7 @@