Merge branch feature/workflowgroup of zentao/zentaopms (#11852)
This commit is contained in:
@@ -100,6 +100,23 @@ ALTER TABLE `zt_approvalnode` CHANGE `result` `result` varchar(20) NOT NULL DEFA
|
||||
DELETE FROM `zt_workflowgroup` WHERE `projectModel` = 'kanban';
|
||||
UPDATE `zt_project` SET `workflowGroup` = '0' WHERE `model` = 'kanban';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `zt_decision` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`workflowGroup` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`stage` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`order` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`title` varchar(255) NOT NULL DEFAULT '',
|
||||
`type` varchar(30) NOT NULL DEFAULT '',
|
||||
`category` varchar(30) NOT NULL DEFAULT '',
|
||||
`builtin` enum('0','1') NOT NULL DEFAULT '0',
|
||||
`createdBy` char(30) NOT NULL DEFAULT '',
|
||||
`createdDate` datetime NULL,
|
||||
`editedBy` char(30) NOT NULL DEFAULT '',
|
||||
`editedDate` datetime NULL,
|
||||
`deleted` enum('0','1') NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
ALTER TABLE `zt_stage` ADD `workflowGroup` mediumint(8) unsigned NOT NULL DEFAULT '0' AFTER `id`;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `zt_decision` (
|
||||
|
||||
@@ -628,6 +628,7 @@ CREATE TABLE IF NOT EXISTS `zt_decision` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`workflowGroup` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`stage` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`order` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`title` varchar(255) NOT NULL DEFAULT '',
|
||||
`type` varchar(30) NOT NULL DEFAULT '',
|
||||
`category` varchar(30) NOT NULL DEFAULT '',
|
||||
|
||||
@@ -1255,6 +1255,7 @@ class projectModel extends model
|
||||
if($project->acl != 'open') $this->loadModel('user')->updateUserView(array($projectID), 'project');
|
||||
|
||||
if(empty($project->multiple) and $project->model != 'waterfall' and $project->model != 'waterfallplus') $this->loadModel('execution')->createDefaultSprint($projectID);
|
||||
if(!empty($project->workflowGroup) && $project->model == 'ipd') $this->loadModel('stage')->addBuiltinPoint($project->workflowGroup);
|
||||
|
||||
return $projectID;
|
||||
}
|
||||
|
||||
@@ -26,3 +26,7 @@ if(isset($config->setPercent) && $config->setPercent == 1) $config->stage->form-
|
||||
$config->stage->form->settype['lang'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->stage->form->settype['keys'] = array('type' => 'array', 'required' => false, 'default' => array());
|
||||
$config->stage->form->settype['values'] = array('type' => 'array', 'required' => false, 'default' => array());
|
||||
|
||||
$config->stage->form->setpoint['id'] = array('type' => 'int', 'required' => false, 'default' => 0);
|
||||
$config->stage->form->setpoint['title'] = array('type' => 'string', 'required' => true, 'default' => '', 'base' => true, 'filter' => 'trim');
|
||||
$config->stage->form->setpoint['flow'] = array('type' => 'int', 'required' => true, 'default' => 1);
|
||||
|
||||
@@ -235,6 +235,19 @@ class stage extends control
|
||||
*/
|
||||
public function setPoint(string $type, int $stageID)
|
||||
{
|
||||
$this->app->loadLang('review');
|
||||
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$points = form::batchData()->get();
|
||||
$this->stage->setPoint($type, $stageID, $points);
|
||||
if(dao::isError()) return $this->sendError(dao::getError());
|
||||
return $this->sendSuccess(array('closeModal' => true, 'load' => true));
|
||||
}
|
||||
|
||||
$this->view->type = $type;
|
||||
$this->view->approvals = $this->loadModel('approvalflow')->getPairs('project');
|
||||
$this->view->stagePoints = $this->stage->getStagePoints($type, $stageID);
|
||||
$this->display();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
window.refreshApproval = function()
|
||||
{
|
||||
$.getJSON($.createLink('review', 'ajaxGetApproval'), function(data)
|
||||
{
|
||||
$('[name^=flow]').each(function()
|
||||
{
|
||||
$(this).zui('picker').render({items: data});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -21,13 +21,16 @@ $lang->stage->setTRpoint = 'Set TR Point';
|
||||
$lang->stage->setDCPpoint = 'Set DCP Point';
|
||||
|
||||
/* Fields. */
|
||||
$lang->stage->id = 'ID';
|
||||
$lang->stage->name = 'Name';
|
||||
$lang->stage->type = 'Type';
|
||||
$lang->stage->percent = 'Workload %';
|
||||
$lang->stage->setType = 'Set Type';
|
||||
$lang->stage->TRpoint = 'TR Point';
|
||||
$lang->stage->DCPpoint = 'DCP Point';
|
||||
$lang->stage->id = 'ID';
|
||||
$lang->stage->name = 'Name';
|
||||
$lang->stage->type = 'Type';
|
||||
$lang->stage->percent = 'Workload %';
|
||||
$lang->stage->setType = 'Set Type';
|
||||
$lang->stage->TRpoint = 'TR Point';
|
||||
$lang->stage->DCPpoint = 'DCP Point';
|
||||
$lang->stage->TRname = 'TR Point Name';
|
||||
$lang->stage->DCPname = 'DCP Point Name';
|
||||
$lang->stage->pointFlow = 'Approval Flow';
|
||||
|
||||
$lang->stage->typeList['mix'] = 'Mix';
|
||||
$lang->stage->typeList['request'] = 'Story';
|
||||
|
||||
@@ -21,13 +21,16 @@ $lang->stage->setTRpoint = 'Set TR Point';
|
||||
$lang->stage->setDCPpoint = 'Set DCP Point';
|
||||
|
||||
/* Fields. */
|
||||
$lang->stage->id = 'ID';
|
||||
$lang->stage->name = 'Name';
|
||||
$lang->stage->type = 'Type';
|
||||
$lang->stage->percent = 'Workload %';
|
||||
$lang->stage->setType = 'Set Type';
|
||||
$lang->stage->TRpoint = 'TR Point';
|
||||
$lang->stage->DCPpoint = 'DCP Point';
|
||||
$lang->stage->id = 'ID';
|
||||
$lang->stage->name = 'Name';
|
||||
$lang->stage->type = 'Type';
|
||||
$lang->stage->percent = 'Workload %';
|
||||
$lang->stage->setType = 'Set Type';
|
||||
$lang->stage->TRpoint = 'TR Point';
|
||||
$lang->stage->DCPpoint = 'DCP Point';
|
||||
$lang->stage->TRname = 'TR Point Name';
|
||||
$lang->stage->DCPname = 'DCP Point Name';
|
||||
$lang->stage->pointFlow = 'Approval Flow';
|
||||
|
||||
$lang->stage->typeList['mix'] = 'Mix';
|
||||
$lang->stage->typeList['request'] = 'Story';
|
||||
|
||||
@@ -21,13 +21,16 @@ $lang->stage->setTRpoint = 'Set TR Point';
|
||||
$lang->stage->setDCPpoint = 'Set DCP Point';
|
||||
|
||||
/* Fields. */
|
||||
$lang->stage->id = 'ID';
|
||||
$lang->stage->name = 'Name';
|
||||
$lang->stage->type = 'Type';
|
||||
$lang->stage->percent = 'Workload %';
|
||||
$lang->stage->setType = 'Set Type';
|
||||
$lang->stage->TRpoint = 'TR Point';
|
||||
$lang->stage->DCPpoint = 'DCP Point';
|
||||
$lang->stage->id = 'ID';
|
||||
$lang->stage->name = 'Name';
|
||||
$lang->stage->type = 'Type';
|
||||
$lang->stage->percent = 'Workload %';
|
||||
$lang->stage->setType = 'Set Type';
|
||||
$lang->stage->TRpoint = 'TR Point';
|
||||
$lang->stage->DCPpoint = 'DCP Point';
|
||||
$lang->stage->TRname = 'TR Point Name';
|
||||
$lang->stage->DCPname = 'DCP Point Name';
|
||||
$lang->stage->pointFlow = 'Approval Flow';
|
||||
|
||||
$lang->stage->typeList['mix'] = 'Mix';
|
||||
$lang->stage->typeList['request'] = 'Story';
|
||||
|
||||
@@ -21,13 +21,16 @@ $lang->stage->setTRpoint = 'TR评审点配置';
|
||||
$lang->stage->setDCPpoint = 'DCP评审点配置';
|
||||
|
||||
/* Fields. */
|
||||
$lang->stage->id = 'ID';
|
||||
$lang->stage->name = '阶段名称';
|
||||
$lang->stage->type = '阶段类型';
|
||||
$lang->stage->percent = '工作量占比';
|
||||
$lang->stage->setType = '阶段类型';
|
||||
$lang->stage->TRpoint = 'TR评审点';
|
||||
$lang->stage->DCPpoint = 'DCP评审点';
|
||||
$lang->stage->id = 'ID';
|
||||
$lang->stage->name = '阶段名称';
|
||||
$lang->stage->type = '阶段类型';
|
||||
$lang->stage->percent = '工作量占比';
|
||||
$lang->stage->setType = '阶段类型';
|
||||
$lang->stage->TRpoint = 'TR评审点';
|
||||
$lang->stage->DCPpoint = 'DCP评审点';
|
||||
$lang->stage->TRname = 'TR评审点名称';
|
||||
$lang->stage->DCPname = 'DCP评审点名称';
|
||||
$lang->stage->pointFlow = '审批流';
|
||||
|
||||
$lang->stage->typeList['mix'] = '综合';
|
||||
$lang->stage->typeList['request'] = '需求';
|
||||
|
||||
+193
-1
@@ -164,11 +164,29 @@ class stageModel extends model
|
||||
->fetchAll('id');
|
||||
}
|
||||
|
||||
return $this->dao->select('*')->from(TABLE_STAGE)
|
||||
$stages = $this->dao->select('*')->from(TABLE_STAGE)
|
||||
->where('deleted')->eq(0)
|
||||
->andWhere('workflowGroup')->eq($groupID)
|
||||
->orderBy($orderBy)
|
||||
->fetchAll('id');
|
||||
|
||||
$stagePoints = $this->dao->select('*')->from(TABLE_DECISION)->where('stage')->in(array_keys($stages))->orderBy('order_asc')->fetchGroup('stage');
|
||||
$pointList = array();
|
||||
foreach($stagePoints as $stageID => $points)
|
||||
{
|
||||
if(!isset($pointList[$stageID])) $pointList[$stageID] = array();
|
||||
foreach($points as $point)
|
||||
{
|
||||
if(!isset($pointList[$stageID][$point->type])) $pointList[$stageID][$point->type] = array();
|
||||
$pointList[$stageID][$point->type][$point->id] = $point->title;
|
||||
}
|
||||
}
|
||||
foreach($stages as $stage)
|
||||
{
|
||||
$stage->TRpoint = isset($pointList[$stage->id]['TR']) ? implode(', ', $pointList[$stage->id]['TR']) : '';
|
||||
$stage->DCPpoint = isset($pointList[$stage->id]['DCP']) ? implode(', ', $pointList[$stage->id]['DCP']) : '';
|
||||
}
|
||||
return $stages;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,4 +213,178 @@ class stageModel extends model
|
||||
{
|
||||
return (float)$this->dao->select('sum(percent) as total')->from(TABLE_STAGE)->where('deleted')->eq('0')->andWhere('workflowGroup')->eq($groupID)->fetch('total');
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加内置评审点。
|
||||
* Add the builtin point.
|
||||
*
|
||||
* @param int $groupID
|
||||
* @return void
|
||||
*/
|
||||
public function addBuiltinPoint(int $groupID)
|
||||
{
|
||||
$workflowGroup = $this->dao->select('*')->from(TABLE_WORKFLOWGROUP)->where('id')->eq($groupID)->fetch();
|
||||
if($workflowGroup->projectModel != 'ipd') return;
|
||||
|
||||
$builtinPoints = $this->dao->select('*')->from(TABLE_DECISION)->where('workflowGroup')->eq($groupID)->andWhere('builtin')->eq('1')->fetchAll();
|
||||
if(!empty($builtinPoints)) return;
|
||||
|
||||
$this->app->loadConfig('review');
|
||||
$this->app->loadConfig('project');
|
||||
$stageList = $this->dao->select('*')->from(TABLE_STAGE)->where('workflowGroup')->eq($groupID)->fetchAll('id');
|
||||
if(empty($stageList))
|
||||
{
|
||||
$stageTypeList = array();
|
||||
if($workflowGroup->projectType == 'ipd') $stageTypeList = $this->config->project->categoryStages['IPD'];
|
||||
if($workflowGroup->projectType == 'tpd') $stageTypeList = $this->config->project->categoryStages['TPD'];
|
||||
if($workflowGroup->projectType == 'cbb') $stageTypeList = $this->config->project->categoryStages['CBB'];
|
||||
if(in_array($workflowGroup->projectType, array('cpdproduct', 'cpdproject'))) $stageTypeList= $this->config->project->categoryStages['CPD'];
|
||||
|
||||
foreach($stageTypeList as $stageType)
|
||||
{
|
||||
$builtinStage = new stdClass();
|
||||
$builtinStage->workflowGroup = $groupID;
|
||||
$builtinStage->createdBy = 'system';
|
||||
$builtinStage->createdDate = helper::now();
|
||||
$builtinStage->name = zget($this->lang->stage->ipdTypeList, $stageType, '');
|
||||
$builtinStage->type = $stageType;
|
||||
$this->dao->insert(TABLE_STAGE)->data($builtinStage)->exec();
|
||||
|
||||
$stageID = $this->dao->lastInsertID();
|
||||
$stageList[$stageID] = $builtinStage;
|
||||
}
|
||||
}
|
||||
|
||||
$decision = new stdClass();
|
||||
$decision->builtin = '1';
|
||||
$decision->createdBy = 'system';
|
||||
$decision->createdDate = helper::now();
|
||||
$decision->workflowGroup = $groupID;
|
||||
|
||||
$decisionFlow = new stdClass();
|
||||
$decisionFlow->flow = 1;
|
||||
$decisionFlow->objectType = 'point';
|
||||
$decisionFlow->relatedBy = 'system';
|
||||
$decisionFlow->relatedDate = helper::now();
|
||||
foreach($stageList as $id => $stage)
|
||||
{
|
||||
foreach($this->config->review->ipdReviewPoint->{$stage->type} as $index => $point)
|
||||
{
|
||||
$decision->stage = $id;
|
||||
$decision->order = $index + 1;
|
||||
$decision->title = $point;
|
||||
$decision->type = strpos($point, 'TR') !== false ? 'TR' : 'DCP';
|
||||
$decision->category = $point;
|
||||
$this->dao->insert(TABLE_DECISION)->data($decision)->exec();
|
||||
$decisionID = $this->dao->lastInsertID();
|
||||
|
||||
$decisionFlow->root = $stage->workflowGroup;
|
||||
$decisionFlow->objectID = $decisionID;
|
||||
$this->dao->insert(TABLE_APPROVALFLOWOBJECT)->data($decisionFlow)->exec();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取阶段的评审点。
|
||||
* Get points of stage.
|
||||
*
|
||||
* @param string $type TR|DCP
|
||||
* @param int $stageID
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function getStagePoints(string $type, int $stageID)
|
||||
{
|
||||
$stage = $this->dao->select('*')->from(TABLE_STAGE)->where('id')->eq($stageID)->fetch();
|
||||
return $this->dao->select('t1.*,t2.flow')->from(TABLE_DECISION)->alias('t1')
|
||||
->leftJoin(TABLE_APPROVALFLOWOBJECT)->alias('t2')->on("t1.id = t2.objectID AND t2.objectType = 'point'")
|
||||
->where('t1.stage')->eq($stageID)
|
||||
->andWhere('t1.type')->eq($type)
|
||||
->andWhere('t2.root')->eq($stage->workflowGroup)
|
||||
->orderBy('order_asc')
|
||||
->fetchAll('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置阶段的评审点。
|
||||
* Set point of stage.
|
||||
*
|
||||
* @param string $type TR|DCP
|
||||
* @param int $stageID
|
||||
* @param array $stageID
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function setPoint(string $type, int $stageID, array $points): bool
|
||||
{
|
||||
$stage = $this->getByID($stageID);
|
||||
$oldStagePoints = $this->getStagePoints($type, $stageID);
|
||||
|
||||
foreach($points as $index => $point)
|
||||
{
|
||||
if(!empty($point->id) && isset($oldStagePoints[$point->id]))
|
||||
{
|
||||
$oldPoint = $oldStagePoints[$point->id];
|
||||
if($oldPoint->title != $point->title || $oldPoint->order != $index)
|
||||
{
|
||||
$this->dao->update(TABLE_DECISION)
|
||||
->set('title')->eq($point->title)
|
||||
->set('order')->eq($index)
|
||||
->set('editedBy')->eq($this->app->user->account)
|
||||
->set('editedDate')->eq(helper::now())
|
||||
->where('id')->eq($point->id)
|
||||
->exec();
|
||||
if(dao::isError()) return false;
|
||||
}
|
||||
if($oldPoint->flow != $point->flow)
|
||||
{
|
||||
$this->dao->update(TABLE_APPROVALFLOWOBJECT)
|
||||
->set('flow')->eq($point->flow)
|
||||
->where('objectID')->eq($point->id)
|
||||
->andWhere('objectType')->eq('point')
|
||||
->andWhere('root')->eq($stage->workflowGroup)
|
||||
->exec();
|
||||
if(dao::isError()) return false;
|
||||
}
|
||||
unset($oldStagePoints[$point->id]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$newPoint = new stdClass();
|
||||
$newPoint->workflowGroup = $stage->workflowGroup;
|
||||
$newPoint->stage = $stageID;
|
||||
$newPoint->title = $point->title;
|
||||
$newPoint->type = $type;
|
||||
$newPoint->builtin = '0';
|
||||
$newPoint->createdBy = $this->app->user->account;
|
||||
$newPoint->createdDate = helper::now();
|
||||
$newPoint->order = $index;
|
||||
$this->dao->insert(TABLE_DECISION)->data($newPoint)->exec();
|
||||
$newPointID = $this->dao->lastInsertID();
|
||||
if(dao::isError()) return false;
|
||||
|
||||
$approvalFlowObject = new stdClass();
|
||||
$approvalFlowObject->root = $stage->workflowGroup;
|
||||
$approvalFlowObject->flow = $point->flow;
|
||||
$approvalFlowObject->objectType = 'point';
|
||||
$approvalFlowObject->objectID = $newPointID;
|
||||
$approvalFlowObject->relatedBy = $this->app->user->account;
|
||||
$approvalFlowObject->relatedDate = helper::now();
|
||||
$this->dao->insert(TABLE_APPROVALFLOWOBJECT)->data($approvalFlowObject)->exec();
|
||||
if(dao::isError()) return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty($oldStagePoints))
|
||||
{
|
||||
$this->dao->delete()->from(TABLE_DECISION)->where('id')->in(array_keys($oldStagePoints))->exec();
|
||||
$this->dao->delete()->from(TABLE_APPROVALFLOWOBJECT)
|
||||
->where('objectID')->in(array_keys($oldStagePoints))
|
||||
->andWhere('objectType')->eq('point')
|
||||
->andWhere('root')->eq($stage->workflowGroup)
|
||||
->exec();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Executable
+85
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
|
||||
title=测试 stageModel->addBuiltinPoint();
|
||||
cid=1
|
||||
|
||||
- 获取TR1评审点
|
||||
- 第1条的title属性 @TR1
|
||||
- 第1条的type属性 @TR
|
||||
- 第1条的category属性 @TR1
|
||||
- 获取CDCP评审点
|
||||
- 第2条的title属性 @CDCP
|
||||
- 第2条的type属性 @DCP
|
||||
- 第2条的category属性 @CDCP
|
||||
- 获取TR2评审点
|
||||
- 第3条的title属性 @TR2
|
||||
- 第3条的type属性 @TR
|
||||
- 第3条的category属性 @TR2
|
||||
- 获取TR3评审点
|
||||
- 第4条的title属性 @TR3
|
||||
- 第4条的type属性 @TR
|
||||
- 第4条的category属性 @TR3
|
||||
- 获取PDCP评审点
|
||||
- 第5条的title属性 @PDCP
|
||||
- 第5条的type属性 @DCP
|
||||
- 第5条的category属性 @PDCP
|
||||
- 获取TR4评审点
|
||||
- 第6条的title属性 @TR4
|
||||
- 第6条的type属性 @TR
|
||||
- 第6条的category属性 @TR4
|
||||
- 获取TR4A评审点
|
||||
- 第7条的title属性 @TR4A
|
||||
- 第7条的type属性 @TR
|
||||
- 第7条的category属性 @TR4A
|
||||
- 获取TR5评审点
|
||||
- 第8条的title属性 @TR5
|
||||
- 第8条的type属性 @TR
|
||||
- 第8条的category属性 @TR5
|
||||
- 获取TR6评审点
|
||||
- 第9条的title属性 @TR6
|
||||
- 第9条的type属性 @TR
|
||||
- 第9条的category属性 @TR6
|
||||
- 获取ADCP评审点
|
||||
- 第10条的title属性 @ADCP
|
||||
- 第10条的type属性 @DCP
|
||||
- 第10条的category属性 @ADCP
|
||||
- 获取LDCP评审点
|
||||
- 第11条的title属性 @LDCP
|
||||
- 第11条的type属性 @DCP
|
||||
- 第11条的category属性 @LDCP
|
||||
|
||||
*/
|
||||
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
|
||||
zenData('user')->gen(5);
|
||||
zenData('decision')->gen(0);
|
||||
|
||||
$workflowGroup = zenData('workflowgroup');
|
||||
$workflowGroup->id->range('1-5');
|
||||
$workflowGroup->type->range('project');
|
||||
$workflowGroup->projectModel->range('ipd');
|
||||
$workflowGroup->projectType->range('ipd,tpd,cbb,cpdproduct,cpdproject');
|
||||
$workflowGroup->name->range('IPD集成产品研发,IPD预研产品研发,IPD平台产品研发,IPD定制产品研发,IPD定制项目研发');
|
||||
$workflowGroup->code->range('ipdproduct,tpdproduct,cbbproduct,cpdproduct,cpdproject');
|
||||
$workflowGroup->status->range('normal');
|
||||
$workflowGroup->main->range('1');
|
||||
$workflowGroup->gen(5);
|
||||
|
||||
global $tester;
|
||||
$stageTester = $tester->loadModel('stage');
|
||||
$stageTester->addBuiltinPoint(1);
|
||||
$IPDpoint = $stageTester->dao->select('*')->from(TABLE_DECISION)->where('workflowGroup')->eq(1)->fetchAll('id');
|
||||
r($IPDpoint) && p('1:title,type,category') && e('TR1,TR,TR1'); //获取TR1评审点
|
||||
r($IPDpoint) && p('2:title,type,category') && e('CDCP,DCP,CDCP'); //获取CDCP评审点
|
||||
r($IPDpoint) && p('3:title,type,category') && e('TR2,TR,TR2'); //获取TR2评审点
|
||||
r($IPDpoint) && p('4:title,type,category') && e('TR3,TR,TR3'); //获取TR3评审点
|
||||
r($IPDpoint) && p('5:title,type,category') && e('PDCP,DCP,PDCP'); //获取PDCP评审点
|
||||
r($IPDpoint) && p('6:title,type,category') && e('TR4,TR,TR4'); //获取TR4评审点
|
||||
r($IPDpoint) && p('7:title,type,category') && e('TR4A,TR,TR4A'); //获取TR4A评审点
|
||||
r($IPDpoint) && p('8:title,type,category') && e('TR5,TR,TR5'); //获取TR5评审点
|
||||
r($IPDpoint) && p('9:title,type,category') && e('TR6,TR,TR6'); //获取TR6评审点
|
||||
r($IPDpoint) && p('10:title,type,category') && e('ADCP,DCP,ADCP'); //获取ADCP评审点
|
||||
r($IPDpoint) && p('11:title,type,category') && e('LDCP,DCP,LDCP'); //获取LDCP评审点
|
||||
Executable
+54
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
|
||||
title=测试 stageModel->getStagePoints();
|
||||
cid=1
|
||||
|
||||
- 获取阶段1的TR评审点
|
||||
- 第1条的stage属性 @1
|
||||
- 第1条的title属性 @TR1
|
||||
- 获取阶段2的TR评审点
|
||||
- 第2条的stage属性 @2
|
||||
- 第2条的title属性 @TR2
|
||||
- 获取阶段2的TR评审点
|
||||
- 第3条的stage属性 @3
|
||||
- 第3条的title属性 @TR3
|
||||
- 获取阶段4的DCP评审点
|
||||
- 第4条的stage属性 @4
|
||||
- 第4条的title属性 @CDCP
|
||||
- 获取阶段5的DCP评审点
|
||||
- 第5条的stage属性 @5
|
||||
- 第5条的title属性 @PDCP
|
||||
|
||||
*/
|
||||
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
include dirname(__FILE__, 2) . '/lib/stage.unittest.class.php';
|
||||
|
||||
zenData('stage')->loadYaml('stage')->gen(5);
|
||||
zenData('user')->gen(5);
|
||||
|
||||
$decision = zenData('decision');
|
||||
$decision->id->range('1-5');
|
||||
$decision->workflowGroup->range('1-5');
|
||||
$decision->stage->range('1-5');
|
||||
$decision->title->range('TR1,TR2,TR3,CDCP,PDCP');
|
||||
$decision->type->range('TR{3},DCP{2}');
|
||||
$decision->gen(5);
|
||||
|
||||
$approvalFlowObject = zenData('approvalflowobject');
|
||||
$approvalFlowObject->id->range('1-5');
|
||||
$approvalFlowObject->root->range('4');
|
||||
$approvalFlowObject->objectID->range('1-5');
|
||||
$approvalFlowObject->objectType->range('point');
|
||||
$approvalFlowObject->extra->range('review');
|
||||
$approvalFlowObject->gen(5);
|
||||
|
||||
global $tester;
|
||||
$stageTester = $tester->loadModel('stage');
|
||||
r($stageTester->getStagePoints('TR', 1)) && p('1:stage,title') && e('1,TR1'); //获取阶段1的TR评审点
|
||||
r($stageTester->getStagePoints('TR', 2)) && p('2:stage,title') && e('2,TR2'); //获取阶段2的TR评审点
|
||||
r($stageTester->getStagePoints('TR', 3)) && p('3:stage,title') && e('3,TR3'); //获取阶段2的TR评审点
|
||||
r($stageTester->getStagePoints('DCP', 4)) && p('4:stage,title') && e('4,CDCP'); //获取阶段4的DCP评审点
|
||||
r($stageTester->getStagePoints('DCP', 5)) && p('5:stage,title') && e('5,PDCP'); //获取阶段5的DCP评审点
|
||||
@@ -12,8 +12,7 @@ cid=1
|
||||
- 测试获取有stage数据的waterfallplus类型总百分比 @60
|
||||
- 测试获取不存在的项目类型总百分比 @0
|
||||
- 测试获取scrum类型的总百分比 @0
|
||||
- 测试获取空字符串类型的总百分比 @0
|
||||
- 测试已删除stage的百分比不被计算 @60
|
||||
- 测试已删除stage的百分比不被计算 @0
|
||||
|
||||
*/
|
||||
|
||||
@@ -24,22 +23,19 @@ $stageTester = new stageTest();
|
||||
|
||||
// 步骤1:测试空数据库情况
|
||||
zenData('stage')->gen(0);
|
||||
r($stageTester->getTotalPercentTest('waterfall')) && p() && e('0'); // 测试空数据库中waterfall类型的总百分比
|
||||
r($stageTester->getTotalPercentTest(4)) && p() && e('0'); // 测试空数据库中waterfall类型的总百分比
|
||||
|
||||
// 步骤2和3:准备测试数据,测试有数据情况
|
||||
zenData('user')->gen(5);
|
||||
zenData('stage')->loadYaml('stage')->gen(12);
|
||||
r($stageTester->getTotalPercentTest('waterfall')) && p() && e('60'); // 测试获取有stage数据的waterfall类型总百分比
|
||||
r($stageTester->getTotalPercentTest('waterfallplus')) && p() && e('60'); // 测试获取有stage数据的waterfallplus类型总百分比
|
||||
r($stageTester->getTotalPercentTest(4)) && p() && e('60'); // 测试获取有stage数据的waterfall类型总百分比
|
||||
r($stageTester->getTotalPercentTest(8)) && p() && e('60'); // 测试获取有stage数据的waterfallplus类型总百分比
|
||||
|
||||
// 步骤4:测试不存在的项目类型
|
||||
r($stageTester->getTotalPercentTest('nonexistent')) && p() && e('0'); // 测试获取不存在的项目类型总百分比
|
||||
r($stageTester->getTotalPercentTest(0)) && p() && e('0'); // 测试获取不存在的项目类型总百分比
|
||||
|
||||
// 步骤5:测试scrum类型(应该没有数据)
|
||||
r($stageTester->getTotalPercentTest('scrum')) && p() && e('0'); // 测试获取scrum类型的总百分比
|
||||
|
||||
// 步骤6:测试空字符串类型
|
||||
r($stageTester->getTotalPercentTest('')) && p() && e('0'); // 测试获取空字符串类型的总百分比
|
||||
r($stageTester->getTotalPercentTest(2)) && p() && e('0'); // 测试获取scrum类型的总百分比
|
||||
|
||||
// 步骤7:测试已删除的stage不被计算(需要准备包含已删除数据的测试数据)
|
||||
$table = zenData('stage');
|
||||
@@ -50,4 +46,4 @@ $table->type->range('request,design');
|
||||
$table->percent->range('15,25');
|
||||
$table->deleted->range('1{2}');
|
||||
$table->gen(2);
|
||||
r($stageTester->getTotalPercentTest('waterfall')) && p() && e('60'); // 测试已删除stage的百分比不被计算
|
||||
r($stageTester->getTotalPercentTest(2)) && p() && e('0'); // 测试已删除stage的百分比不被计算
|
||||
|
||||
Executable
+77
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
|
||||
title=测试 stageModel->setPoint();
|
||||
cid=1
|
||||
|
||||
- 测试修改评审点标题 @TR1 change
|
||||
- 测试修改评审点的审批流 @2
|
||||
- 测试修改评审点的顺序 @2
|
||||
- 测试删除评审点 @0
|
||||
- 测试添加评审点第6条的title属性 @test add point
|
||||
|
||||
*/
|
||||
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
include dirname(__FILE__, 2) . '/lib/stage.unittest.class.php';
|
||||
|
||||
zenData('stage')->loadYaml('stage')->gen(5);
|
||||
zenData('user')->gen(5);
|
||||
|
||||
$decision = zenData('decision');
|
||||
$decision->id->range('1-5');
|
||||
$decision->workflowGroup->range('1-5');
|
||||
$decision->stage->range('1-5');
|
||||
$decision->order->range('1');
|
||||
$decision->title->range('TR1,TR2,TR3,CDCP,PDCP');
|
||||
$decision->type->range('TR{3},DCP{2}');
|
||||
$decision->gen(5);
|
||||
|
||||
$approvalFlowObject = zenData('approvalflowobject');
|
||||
$approvalFlowObject->id->range('1-5');
|
||||
$approvalFlowObject->root->range('4');
|
||||
$approvalFlowObject->flow->range('1');
|
||||
$approvalFlowObject->objectID->range('1-5');
|
||||
$approvalFlowObject->objectType->range('point');
|
||||
$approvalFlowObject->extra->range('review');
|
||||
$approvalFlowObject->gen(5);
|
||||
|
||||
global $tester;
|
||||
$stageTester = $tester->loadModel('stage');
|
||||
|
||||
$changeTitle = new stdClass();
|
||||
$changeTitle->id = 1;
|
||||
$changeTitle->title = 'TR1 change';
|
||||
$changeTitle->flow = '1';
|
||||
$stageTester->setPoint('TR', 1, array(1 => $changeTitle));
|
||||
$result = $stageTester->dao->select('title')->from(TABLE_DECISION)->where('id')->eq(1)->fetch('title');
|
||||
r($result) && p() && e('TR1 change'); //测试修改评审点标题
|
||||
|
||||
$changeFlow = new stdClass();
|
||||
$changeFlow->id = 2;
|
||||
$changeFlow->title = 'TR2';
|
||||
$changeFlow->flow = 2;
|
||||
$stageTester->setPoint('TR', 2, array(1 => $changeFlow));
|
||||
$result = $stageTester->dao->select('flow')->from(TABLE_APPROVALFLOWOBJECT)->where('objectType')->eq('point')->andWhere('objectID')->eq(2)->fetch('flow');
|
||||
r($result) && p() && e('2'); //测试修改评审点的审批流
|
||||
|
||||
$changeOrder = new stdClass();
|
||||
$changeOrder->id = 3;
|
||||
$changeOrder->title = 'TR3';
|
||||
$changeOrder->flow = 1;
|
||||
$stageTester->setPoint('TR', 3, array(2 => $changeOrder));
|
||||
$result = $stageTester->dao->select('`order`')->from(TABLE_DECISION)->where('id')->eq(3)->fetch('order');
|
||||
r($result) && p() && e('2'); //测试修改评审点的顺序
|
||||
|
||||
$stageTester->setPoint('DCP', 4, array());
|
||||
$result = $stageTester->dao->select('*')->from(TABLE_DECISION)->where('stage')->eq(4)->fetchAll();
|
||||
r(count($result)) && p() && e('0'); //测试删除评审点
|
||||
|
||||
$addPoint = new stdClass();
|
||||
$addPoint->id = 0;
|
||||
$addPoint->title = 'test add point';
|
||||
$addPoint->flow = 1;
|
||||
$stageTester->setPoint('DCP', 4, array(1 => $addPoint));
|
||||
$result = $stageTester->dao->select('*')->from(TABLE_DECISION)->where('stage')->eq(4)->fetchAll('id');
|
||||
r($result) && p('6:title') && e('test add point'); //测试添加评审点
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* Set point view of stage module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2025 禅道软件(青岛)集团有限公司
|
||||
* @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
* @author xieqiyu <xieqiyu@chandao.com>
|
||||
* @package stage
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
|
||||
namespace zin;
|
||||
|
||||
modalHeader
|
||||
(
|
||||
set::title($type == 'TR' ? $lang->stage->setTRpoint : $lang->stage->setDCPpoint),
|
||||
set::titleClass('text-md font-semibold')
|
||||
);
|
||||
|
||||
formBatchPanel
|
||||
(
|
||||
setID('setPointForm'),
|
||||
set::minRows(1),
|
||||
set::sortable(true),
|
||||
set::data(array_values($stagePoints)),
|
||||
set::idKey('index'),
|
||||
formBatchItem
|
||||
(
|
||||
set::name('id'),
|
||||
set::hidden(true)
|
||||
),
|
||||
formBatchItem
|
||||
(
|
||||
set::name('title'),
|
||||
set::required(true),
|
||||
set::label($type == 'TR' ? $lang->stage->TRname : $lang->stage->DCPname)
|
||||
),
|
||||
formBatchItem
|
||||
(
|
||||
set::name('flow'),
|
||||
set::label($lang->stage->pointFlow),
|
||||
set::required(true),
|
||||
set::control('inputGroup'),
|
||||
inputGroup
|
||||
(
|
||||
picker
|
||||
(
|
||||
set::name('flow'),
|
||||
set::required(true),
|
||||
set::items($approvals),
|
||||
set::value(1)
|
||||
),
|
||||
hasPriv('approvalflow', 'create') ? div
|
||||
(
|
||||
a(set::className('btn secondary ml-1'), set::href(createLink('approvalflow', 'create', 'workflow=&callback=refreshApproval')), setData(array('toggle' => 'modal')), $lang->review->createApproval)
|
||||
) : null
|
||||
)
|
||||
)
|
||||
);
|
||||
@@ -112,7 +112,7 @@ $config->upgrade->execFlow['21_6_beta'] = array('functions' => 'processCharter
|
||||
$config->upgrade->execFlow['21_6_1'] = array('xxsqls' => "$appRoot/db/upgradexuanxuan9.1.2.sql");
|
||||
$config->upgrade->execFlow['21_7'] = array('functions' => 'fixWorkflowNameForExecution');
|
||||
$config->upgrade->execFlow['21_7_1'] = array('functions' => 'convertCharset,processActionProduct');
|
||||
$config->upgrade->execFlow['21_7_3'] = array('functions' => 'modifyProjectWorkflowGroup,upgradeProcessAndActivity,addWorkflowGroupOtherActivity,addDefaultDeliverableModule,upgradeDesignToDeliverable,buildinTestcaseStageDeliverable,upgradeDeliverable,buildinBaselineReview,upgradeReviewclCategory,upgradeBaselineObjects,upgradeReviewToDeliverable,upgradeBaseline,addDeliverablePrivs');
|
||||
$config->upgrade->execFlow['21_7_3'] = array('functions' => 'modifyProjectWorkflowGroup,upgradeProcessAndActivity,addWorkflowGroupOtherActivity,addDefaultDeliverableModule,upgradeDesignToDeliverable,buildinTestcaseStageDeliverable,upgradeDeliverable,buildinBaselineReview,upgradeReviewclCategory,upgradeBaselineObjects,upgradeReviewToDeliverable,upgradeBaseline,addDeliverablePrivs,upgradeStageAndPoint');
|
||||
$config->upgrade->execFlow['21_7_5'] = array('functions' => 'weekly-addBuiltinWeeklyTemplate,adjustPriv21_7_5');
|
||||
|
||||
if(!empty($config->isINT))
|
||||
|
||||
+35
-57
@@ -12505,18 +12505,19 @@ class upgradeModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* 升级阶段列表。
|
||||
* Update stage list.
|
||||
* 升级阶段列表及评审点。
|
||||
* Update stage and point.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function upgradeStageList()
|
||||
public function upgradeStageAndPoint()
|
||||
{
|
||||
$stageGroup = $this->dao->select('*')->from(TABLE_STAGE)->where('workflowGroup')->eq(0)->fetchGroup('projectType', 'id');
|
||||
if(empty($stageGroup)) return true;
|
||||
|
||||
$this->app->loadConfig('project');
|
||||
$this->app->loadConfig('review');
|
||||
$typeCodeGroup = $this->dao->select('projectModel, code, id')->from(TABLE_WORKFLOWGROUP)->where('main')->eq('1')->andWhere('projectModel')->in('waterfall,waterfallplus,ipd')->fetchGroup('projectModel', 'code');
|
||||
foreach($typeCodeGroup as $projectModel => $flowList)
|
||||
{
|
||||
@@ -12532,6 +12533,37 @@ class upgradeModel extends model
|
||||
$stage->workflowGroup = $typeCodeGroup[$projectModel][$flowCode]->id;
|
||||
if(empty($stage->editedDate)) $stage->editedDate = null;
|
||||
$this->dao->insert(TABLE_STAGE)->data($stage)->exec();
|
||||
$stageID = $this->dao->lastInsertID();
|
||||
|
||||
/* 添加IPD项目流程阶段的评审点。*/
|
||||
if($projectModel == 'ipd')
|
||||
{
|
||||
$decision = new stdClass();
|
||||
$decision->builtin = '1';
|
||||
$decision->createdBy = 'system';
|
||||
$decision->createdDate = helper::now();
|
||||
|
||||
$decisionFlow = new stdClass();
|
||||
$decisionFlow->flow = 1;
|
||||
$decisionFlow->objectType = 'point';
|
||||
$decisionFlow->relatedBy = 'system';
|
||||
$decisionFlow->relatedDate = helper::now();
|
||||
foreach($this->config->review->ipdReviewPoint->{$stage->type} as $index => $point)
|
||||
{
|
||||
$decision->workflowGroup = $stage->workflowGroup;
|
||||
$decision->stage = $stageID;
|
||||
$decision->order = $index + 1;
|
||||
$decision->title = $point;
|
||||
$decision->type = strpos($point, 'TR') !== false ? 'TR' : 'DCP';
|
||||
$decision->category = $point;
|
||||
$this->dao->insert(TABLE_DECISION)->data($decision)->exec();
|
||||
$decisionID = $this->dao->lastInsertID();
|
||||
|
||||
$decisionFlow->root = $stage->workflowGroup;
|
||||
$decisionFlow->objectID = $decisionID;
|
||||
$this->dao->insert(TABLE_APPROVALFLOWOBJECT)->data($decisionFlow)->exec();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12540,60 +12572,6 @@ class upgradeModel extends model
|
||||
$this->dao->exec('ALTER TABLE ' . TABLE_STAGE . ' DROP COLUMN `projectType`');
|
||||
}
|
||||
|
||||
/**
|
||||
* TR和DCP评审对象升级到技术与决策评审流程。
|
||||
* Upgrade TR and DCP objects to decision flows.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function upgradeDecision()
|
||||
{
|
||||
$ipdProjectGroups = $this->dao->select('id')->from(TABLE_WORKFLOWGROUP)->where('type')->eq('project')->andWhere('projectModel')->eq('ipd')->andWhere('builtin')->eq('1')->fetchPairs();
|
||||
$ipdProjectStages = $this->dao->select('id,workflowGroup,type')->from(TABLE_STAGE)->where('projectType')->eq('ipd')->fetchGroup('workflowGroup');
|
||||
|
||||
$object = new stdclass();
|
||||
$object->createdBy = $this->app->user->account;
|
||||
$object->createdDate = helper::now();
|
||||
|
||||
$decisionFlow = new stdclass();
|
||||
$decisionFlow->flow = 1;
|
||||
$decisionFlow->objectType = 'decision';
|
||||
$decisionFlow->relatedBy = $this->app->user->account;
|
||||
$decisionFlow->relatedDate = helper::now();
|
||||
$decisionFlow->extra = 'review';
|
||||
|
||||
foreach($ipdProjectGroups as $ipdProjectGroupID)
|
||||
{
|
||||
if(empty($ipdProjectStages[$ipdProjectGroupID])) continue;
|
||||
|
||||
$object->workflowgroup = $ipdProjectGroupID;
|
||||
|
||||
$decisionFlow->root = $ipdProjectGroupID;
|
||||
|
||||
foreach($ipdProjectStages[$ipdProjectGroupID] as $stages)
|
||||
{
|
||||
foreach($stages as $stage)
|
||||
{
|
||||
$object->stage = $stage->id;
|
||||
|
||||
$stageType = $stage->type;
|
||||
foreach($this->config->review->ipdReviewPoint->$stageType as $category)
|
||||
{
|
||||
$object->title = $this->lang->review->reviewPoint->titleList[$category];
|
||||
$object->type = strpos($category, 'TR') === 0 ? 'TR' : 'DCP';
|
||||
$object->category = $category;
|
||||
$this->dao->insert(TABLE_DECISION)->data($object)->autoCheck()->exec();
|
||||
|
||||
$decisionFlow->objectID = $this->dao->lastInsertID();
|
||||
$this->dao->insert(TABLE_APPROVALFLOWOBJECT)->data($decisionFlow)->autoCheck()->exec();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return !dao::isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* 调整 21.7.5 版本的权限
|
||||
* Adjust priv 21.7.5.
|
||||
|
||||
Reference in New Issue
Block a user