diff --git a/db/update18.10.sql b/db/update18.10.sql index f202517d85..ef8a724c1a 100644 --- a/db/update18.10.sql +++ b/db/update18.10.sql @@ -1,3 +1,6 @@ ALTER TABLE `zt_demandpool` ADD COLUMN `products` varchar(255) NOT NULL DEFAULT ''; ALTER TABLE `zt_project` ADD COLUMN `parallel` mediumint(9) NOT NULL DEFAULT '0'; ALTER TABLE `zt_demand` CHANGE `product` `product` varchar(255) NOT NULL DEFAULT ''; +ALTER TABLE `zt_story` ADD COLUMN `retractedReason` ENUM('', 'omit', 'other') NOT NULL DEFAULT ''; +ALTER TABLE `zt_story` ADD COLUMN `retractedBy` varchar(255) NOT NULL DEFAULT ''; +ALTER TABLE `zt_story` ADD COLUMN `retractedDate` datetime NOT NULL; diff --git a/module/action/model.php b/module/action/model.php index 94ff20f493..f0c5dae5f0 100755 --- a/module/action/model.php +++ b/module/action/model.php @@ -649,6 +649,11 @@ class actionModel extends model $action->extra = sprintf($this->lang->execution->action->extra, '' . join(', ', $linkedProducts) . ''); } } + elseif($objectType == 'story' && $actionName == 'retracted') + { + $story = $this->loadModel('story')->getById($objectID); + $action->extra = "#{$story->id} {$this->lang->story->title} {$story->title}"; + } $action->history = isset($histories[$actionID]) ? $histories[$actionID] : array(); $actionName = strtolower($action->action); diff --git a/module/group/packagemanager.php b/module/group/packagemanager.php index 7da863ad2f..a50cfa30a5 100644 --- a/module/group/packagemanager.php +++ b/module/group/packagemanager.php @@ -3715,6 +3715,7 @@ $config->group->package->manageDemand->privs['demand-manageTree'] = array('edit $config->group->package->manageDemand->privs['demand-close'] = array('edition' => 'ipd', 'vision' => 'or', 'order' => 180, 'depend' => array('demand-browse', 'demand-view'), 'recommend' => array('demand-activate', 'demand-assignTo', 'demand-batchCreate', 'demand-create', 'demand-edit')); $config->group->package->manageDemand->privs['demand-activate'] = array('edition' => 'ipd', 'vision' => 'or', 'order' => 190, 'depend' => array('demand-browse', 'demand-view'), 'recommend' => array('demand-assignTo', 'demand-batchCreate', 'demand-close', 'demand-create', 'demand-edit')); $config->group->package->manageDemand->privs['demand-distribute'] = array('edition' => 'ipd', 'vision' => 'or', 'order' => 200, 'depend' => array('demand-browse', 'demand-view'), 'recommend' => array('demand-assignTo', 'demand-batchCreate', 'demand-create', 'demand-edit')); +$config->group->package->manageDemand->privs['demand-retract'] = array('edition' => 'ipd', 'vision' => 'or', 'order' => 210, 'depend' => array('demandpool-browse', 'demand-browse', 'demand-view'), 'recommend' => array('demand-distribute')); $config->group->package->reviewDemand = new stdclass(); $config->group->package->reviewDemand->order = 5; diff --git a/module/project/model.php b/module/project/model.php index b491d4792b..16453757ca 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -2845,15 +2845,18 @@ class projectModel extends model $projectProduct = 0; if(empty($project->hasProduct) || $model == 'ipd') $projectProduct = $this->dao->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($objectID)->fetch('product'); - $lang->project->menu->settings['subMenu']->module['link'] = sprintf($lang->project->menu->settings['subMenu']->module['link'], $projectProduct); + if(isset($lang->project->menu->settings['subMenu']->module['link'])) $lang->project->menu->settings['subMenu']->module['link'] = sprintf($lang->project->menu->settings['subMenu']->module['link'], $projectProduct); - if(isset($project->model) and ($project->model == 'scrum' or $project->model == 'agileplus')) + if(isset($lang->project->menu->projectplan)) { - $lang->project->menu->projectplan['link'] = sprintf($lang->project->menu->projectplan['link'], $projectProduct); - } - else - { - unset($lang->project->menu->projectplan); + if(isset($project->model) and ($project->model == 'scrum' or $project->model == 'agileplus')) + { + $lang->project->menu->projectplan['link'] = sprintf($lang->project->menu->projectplan['link'], $projectProduct); + } + else + { + unset($lang->project->menu->projectplan); + } } if(!empty($this->config->URAndSR) && $project->model !== 'kanban' && isset($lang->project->menu->storyGroup)) diff --git a/module/story/model.php b/module/story/model.php index 705dbc9ce7..e7629aefd6 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -45,18 +45,25 @@ class storyModel extends model if($setImgSize) $story->spec = $this->file->setImgSize($story->spec); if($setImgSize) $story->verify = $this->file->setImgSize($story->verify); + $storyIdList = $story->id; + if($story->type == 'requirement') + { + $stories = $this->getStoryRelationByIds($story->id, 'requirement'); + if(isset($stories[$story->id])) $storyIdList = $stories[$story->id]; + } + $story->executions = $this->dao->select('t1.project, t2.name, t2.status, t2.type, t2.multiple')->from(TABLE_PROJECTSTORY)->alias('t1') ->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.project = t2.id') ->where('t2.type')->in('sprint,stage,kanban') - ->beginIF($story->twins)->andWhere('t1.story')->in(ltrim($story->twins, ',') . $story->id)->fi() - ->beginIF(!$story->twins)->andWhere('t1.story')->in($story->id)->fi() + ->beginIF($story->twins)->andWhere('t1.story')->in(ltrim($story->twins, ',') . $storyIdList)->fi() + ->beginIF(!$story->twins)->andWhere('t1.story')->in($storyIdList)->fi() ->orderBy('t1.`order` DESC') ->fetchAll('project'); $story->tasks = $this->dao->select('id, name, assignedTo, execution, project, status, consumed, `left`,type')->from(TABLE_TASK) ->where('deleted')->eq(0) - ->beginIF($story->twins)->andWhere('story')->in(ltrim($story->twins, ',') . $story->id)->fi() - ->beginIF(!$story->twins)->andWhere('story')->in($story->id)->fi() + ->beginIF($story->twins)->andWhere('story')->in(ltrim($story->twins, ',') . $storyIdList)->fi() + ->beginIF(!$story->twins)->andWhere('story')->in($storyIdList)->fi() ->orderBy('id DESC') ->fetchGroup('execution'); @@ -155,6 +162,12 @@ class storyModel extends model */ public function getAffectedScope($story) { + $storyIdList = $story->id; + if($story->type == 'requirement') + { + $stories = $this->getStoryRelationByIds($story->id, 'requirement'); + if(isset($stories[$story->id])) $storyIdList = $stories[$story->id]; + } /* Remove closed executions. */ if($story->executions) { @@ -174,8 +187,8 @@ class storyModel extends model /* Get affected bugs. */ $story->bugs = $this->dao->select('*')->from(TABLE_BUG) ->where('status')->ne('closed') - ->beginIF($story->twins)->andWhere('story')->in(ltrim($story->twins, ',') . $story->id)->fi() - ->beginIF(!$story->twins)->andWhere('story')->in($story->id)->fi() + ->beginIF($story->twins)->andWhere('story')->in(ltrim($story->twins, ',') . $storyIdList)->fi() + ->beginIF(!$story->twins)->andWhere('story')->in($storyIdList)->fi() ->andWhere('status')->ne('closed') ->andWhere('deleted')->eq(0) ->orderBy('id desc')->fetchAll(); @@ -183,10 +196,19 @@ class storyModel extends model /* Get affected cases. */ $story->cases = $this->dao->select('*')->from(TABLE_CASE) ->where('deleted')->eq(0) - ->beginIF($story->twins)->andWhere('story')->in(ltrim($story->twins, ',') . $story->id)->fi() - ->beginIF(!$story->twins)->andWhere('story')->in($story->id)->fi() + ->beginIF($story->twins)->andWhere('story')->in(ltrim($story->twins, ',') . $storyIdList)->fi() + ->beginIF(!$story->twins)->andWhere('story')->in($storyIdList)->fi() ->fetchAll(); + $story->stories = $this->dao->select('t1.*, t2.spec, t2.verify, t3.name as productTitle, t3.deleted as productDeleted') + ->from(TABLE_STORY)->alias('t1') + ->leftJoin(TABLE_STORYSPEC)->alias('t2')->on('t1.id=t2.story') + ->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t1.product=t3.id') + ->where('t1.version=t2.version') + ->andWhere('t1.deleted')->eq(0) + ->andWhere('t1.id')->in($storyIdList) + ->fetchAll('id'); + return $story; }