Merge branch 'feature/demand'

This commit is contained in:
tanghucheng
2024-07-17 10:26:06 +08:00
30 changed files with 102 additions and 148 deletions
+9 -1
View File
@@ -1,5 +1,13 @@
UPDATE zt_demand SET status = 'active' WHERE status in ('launched','distributed','pass');
UPDATE zt_story SET status = 'active' WHERE status in ('launched','developing');
ALTER TABLE `zt_demand` ADD `parentVersion` smallint NOT NULL DEFAULT 0 AFTER `version`;
ALTER TABLE `zt_story` ADD `demandVersion` smallint NOT NULL DEFAULT 0 AFTER `parentVersion`;
UPDATE `zt_demand` AS t1 JOIN `zt_demand` AS t2 ON t1.parent = t2.id SET t1.parentVersion = t2.version WHERE t1.parent > 0;
UPDATE `zt_story` AS t1 JOIN `zt_demand` AS t2 ON t1.demand = t2.id SET t1.demandVersion = t2.version WHERE t1.demand > 0;
ALTER TABLE `zt_approvalnode` ADD `forwardBy` char(30) NOT NULL DEFAULT '' AFTER `extra`;
ALTER TABLE `zt_approvalnode` ADD `revertTo` char(30) NOT NULL DEFAULT '' AFTER `extra`;
ALTER TABLE `zt_approvalnode` ADD `revertTo` char(30) NOT NULL DEFAULT '' AFTER `extra`;
UPDATE `zt_workflowaction` SET conditions = '' WHERE `action` = 'approvalreview' AND `conditions` = '[{"conditionType":"data","fields":[{"field":"deleted","operator":"equal","param":"0","logicalOperator":"and"},{"field":"reviewStatus","operator":"equal","param":"doing","logicalOperator":"and"},{"field":"reviewers","operator":"include","param":"currentUser"}]}]';
UPDATE `zt_workflowaction` SET conditions = '' WHERE `action` = 'approvalcancel' AND `conditions` = '[{"conditionType":"data","fields":[{"field":"deleted","operator":"equal","param":"0","logicalOperator":"and"},{"field":"reviewStatus","operator":"equal","param":"doing","logicalOperator":"and"},{"field":"openedBy","operator":"equal","param":"currentUser"}]}]';
+2
View File
@@ -117,6 +117,8 @@ class dropdown extends wg
if(is_array($menu) && $menu) $menu = $menu[0];
if(is_array($menu) && $menu) $menu = $menu[0];
if($menu instanceof menu)
{
list($id, $menuProps, $menuClass) = $this->prop(array('id', 'menu', 'menuClass'));
+1 -1
View File
@@ -1,4 +1,4 @@
.productBox {position: relative; padding-top: 5px;}
.productBox {position: relative;}
.productBox .distributeProduct, .productsBox .addProductBox .form-group{padding-left: 0px;}
.productBox .roadmapBox{padding-right: 0px;}
.productBox .c-actions {position: absolute; width: 100px; right: -100px;}
+5
View File
@@ -1356,6 +1356,11 @@ class actionModel extends model
$this->recoverRelatedData($action, $object);
/* 还原已删除的需求时重算OR需求和业用研需的阶段。 */
/* The stage of recalculating OR requirements and industrial research needs when restoring deleted requirements. */
if(in_array($action->objectType, array('story', 'epic', 'requirement'))) $this->loadModel('story')->setStage($action->objectID);
if($action->objectType == 'demand' && !empty($object->parent)) $this->loadModel('demand')->updateParentDemandStage($object->parent);
/* 在action表中更新action记录。 */
/* Update action record in action table. */
$this->dao->update(TABLE_ACTION)->set('extra')->eq(actionModel::BE_UNDELETED)->where('id')->eq($actionID)->exec();
+3 -3
View File
@@ -183,10 +183,10 @@ r($action->getListTest($objectType[2], $bugID[1])) && p() && e('link'); // 测
r($action->getListTest($objectType[2], $bugID[2])) && p() && e('link'); // 测试获取对象类型 bug 对象ID 3 的动态信息
// 操作是 tostory 对象类型 feedback
r($action->getListTest($objectType[3], $feedbackID[0])) && p() && e('link'); // 测试获取对象类型 feedback 对象ID 1 的动态信息
r($action->getListTest($objectType[3], $feedbackID[0])) && p() && e('nochanged'); // 测试获取对象类型 feedback 对象ID 1 的动态信息
// 操作是 tostory 对象类型 ticket
r($action->getListTest($objectType[4], $hasOneID[0])) && p() && e('link'); // 测试获取对象类型 ticket 对象ID 1 的动态信息
r($action->getListTest($objectType[4], $hasOneID[0])) && p() && e('nochanged'); // 测试获取对象类型 ticket 对象ID 1 的动态信息
// 操作是 moved 对象类型是 task
r($action->getListTest($objectType[1], $taskID[0])) && p() && e('link'); // 测试获取对象类型 task 对象ID 1 的动态信息
@@ -285,7 +285,7 @@ r($action->getListTest($objectType[1], $taskID[9])) && p() && e('link'); // 测
r($action->getListTest($objectType[1], $taskID[10])) && p() && e('link'); // 测试获取对象类型 task 对象ID 11 的动态信息
// 操作 totask 对象类型 feedback
r($action->getListTest($objectType[3], $feedbackID[1])) && p() && e('link'); // 测试获取对象类型 feedback 对象ID 2 的动态信息
r($action->getListTest($objectType[3], $feedbackID[1])) && p() && e('nochanged'); // 测试获取对象类型 feedback 对象ID 2 的动态信息
// 操作 linkchildtask 对象类型 feedback
r($action->getListTest($objectType[3], $feedbackID[2])) && p() && e('nochanged'); // 测试获取对象类型 feedback 对象ID 3 的动态信息
+1 -1
View File
@@ -72,6 +72,6 @@ r($action->getObjectLabelTest($objectType[18], $objectId[18], $actionType[18], $
r($action->getObjectLabelTest($objectType[19], $objectId[19], $actionType[19], $requirements, $epics)) && p() && e('报告|testreport|view|report=%s'); // 测试获取objectType testreport objectId 20的动态信息
r($action->getObjectLabelTest($objectType[20], $objectId[20], $actionType[20], $requirements, $epics)) && p() && e('应用|entry|browse|'); // 测试获取objectType entry objectId 21的动态信息
r($action->getObjectLabelTest($objectType[21], $objectId[21], $actionType[21], $requirements, $epics)) && p() && e('Webhook|webhook|browse|'); // 测试获取objectType webhook objectId 22的动态信息
r($action->getObjectLabelTest($objectType[22], $objectId[22], $actionType[22], $requirements, $epics)) && p() && e('评审|review|view|reviewID=%s'); // 测试获取objectType review objectId 23的动态信息
r($action->getObjectLabelTest($objectType[22], $objectId[22], $actionType[22], $requirements, $epics)) && p() && e('review'); // 测试获取objectType review objectId 23的动态信息
r($action->getObjectLabelTest($objectType[1], $objectId[23], $actionType[23], $requirements, $epics)) && p() && e('用户需求|story|storyView|storyID=%s'); // 测试获取objectType story objectId 25的动态信息
r($action->getObjectLabelTest($objectType[1], $objectId[24], $actionType[23], $requirements, $epics)) && p() && e('业务需求|story|storyView|storyID=%s'); // 测试获取objectType story objectId 26的动态信息
@@ -382,10 +382,10 @@ class branchTest
public function changeBranchLanguageTest($productID)
{
global $tester;
global $lang;
global $app;
$filePath = dirname(__FILE__, 2) . DS . 'lang' . DS . 'zh-cn.php';
include $filePath;
$app::$loadedLangs = array();
$app->loadLang('branch');
$this->objectModel->changeBranchLanguage($productID);
+2 -2
View File
@@ -25,9 +25,9 @@ $buildIdList = array('1,0,trunk', '1,trunk', '0,trunk');
$bug = new bugTest();
r($bug->getActivatedBugsTest($productIdList[0], $beginList[0], $endList[0], $buildIdList[0])) && p() && e('2,5,6,9'); // 测试获取产品 1 2 3 类型 空 开始日期 上月 结束日期 下月 的bug
r($bug->getActivatedBugsTest($productIdList[0], $beginList[0], $endList[0], $buildIdList[0])) && p() && e('1,2,5,6,9'); // 测试获取产品 1 2 3 类型 空 开始日期 上月 结束日期 下月 的bug
r($bug->getActivatedBugsTest($productIdList[0], $beginList[1], $endList[1], $buildIdList[0])) && p() && e('0'); // 测试获取产品 1 2 3 类型 空 开始日期 上周 结束日期 下周 的bug
r($bug->getActivatedBugsTest($productIdList[0], $beginList[0], $endList[0], $buildIdList[1])) && p() && e('5,6,9'); // 测试获取产品 1 2 3 类型 resolved 开始日期 上月 结束日期 下月 的bug
r($bug->getActivatedBugsTest($productIdList[0], $beginList[0], $endList[0], $buildIdList[1])) && p() && e('1,5,6,9'); // 测试获取产品 1 2 3 类型 resolved 开始日期 上月 结束日期 下月 的bug
r($bug->getActivatedBugsTest($productIdList[0], $beginList[1], $endList[1], $buildIdList[1])) && p() && e('0'); // 测试获取产品 1 2 3 类型 resolved 开始日期 上周 结束日期 下周 的bug
r($bug->getActivatedBugsTest($productIdList[0], $beginList[0], $endList[0], $buildIdList[2])) && p() && e('2,5,6,9'); // 测试获取产品 1 2 3 类型 opened 开始日期 上月 结束日期 下月 的bug
r($bug->getActivatedBugsTest($productIdList[0], $beginList[1], $endList[1], $buildIdList[2])) && p() && e('0'); // 测试获取产品 1 2 3 类型 opened 开始日期 上周 结束日期 下周 的bug
+4
View File
@@ -23,6 +23,8 @@ $app->methodName = 'create';
$config->webRoot = '';
$config->requestType = 'PATH_INFO';
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest';
try
{
$result = $tester->loadModel('common')->checkPriv();
@@ -47,3 +49,5 @@ catch (Exception $e)
}
r($result) && p() && e('1'); // 用户有权限时,返回TRUE
unset($_SERVER['HTTP_X_REQUESTED_WITH']);
+2 -2
View File
@@ -9,7 +9,7 @@ timeout=0
cid=1
- deny中鉴权,有权限时返回TRUE @1
- deny中鉴权,无权限时返回跳转的URL @{"load":"-deny.php?m=user&f=deny&module=execution&method=create"}0
- deny中鉴权,无权限时返回0 @0
*/
su('admin');
@@ -33,4 +33,4 @@ try{
$result2 = $e->getMessage();
}
r($result2) && p() && e('{"load":"user-deny-execution-create.html"}0'); // deny中鉴权,无权限时返回跳转的URL
r($result2) && p() && e('0'); // deny中鉴权,无权限时返回0
+6 -6
View File
@@ -21,11 +21,11 @@ $tester->loadModel('common');
$tester->common->lang->db->custom = array();
r($tester->common->replaceMenuLang()) && p() && e('0'); //没有 db->custom 数据。
$tester->common->lang->db->custom['myMenu']['menu']['execution'] = '执行1';
$tester->common->lang->db->custom['mySubMenu']['work']['task'] = '任务1';
$tester->common->lang->db->custom['executionMenu']['storyGroupDropMenu']['story'] = '需求1';
$tester->common->lang->db->custom['myMenu']['menu']['execution'] = '执行1';
$tester->common->lang->db->custom['mySubMenu']['work']['task'] = '任务1';
$tester->common->lang->db->custom['executionMenu']['menu']['story'] = '需求1';
$tester->common->replaceMenuLang();
r($tester->common->lang->my->menu->execution) && p('link') && e("执行1|my|execution|type=undone"); // 替换二级导航语言项。
r($tester->common->lang->my->menu->work['subMenu']->task) && p('link') && e("任务1|my|work|mode=task"); // 替换三级导航语言项。
r($tester->common->lang->execution->menu->storyGroup['dropMenu']->story) && p('link') && e("需求1|execution|story|executionID=%s"); // 替换二级导航下拉的语言项。
r($tester->common->lang->my->menu->execution) && p('link') && e("执行1|my|execution|type=undone"); // 替换二级导航语言项。
r($tester->common->lang->my->menu->work['subMenu']->task) && p('link') && e("任务1|my|work|mode=task"); // 替换三级导航语言项。
r($tester->common->lang->execution->menu->story) && p('link') && e("需求1|execution|story|executionID=%s"); // 替换二级导航下拉的语言项。
+9 -9
View File
@@ -78,12 +78,12 @@ $openFeatures = $customTester->computeFeaturesTest($editionList[0]);
$ipdFeatures = $customTester->computeFeaturesTest($editionList[1]);
$maxFeatures = $customTester->computeFeaturesTest($editionList[2]);
r($openFeatures[0]) && p('0,1,2,3,4') && e('program,productLine,productUR,projectWaterfall,projectWaterfallplus'); // 计算无相关数据时,开源版不启用的功能
r($openFeatures[1]) && p() && e('0'); // 计算无相关数据时,开源版敏捷项目启用的功能
r($openFeatures[2]) && p() && e('0'); // 计算无相关数据时,开源版敏捷项目不启用的功能
r($ipdFeatures[0]) && p('0,1,2,3,4') && e('program,productLine,productUR,projectWaterfall,projectWaterfallplus'); // 计算无相关数据时,ipd版不启用的功能
r($ipdFeatures[1]) && p() && e('0'); // 计算无相关数据时,ipd版敏捷项目启用的功能
r($ipdFeatures[2]) && p() && e('0'); // 计算无相关数据时,ipd版敏捷项目不启用的功能
r($maxFeatures[0]) && p('0,1,2,3,4') && e('program,productLine,productUR,projectWaterfall,projectWaterfallplus'); // 计算无相关数据时,旗舰版不启用的功能
r($maxFeatures[1]) && p() && e('0'); // 计算无相关数据时,旗舰版敏捷项目启用的功能
r($maxFeatures[2]) && p() && e('0'); // 计算无相关数据时,旗舰版敏捷项目不启用的功能
r($openFeatures[0]) && p('0,1,2,3,4') && e('program,productLine,productER,productUR,projectWaterfall'); // 计算无相关数据时,开源版不启用的功能
r($openFeatures[1]) && p() && e('0'); // 计算无相关数据时,开源版敏捷项目启用的功能
r($openFeatures[2]) && p() && e('0'); // 计算无相关数据时,开源版敏捷项目不启用的功能
r($ipdFeatures[0]) && p('0,1,2,3,4') && e('program,productLine,productER,productUR,projectWaterfall'); // 计算无相关数据时,ipd版不启用的功能
r($ipdFeatures[1]) && p() && e('0'); // 计算无相关数据时,ipd版敏捷项目启用的功能
r($ipdFeatures[2]) && p() && e('0'); // 计算无相关数据时,ipd版敏捷项目不启用的功能
r($maxFeatures[0]) && p('0,1,2,3,4') && e('program,productLine,productER,productUR,projectWaterfall'); // 计算无相关数据时,旗舰版不启用的功能
r($maxFeatures[1]) && p() && e('0'); // 计算无相关数据时,旗舰版敏捷项目启用的功能
r($maxFeatures[2]) && p() && e('0'); // 计算无相关数据时,旗舰版敏捷项目不启用的功能
@@ -20,5 +20,5 @@ cid=1
$modeList = array('ALM', 'light');
$customTester = new customTest();
r($customTester->disableFeaturesByModeTest($modeList[0])) && p() && e('0'); // 将模式设置为全生命周期管理模式
r($customTester->disableFeaturesByModeTest($modeList[1], ';')) && p() && e('productUR,waterfall,waterfallplus,scrumMeasrecord,agileplusMeasrecord,productTrack,productRoadmap'); // 将模式设置为轻量级管理模式
r($customTester->disableFeaturesByModeTest($modeList[0])) && p() && e('0'); // 将模式设置为全生命周期管理模式
r($customTester->disableFeaturesByModeTest($modeList[1], ';')) && p() && e('productER,productUR,waterfall,waterfallplus,scrumMeasrecord,agileplusMeasrecord,productTrack,productRoadmap'); // 将模式设置为轻量级管理模式
@@ -1,48 +0,0 @@
#!/usr/bin/env php
<?php
include dirname(__FILE__, 5) . '/test/lib/init.php';
zdTable('storygrade');
su('admin');
/**
title=测试 customModel->setStoryGrade();
timeout=0
cid=1
- 查看插入的等级数量 @5
- 查看插入的等级1详情
- 第0条的grade属性 @1
- 第0条的name属性 @一级
- 第0条的status属性 @enable
- 查看插入的等级5详情
- 第4条的grade属性 @5
- 第4条的name属性 @五级
- 第4条的status属性 @enable
*/
$data['grade'] = array(
0 => 1,
1 => 2,
2 => 3,
3 => 4,
4 => 5
);
$data['gradeName'] = array(
0 => '一级',
1 => '二级',
2 => '三级',
3 => '四级',
4 => '五级'
);
global $tester;
$tester->loadModel('custom')->setStoryGrade('story', $data);
$gradeSetting = $tester->loadModel('story')->getGradeList();
r(count($gradeSetting)) && p() && e('5'); // 查看插入的等级数量
r($gradeSetting) && p('0:grade,name,status') && e('1,一级,enable'); // 查看插入的等级1详情
r($gradeSetting) && p('4:grade,name,status') && e('5,五级,enable'); // 查看插入的等级5详情
+3 -3
View File
@@ -18,9 +18,9 @@ su('admin');
$key = array(1, 0);
$SRName = array('', '软件需求', '软件需求1');
$dataList[] = array('SRName' => $SRName[0], 'URName' => '用户需求');
$dataList[] = array('SRName' => $SRName[1], 'URName' => '用户需求');
$dataList[] = array('SRName' => $SRName[2], 'URName' => '用户需求');
$dataList[] = array('SRName' => $SRName[0], 'URName' => '用户需求', 'ERName' => '业务需求');
$dataList[] = array('SRName' => $SRName[1], 'URName' => '用户需求', 'ERName' => '业务需求');
$dataList[] = array('SRName' => $SRName[2], 'URName' => '用户需求', 'ERName' => '业务需求');
$customTester = new customTest();
r($customTester->updateURAndSRTest($key[0], $dataList[2])) && p('SRName') && e('软件需求1'); // 测试修改key为1,SRName值更改为软件需求1
+1 -4
View File
@@ -2944,7 +2944,7 @@ class executionModel extends model
foreach($planStories as $id => $story)
{
if(!in_array($story->status, array('active', 'launched')) || (!empty($story->branch) && !empty($executionBranches) && !isset($executionBranches[$story->branch]))) unset($planStories[$id]);
if($story->status != 'active' || (!empty($story->branch) && !empty($executionBranches) && !isset($executionBranches[$story->branch]))) unset($planStories[$id]);
if(strpos($project->storyType, $story->type) === false) unset($planStories[$id]);
if(!in_array($execution->attribute, array('mix', 'request', 'design')) && $story->type != 'story' && $execution->multiple) unset($planStories[$id]);
}
@@ -2981,9 +2981,6 @@ class executionModel extends model
}
$this->dao->delete()->from(TABLE_PROJECTSTORY)->where('project')->eq($executionID)->andWhere('story')->eq($storyID)->limit(1)->exec();
/* In ipd project, unlink stories change it's status to launched. */
if($execution->model == 'ipd' and $storyType == 'requirement') $this->dao->update(TABLE_STORY)->set('status')->eq('launched')->where('id')->eq($storyID)->exec();
/* Resolve TABLE_KANBANCELL's field cards. */
if($execution->type == 'kanban')
{
+11 -10
View File
@@ -3749,16 +3749,17 @@ $config->group->package->manageDemand = new stdclass();
$config->group->package->manageDemand->order = 5;
$config->group->package->manageDemand->subset = 'demand';
$config->group->package->manageDemand->privs = array();
$config->group->package->manageDemand->privs['demand-create'] = array('edition' => 'ipd', 'vision' => 'or', 'order' => 20, 'depend' => array('demand-browse', 'demand-view'), 'recommend' => array('demand-assignTo', 'demand-batchCreate', 'demand-change', 'demand-edit', 'demand-recall', 'demand-submitReview'));
$config->group->package->manageDemand->privs['demand-batchCreate'] = array('edition' => 'ipd', 'vision' => 'or', 'order' => 30, 'depend' => array('demand-browse', 'demand-view'), 'recommend' => array('demand-create'));
$config->group->package->manageDemand->privs['demand-edit'] = array('edition' => 'ipd', 'vision' => 'or', 'order' => 40, 'depend' => array('demand-browse'), 'recommend' => array('demand-assignTo', 'demand-batchCreate'));
$config->group->package->manageDemand->privs['demand-assignTo'] = array('edition' => 'ipd', 'vision' => 'or', 'order' => 60, 'depend' => array('demand-browse'), 'recommend' => array('demand-activate', 'demand-close', 'demand-create', 'demand-edit'));
$config->group->package->manageDemand->privs['demand-change'] = array('edition' => 'ipd', 'vision' => 'or', 'order' => 70, 'depend' => array('demand-browse', 'demand-view'), 'recommend' => array('demand-activate', 'demand-assignTo', 'demand-batchCreate', 'demand-close', 'demand-create', 'demand-edit'));
$config->group->package->manageDemand->privs['demand-manageTree'] = array('edition' => 'ipd', 'vision' => 'or', 'order' => 120, 'depend' => array('demand-browse'), 'recommend' => array());
$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->manageDemand->privs['demand-create'] = array('edition' => 'ipd', 'vision' => 'or', 'order' => 20, 'depend' => array('demand-browse', 'demand-view'), 'recommend' => array('demand-assignTo', 'demand-batchCreate', 'demand-change', 'demand-edit', 'demand-recall', 'demand-submitReview'));
$config->group->package->manageDemand->privs['demand-batchCreate'] = array('edition' => 'ipd', 'vision' => 'or', 'order' => 30, 'depend' => array('demand-browse', 'demand-view'), 'recommend' => array('demand-create'));
$config->group->package->manageDemand->privs['demand-edit'] = array('edition' => 'ipd', 'vision' => 'or', 'order' => 40, 'depend' => array('demand-browse'), 'recommend' => array('demand-assignTo', 'demand-batchCreate'));
$config->group->package->manageDemand->privs['demand-assignTo'] = array('edition' => 'ipd', 'vision' => 'or', 'order' => 60, 'depend' => array('demand-browse'), 'recommend' => array('demand-activate', 'demand-close', 'demand-create', 'demand-edit'));
$config->group->package->manageDemand->privs['demand-change'] = array('edition' => 'ipd', 'vision' => 'or', 'order' => 70, 'depend' => array('demand-browse', 'demand-view'), 'recommend' => array('demand-activate', 'demand-assignTo', 'demand-batchCreate', 'demand-close', 'demand-create', 'demand-edit'));
$config->group->package->manageDemand->privs['demand-manageTree'] = array('edition' => 'ipd', 'vision' => 'or', 'order' => 120, 'depend' => array('demand-browse'), 'recommend' => array());
$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->manageDemand->privs['demand-processDemandChange'] = array('edition' => 'ipd', 'vision' => 'or', 'order' => 220, 'depend' => array('demand-browse'), 'recommend' => array('demand-activate', 'demand-assignTo'));
$config->group->package->reviewDemand = new stdclass();
$config->group->package->reviewDemand->order = 5;
+8 -1
View File
@@ -663,7 +663,14 @@ class productModel extends model
{
$unclosedStatus = $this->lang->story->statusList;
unset($unclosedStatus['closed']);
return $this->story->getProductStories($productID, $branch, $modules, array_keys($unclosedStatus), $type, $sort, true, '', $pager);
$stories = $this->story->getProductStories($productID, $branch, $modules, array_keys($unclosedStatus), $type, $sort, true, '', $pager);
foreach($stories as $storyID => $story)
{
if($story->type != 'story' && $story->stage == 'closed') unset($stories[$storyID]);
}
$this->app->loadClass('pager', true);
$pager = new pager(count($stories), $pager->recPerPage, $pager->pageID);
return $stories ? current(array_chunk($stories, $pager->recPerPage, true)) : array();
}
/* Set default function called, when browseType is (draftstory, activestory, changingstory, reviewingstory, closedstory, developingstory, launchedstory). */
+1
View File
@@ -35,6 +35,7 @@ cid=0
include dirname(__FILE__, 5) . '/test/lib/init.php';
include dirname(__FILE__, 2) . '/lib/product.unittest.class.php';
zenData('product')->gen(5);
zenData('story')->gen(100);
$productIDList = array(1, 2, 3, 4, 5, 1000001);
+2 -2
View File
@@ -1434,8 +1434,8 @@ class productZen extends product
$this->view->storyCases = $this->loadModel('testcase')->getStoryCaseCounts($storyIdList);
$this->view->reports = in_array($this->config->edition, array('max', 'ipd')) ? $this->loadModel('researchreport')->getPairs() : array();
$this->view->roadmaps = ($this->config->edition == 'ipd' && $storyType == 'requirement') ? array(0 => '') + $this->loadModel('roadmap')->getPairs($product->id) : array();
$this->view->noclosedRoadmaps = ($this->config->edition == 'ipd' && $storyType == 'requirement') ? array(0 => '') + $this->loadModel('roadmap')->getPairs($product->id, '', 'noclosed') : array();
$this->view->roadmaps = ($this->config->edition == 'ipd' && $storyType != 'story') ? array(0 => '') + $this->loadModel('roadmap')->getPairs($product->id) : array();
$this->view->noclosedRoadmaps = ($this->config->edition == 'ipd' && $storyType != 'story') ? array(0 => '') + $this->loadModel('roadmap')->getPairs($product->id, '', 'noclosed') : array();
$this->display();
}
+1 -1
View File
@@ -584,7 +584,7 @@ class productplan extends control
}
else
{
$allStories = $this->story->getProductStories($this->view->product->id, $plan->branch ? "0,{$plan->branch}" : 0, '0', 'draft,reviewing,active,changing,launched', 'all', 'id_desc', true, array_keys($planStories), $pager);
$allStories = $this->story->getProductStories($this->view->product->id, $plan->branch ? "0,{$plan->branch}" : 0, '0', 'draft,reviewing,active,changing', 'all', 'id_desc', true, array_keys($planStories), $pager);
}
$modules = $this->loadModel('tree')->getOptionMenu($plan->product, 'story', 0, 'all');
+4 -1
View File
@@ -1486,7 +1486,10 @@ class story extends control
*/
public function processStoryChange(int $storyID)
{
$story = $this->story->fetchByID($storyID);
$story = $this->story->fetchByID($storyID);
if($story->parent <= 0 && $this->config->edition == 'ipd') return $this->fetch('demand', 'processDemandChange', "objectID=$storyID&type=story");
$parent = $this->story->fetchByID($story->parent);
$this->dao->update(TABLE_STORY)->set('parentVersion')->eq($parent->version)->where('id')->eq($storyID)->exec();
-6
View File
@@ -245,12 +245,6 @@ $lang->story->statusList['active'] = 'Aktiv';
$lang->story->statusList['closed'] = 'Geschlossen';
$lang->story->statusList['changing'] = 'Geändert';
if($config->systemMode == 'PLM')
{
$lang->story->statusList['launched'] = 'Launched';
$lang->story->statusList['developing'] = 'Developing';
}
$lang->story->stageList[''] = '';
$lang->story->stageList['wait'] = 'Wartend';
$lang->story->stageList['planned'] = 'Geplant';
-6
View File
@@ -245,12 +245,6 @@ $lang->story->statusList['active'] = 'Active';
$lang->story->statusList['closed'] = 'Closed';
$lang->story->statusList['changing'] = 'Changing';
if($config->systemMode == 'PLM')
{
$lang->story->statusList['launched'] = 'Launched';
$lang->story->statusList['developing'] = 'Developing';
}
$lang->story->stageList[''] = '';
$lang->story->stageList['wait'] = 'Waiting';
$lang->story->stageList['planned'] = 'Planned';
-6
View File
@@ -245,12 +245,6 @@ $lang->story->statusList['active'] = 'Active';
$lang->story->statusList['closed'] = 'Fermée';
$lang->story->statusList['changing'] = 'Changée';
if($config->systemMode == 'PLM')
{
$lang->story->statusList['launched'] = 'Launched';
$lang->story->statusList['developing'] = 'Developing';
}
$lang->story->stageList[''] = '';
$lang->story->stageList['wait'] = 'En Attente';
$lang->story->stageList['planned'] = 'Plannifée';
-6
View File
@@ -245,12 +245,6 @@ $lang->story->statusList['active'] = '激活';
$lang->story->statusList['closed'] = '已关闭';
$lang->story->statusList['changing'] = '变更中';
if($config->systemMode == 'PLM')
{
$lang->story->statusList['launched'] = '已立项';
$lang->story->statusList['developing'] = '研发中';
}
$lang->story->stageList[''] = '';
$lang->story->stageList['wait'] = '未开始';
$lang->story->stageList['planned'] = "已计划";
+15 -12
View File
@@ -966,8 +966,8 @@ class storyModel extends model
$this->computeEstimate($parentID);
$status = $oldParentStory->status;
if(count($childrenStatus) == 1 and current($childrenStatus) == 'closed') $status = current($childrenStatus); // Close parent story.
if($oldParentStory->status == 'closed' && in_array($childStory->status, array('launched', 'active'))) $status = $this->getActivateStatus($parentID); // Activate parent story.
if(count($childrenStatus) == 1 and current($childrenStatus) == 'closed') $status = current($childrenStatus); // Close parent story.
if($oldParentStory->status == 'closed' && $childStory->status == 'active') $status = $this->getActivateStatus($parentID); // Activate parent story.
$action = '';
$preStatus = '';
@@ -977,7 +977,7 @@ class storyModel extends model
if(dao::isError()) return false;
if(!$createAction) return $story;
if(strpos('launched,active,draft,changing', $status) !== false) $action = 'Activated';
if(strpos('active,draft,changing', $status) !== false) $action = 'Activated';
if($status == 'closed')
{
/* Record the status before closed. */
@@ -1336,7 +1336,7 @@ class storyModel extends model
$story = new stdclass();
$story->title = $titleList[$twinID]->title;
$story->version = $oldStory->version - 1;
$story->status = ($this->config->systemMode == 'PLM' and $oldStory->type == 'requirement' and $this->config->vision == 'rnd') ? 'launched' : 'active';
$story->status = 'active';
$this->dao->update(TABLE_STORY)->set('title')->eq($story->title)->set('version')->eq($story->version)->set('status')->eq($story->status)->where('id')->eq($storyID)->exec();
}
@@ -1373,7 +1373,6 @@ class storyModel extends model
$story->reviewer = implode(',', $story->reviewer);
if($story->reviewer) $story->status = 'reviewing';
if($this->config->systemMode == 'PLM' && $this->config->vision == 'rnd' && $oldStory->type == 'requirement' && $story->status == 'active') $story->status = 'launched';
$this->dao->update(TABLE_STORY)->data($story, 'reviewer')->where('id')->in($twinsIdList)->exec();
@@ -2095,9 +2094,6 @@ class storyModel extends model
$story = $postData;
$story->status = $this->getActivateStatus($storyID);
/* If in ipd mode, set requirement status = 'launched'. */
if($this->config->systemMode == 'PLM' and $oldStory->type == 'requirement' and $story->status == 'active' and $this->config->vision == 'rnd') $story->status = 'launched';
$this->dao->update(TABLE_STORY)->data($story, 'comment')->autoCheck()->checkFlow()->where('id')->eq($storyID)->exec();
/* Update parent story status. */
@@ -2737,6 +2733,15 @@ class storyModel extends model
$story->planTitle = '';
$storyPlans = explode(',', trim($story->plan, ','));
foreach($storyPlans as $planID) $story->planTitle .= zget($plans, $planID, '') . ' ';
$story->parent = array();
foreach(explode(',', trim((string)$story->path, ',')) as $parentID)
{
if(!$parentID) continue;
if($parentID == $story->id) continue;
$story->parent[] = (int)$parentID;
}
$stories[$story->id] = $story;
}
@@ -3846,6 +3851,7 @@ class storyModel extends model
->where('root')->in($rootIdList)
->andWhere('product')->eq($productID)
->andWhere('deleted')->eq('0')
->andWhere("FIND_IN_SET('{$this->config->vision}', vision)")
->beginIF($storyType == 'requirement')
->andWhere('type')->eq('story')
->beginIF($showGrades && isset($storyGrades))->andWhere('grade')->in($storyGrades)->fi()
@@ -3977,7 +3983,7 @@ class storyModel extends model
$storyCols = array();
foreach($showCols as $colType)
{
if(!in_array($colType, array('epic', 'requirement', 'story'))) continue;
if(!in_array($colType, array('demand', 'epic', 'requirement', 'story'))) continue;
foreach($tracks['cols'] as $col)
{
$colName = $col['name'];
@@ -4442,9 +4448,6 @@ class storyModel extends model
$story->finalResult = $result;
/* If in ipd mode, set requirement status = 'launched'. */
if($this->config->systemMode == 'PLM' and $oldStory->type == 'requirement' and $story->status == 'active' and $this->config->vision == 'rnd') $story->status = 'launched';
return $story;
}
+6 -2
View File
@@ -264,14 +264,18 @@ class storyTao extends storyModel
->fetchPairs();
}
$demands = $this->dao->select('id,version')->from(TABLE_DEMAND)->where('deleted')->eq(0)->fetchPairs();
foreach($stories as $story)
{
/* Judge parent story has changed. */
if($story->parent > 0 and isset($parents[$story->parent]))
if($story->parent > 0 && isset($parents[$story->parent]))
{
if($parents[$story->parent]->version > $story->parentVersion && $story->parentVersion > 0 && $parents[$story->parent]->status == 'active') $story->parentChanged = true;
}
/* Judge demand has changed. */
if($story->demand && $story->parent <= 0 && isset($demands[$story->demand]) && $demands[$story->demand] > $story->demandVersion) $story->demandChanged = true;
/* Judge parent story if has same type child or other type child. */
if($story->type != 'story' && $story->isParent == '1')
{
@@ -1894,7 +1898,7 @@ class storyTao extends storyModel
$canActivate = common::hasPriv($story->type, 'activate') && $this->isClickable($story, 'activate');
if(!common::canBeChanged($story->type, $story)) return array(array('name' => 'close', 'hint' => $lang->close, 'data-toggle' => 'modal', 'url' => $canClose ? $closeLink : null, 'disabled' => !$canClose));
$canProcessChange = common::hasPriv($story->type, 'processStoryChange');
if(!empty($story->parentChanged)) return array(array('name' => 'processStoryChange', 'url' => $canProcessChange ? $processStoryChangeLink : null, 'disabled' => !$canProcessChange, 'innerClass' => 'ajax-submit'));
if(!empty($story->parentChanged) || !empty($story->demandChanged)) return array(array('name' => 'processStoryChange', 'url' => $canProcessChange ? $processStoryChangeLink : null, 'disabled' => !$canProcessChange, 'innerClass' => 'ajax-submit'));
/* Change button. */
$canChange = common::hasPriv($story->type, 'change') && $this->isClickable($story, 'change');
+1
View File
@@ -87,6 +87,7 @@ if($story->children)
$cols['assignedTo'] = $config->story->dtable->fieldList['assignedTo'];
$cols['estimate'] = $config->story->dtable->fieldList['estimate'];
$cols['status'] = $config->story->dtable->fieldList['status'];
$cols['stage'] = $config->story->dtable->fieldList['stage'];
$cols['actions'] = $config->story->dtable->fieldList['actions'];
$cols['title']['title'] = $lang->story->name;
$cols['id']['checkbox'] = false;
-10
View File
@@ -1193,10 +1193,6 @@ class storyZen extends story
/* Need and force review, then set status to reviewing. */
if($storyData->status != 'draft' and $this->story->checkForceReview($storyType) and !$this->post->needNotReview) $storyData->status = 'reviewing';
/* If in ipd mode, set requirement status = 'launched'. */
if($this->config->systemMode == 'PLM' && $storyData->type == 'requirement' && $storyData->status == 'active' && $this->config->vision == 'rnd') $storyData->status = 'launched';
if($storyData->status == 'launched' && $this->app->tab != 'product') $storyData->status = 'developing';
return $this->loadModel('file')->processImgURL($storyData, $editorFields, $this->post->uid);
}
@@ -1311,9 +1307,6 @@ class storyZen extends story
->setDefault('version', $oldStory->version)
->get();
/* If in ipd mode, set requirement status = 'launched'. */
if($this->config->systemMode == 'PLM' and $this->config->vision == 'rnd' and $oldStory->type == 'requirement' and $story->status == 'active') $story->status = 'launched';
$specChanged = false;
$oldStoryReviewers = array_keys($this->story->getReviewerPairs($storyID, $oldStory->version));
$_POST['reviewer'] = isset($_POST['reviewer']) ? $_POST['reviewer'] : array();
@@ -1513,9 +1506,6 @@ class storyZen extends story
!empty($story->assignedTo) && $story->assignedDate = $now;
if($this->post->uploadImage && $this->post->uploadImage[$i]) $story->uploadImage = $this->post->uploadImage[$i];
/* If in ipd mode, set requirement status = 'launched'. */
if($this->config->systemMode == 'PLM' and $this->config->vision == 'rnd' and $storyType == 'requirement' and $story->status == 'active') $story->status = 'launched';
}
return $stories;