* Resolve confilict.
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
if(!isset($config->programplan->create)) $config->programplan->create = new stdclass;
|
||||
$config->programplan->create->form = array();
|
||||
$config->programplan->create->formFields = array('planIDList', 'names', 'PM', 'percents', 'attributes', 'acl', 'milestone', 'begin', 'end', 'realBegan', 'realEnd', 'desc', 'orders', 'type');
|
||||
foreach($config->programplan->create->formFields as $field) $config->programplan->create->form[$field] = array('required' => false, 'type' => 'array');
|
||||
|
||||
$config->programplan->edit = new stdClass();
|
||||
$config->programplan->edit->form = array();
|
||||
$config->programplan->edit->form['begin'] = array('required' => false, 'type' => 'string', 'default' => '0000-00-00');
|
||||
@@ -9,6 +14,3 @@ $config->programplan->edit->form['realBegan'] = array('required' => false, 'type
|
||||
$config->programplan->edit->form['realEnd'] = array('required' => false, 'type' => 'string', 'default' => '0000-00-00');
|
||||
$config->programplan->edit->form['output'] = array('required' => false, 'type' => 'array', 'default' => array());
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -148,7 +148,8 @@ class programplan extends control
|
||||
$this->app->loadLang('project');
|
||||
if($_POST)
|
||||
{
|
||||
$this->programplan->create($projectID, $this->productID, $planID);
|
||||
$formData = form::data($this->config->programplan->create->form);
|
||||
$this->programplan->create($formData, $projectID, $this->productID, $planID);
|
||||
if(dao::isError())
|
||||
{
|
||||
$errors = dao::getError();
|
||||
@@ -309,44 +310,42 @@ class programplan extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理甘特图拖拽事件数据。
|
||||
* Response gantt drag event.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxResponseGanttDragEvent()
|
||||
{
|
||||
if(!empty($_POST))
|
||||
{
|
||||
if(!isset($_POST['id']) or empty($_POST['id'])) return $this->send(array('result' => 'fail', 'message' => ''));
|
||||
$objectID = $_POST['id'];
|
||||
if(empty($_POST['id']) || empty($_POST['type'])) return $this->send(array('result' => 'fail', 'message' => ''));
|
||||
|
||||
$this->loadModel('task')->updateEsDateByGantt($objectID, $_POST['type']);
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
$objectID = $_POST['id'];
|
||||
$objectType = $_POST['type'];
|
||||
$this->loadModel('task')->updateEsDateByGantt($objectID, $objectType);
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
|
||||
return $this->send(array('result' => 'success'));
|
||||
}
|
||||
return $this->send(array('result' => 'success'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理甘特图移动事件数据。
|
||||
* Response gantt move event.
|
||||
*
|
||||
* @access public
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxResponseGanttMoveEvent()
|
||||
{
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$idList = explode('-', $_POST['id']);
|
||||
$taskID = $idList[1];
|
||||
if(empty($_POST['id'])) return $this->send(array('result' => 'fail', 'message' => ''));
|
||||
|
||||
$this->loadModel('task')->updateOrderByGantt();
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
$this->loadModel('action')->create('task', $taskID, 'ganttMove');
|
||||
return $this->send(array('result' => 'success'));
|
||||
}
|
||||
$idList = explode('-', $_POST['id']);
|
||||
$taskID = !empty($idList[1]) ? $idList[1] : 0;
|
||||
if(empty($taskID)) return $this->send(array('result' => 'fail', 'message' => ''));
|
||||
|
||||
$this->loadModel('task')->updateOrderByGantt();
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
|
||||
$this->loadModel('action')->create('task', $taskID, 'ganttMove');
|
||||
return $this->send(array('result' => 'success'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,19 +13,6 @@
|
||||
<?php
|
||||
class programplanModel extends model
|
||||
{
|
||||
/**
|
||||
* Set menu.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function setMenu($projectID, $productID)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get plan by id.
|
||||
*
|
||||
@@ -150,6 +137,7 @@ class programplanModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取甘特图页面数据。
|
||||
* Get gantt data.
|
||||
*
|
||||
* @param int $executionID
|
||||
@@ -160,27 +148,14 @@ class programplanModel extends model
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getDataForGantt($executionID, $productID, $baselineID = 0, $selectCustom = '', $returnJson = true)
|
||||
public function getDataForGantt(int $executionID, int $productID, int $baselineID = 0, string $selectCustom = '', bool $returnJson = true): string
|
||||
{
|
||||
$this->loadModel('stage');
|
||||
$this->loadModel('execution');
|
||||
|
||||
$plans = $this->getStage($executionID, $productID, 'all', 'order');
|
||||
if($baselineID)
|
||||
{
|
||||
$baseline = $this->loadModel('cm')->getByID($baselineID);
|
||||
$oldData = json_decode($baseline->data);
|
||||
$oldPlans = $oldData->stage;
|
||||
foreach($oldPlans as $id => $oldPlan)
|
||||
{
|
||||
if(!isset($plans[$id])) continue;
|
||||
$plans[$id]->version = $oldPlan->version;
|
||||
$plans[$id]->name = $oldPlan->name;
|
||||
$plans[$id]->milestone = $oldPlan->milestone;
|
||||
$plans[$id]->begin = $oldPlan->begin;
|
||||
$plans[$id]->end = $oldPlan->end;
|
||||
}
|
||||
}
|
||||
|
||||
if($baselineID) $plans = $this->getBaselineData($baselineID, $plans);
|
||||
|
||||
$today = helper::today();
|
||||
$datas = array();
|
||||
@@ -380,6 +355,33 @@ class programplanModel extends model
|
||||
return $returnJson ? json_encode($datas) : $datas;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取基线数据。
|
||||
* Get baseline data.
|
||||
*
|
||||
* @param int $baselineID
|
||||
* @param array $plans
|
||||
* @access private
|
||||
* @return array
|
||||
*/
|
||||
private function getBaselineData(int $baselineID, array $plans): array
|
||||
{
|
||||
$baseline = $this->loadModel('cm')->getByID($baselineID);
|
||||
$oldData = json_decode($baseline->data);
|
||||
$oldPlans = $oldData->stage;
|
||||
foreach($oldPlans as $id => $oldPlan)
|
||||
{
|
||||
if(!isset($plans[$id])) continue;
|
||||
$plans[$id]->version = $oldPlan->version;
|
||||
$plans[$id]->name = $oldPlan->name;
|
||||
$plans[$id]->milestone = $oldPlan->milestone;
|
||||
$plans[$id]->begin = $oldPlan->begin;
|
||||
$plans[$id]->end = $oldPlan->end;
|
||||
}
|
||||
|
||||
return $plans;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get gantt data group by assigned.
|
||||
*
|
||||
@@ -617,11 +619,11 @@ class programplanModel extends model
|
||||
/**
|
||||
* Process plans.
|
||||
*
|
||||
* @param int $plans
|
||||
* @param array $plans
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function processPlans($plans)
|
||||
private function processPlans(array $plans)
|
||||
{
|
||||
foreach($plans as $planID => $plan) $plans[$planID] = $this->processPlan($plan);
|
||||
return $plans;
|
||||
@@ -683,42 +685,60 @@ class programplanModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a plan.
|
||||
* 创建/设置一个项目阶段。
|
||||
* Create/Set a project plan/phase.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param int $productID
|
||||
* @param int $parentID
|
||||
* @param array $formData
|
||||
* @param int $projectID
|
||||
* @param int $productID
|
||||
* @param int $parentID
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function create($projectID = 0, $productID = 0, $parentID = 0)
|
||||
public function create(array $formData, int $projectID = 0, int $productID = 0, int $parentID = 0): bool
|
||||
{
|
||||
$data = (array)fixer::input('post')->get();
|
||||
extract($data);
|
||||
/* Get every value from formData without use extract(). */
|
||||
$planIDList = $formData['planIDList'];
|
||||
$names = $formData['names'];
|
||||
$PM = $formData['PM'];
|
||||
$percents = $formData['percents'];
|
||||
$attributes = $formData['attributes'];
|
||||
$acl = $formData['acl'];
|
||||
$milestone = $formData['milestone'];
|
||||
$begin = $formData['begin'];
|
||||
$end = $formData['end'];
|
||||
$realBegan = $formData['realBegan'];
|
||||
$realEnd = $formData['realEnd'];
|
||||
$desc = $formData['desc'];
|
||||
$orders = $formData['orders'];
|
||||
$type = $formData['type'];
|
||||
$codes = $formData['codes'];
|
||||
$output = $formData['output'];
|
||||
|
||||
/* Determine if a task has been created under the parent phase. */
|
||||
if(!$this->isCreateTask($parentID)) return dao::$errors['message'][] = $this->lang->programplan->error->createdTask;
|
||||
|
||||
/* The child phase type setting is the same as the parent phase. */
|
||||
$parentAttribute = '';
|
||||
$parentPercent = 0;
|
||||
if($parentID)
|
||||
{
|
||||
$parentStage = $this->getByID($parentID);
|
||||
$parentAttribute = $parentStage->attribute;
|
||||
$parentPercent = $parentStage->percent;
|
||||
$parentACL = $parentStage->acl;
|
||||
}
|
||||
|
||||
/* Remove empty items and get same items in array. */
|
||||
$names = array_filter($names);
|
||||
$sameNames = array_diff_assoc($names, array_unique($names));
|
||||
|
||||
$project = $this->loadModel('project')->getByID($projectID);
|
||||
/* Check weather need to set code and compute same code. */
|
||||
$setCode = (isset($this->config->setCode) and $this->config->setCode == 1) ? true : false;
|
||||
$sameCodes = $setCode ? $this->checkCodeUnique($codes, isset($planIDList) ? $planIDList : '') : false;
|
||||
|
||||
/* Prepare the plans user inputted. Process the plan which names not empty only. */
|
||||
$project = $this->loadModel('project')->getByID($projectID);
|
||||
$setPercent = (isset($this->config->setPercent) and $this->config->setPercent == 1) ? true : false;
|
||||
$datas = array();
|
||||
$plans = array();
|
||||
foreach($names as $key => $name)
|
||||
{
|
||||
if(empty($name)) continue;
|
||||
@@ -729,8 +749,6 @@ class programplanModel extends model
|
||||
$plan->project = $projectID;
|
||||
$plan->parent = $parentID ? $parentID : $projectID;
|
||||
$plan->name = $names[$key];
|
||||
if($setCode) $plan->code = $codes[$key];
|
||||
if($setPercent) $plan->percent = $percents[$key];
|
||||
$plan->attribute = (empty($parentID) or $parentAttribute == 'mix') ? $attributes[$key] : $parentAttribute;
|
||||
$plan->milestone = $milestone[$key];
|
||||
$plan->output = empty($output[$key]) ? '' : implode(',', $output[$key]);
|
||||
@@ -738,25 +756,26 @@ class programplanModel extends model
|
||||
$plan->PM = empty($PM[$key]) ? '' : $PM[$key];
|
||||
$plan->desc = empty($desc[$key]) ? '' : $desc[$key];
|
||||
$plan->hasProduct = $project->hasProduct;
|
||||
if($setCode) $plan->code = $codes[$key];
|
||||
if($setPercent) $plan->percent = $percents[$key];
|
||||
|
||||
if(!empty($begin[$key])) $plan->begin = $begin[$key];
|
||||
if(!empty($end[$key])) $plan->end = $end[$key];
|
||||
if(!empty($realBegan[$key])) $plan->realBegan = $realBegan[$key];
|
||||
if(!empty($realEnd[$key])) $plan->realEnd = $realEnd[$key];
|
||||
|
||||
$datas[] = $plan;
|
||||
$plans[] = $plan;
|
||||
}
|
||||
|
||||
if(empty($datas))
|
||||
if(empty($plans))
|
||||
{
|
||||
dao::$errors['message'][] = sprintf($this->lang->error->notempty, $this->lang->programplan->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
$totalPercent = 0;
|
||||
$totalDevType = 0;
|
||||
$milestone = 0;
|
||||
foreach($datas as $index => $plan)
|
||||
foreach($plans as $index => $plan)
|
||||
{
|
||||
if(!empty($sameNames) and in_array($plan->name, $sameNames)) dao::$errors[$index]['name'] = empty($type) ? $this->lang->programplan->error->sameName : str_replace($this->lang->execution->stage, '', $this->lang->programplan->error->sameName);
|
||||
if($setCode and $sameCodes !== true and !empty($sameCodes) and in_array($plan->code, $sameCodes)) dao::$errors[$index]['code'] = sprintf($this->lang->error->repeat, $plan->type == 'stage' ? $this->lang->execution->code : $this->lang->code, $plan->code);
|
||||
@@ -838,7 +857,7 @@ class programplanModel extends model
|
||||
|
||||
if(!isset($orders)) $orders = array();
|
||||
asort($orders);
|
||||
if(count($orders) < count($datas))
|
||||
if(count($orders) < count($plans))
|
||||
{
|
||||
$orderIndex = empty($orders) ? 0 : count($orders);
|
||||
$lastID = $this->dao->select('id')->from(TABLE_EXECUTION)->orderBy('id_desc')->fetch('id');
|
||||
@@ -1602,13 +1621,14 @@ class programplanModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取阶段同一层级信息。
|
||||
* Get plan's siblings.
|
||||
*
|
||||
* @param string|int|array $planIdList
|
||||
* @param string|int|array $planIdList
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getSiblings($planIdList)
|
||||
public function getSiblings(array|string|int $planIdList): array
|
||||
{
|
||||
if(is_numeric($planIdList)) $planIdList = (array)$planIdList;
|
||||
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* The tao file of programplan module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
|
||||
* @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
* @author lanzongjun <lanzongjun@easycorp.ltd>
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
class programplanTao extends programplanModel
|
||||
{
|
||||
|
||||
|
||||
@@ -7,23 +7,39 @@ su('admin');
|
||||
/**
|
||||
|
||||
title=测试 programplanModel->getByID();
|
||||
timeout=0
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
获取阶段131 >> 阶段31,project31
|
||||
获取阶段132 >> 阶段32,project32
|
||||
获取阶段133 >> 阶段33,project33
|
||||
获取阶段134 >> 阶段34,project34
|
||||
获取阶段135 >> 阶段35,project35
|
||||
- 判断项目阶段1的name是否为项目1
|
||||
- 属性name @项目1
|
||||
- 属性code @project1
|
||||
|
||||
- 判断项目阶段2的name是否为项目2
|
||||
- 属性name @项目2
|
||||
- 属性code @project2
|
||||
|
||||
- 判断项目阶段3的type是否为project属性type @project
|
||||
|
||||
- 判断项目阶段1的milestone,setMilestone在另外一种情况下是否为0
|
||||
- 属性milestone @0
|
||||
- 属性setMilestone @0
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
$planIDList = array('131', '132', '133', '134', '135');
|
||||
function initData()
|
||||
{
|
||||
zdTable('project')->config('getbyid')->gen(5);
|
||||
}
|
||||
|
||||
initData();
|
||||
|
||||
$planIDList = array('1', '2' ,'3' ,'4', '5');
|
||||
|
||||
$programplan = new programplanTest();
|
||||
|
||||
r($programplan->getByIDTest($planIDList[0])) && p('name,code') && e('阶段31,project31'); // 获取阶段131
|
||||
r($programplan->getByIDTest($planIDList[1])) && p('name,code') && e('阶段32,project32'); // 获取阶段132
|
||||
r($programplan->getByIDTest($planIDList[2])) && p('name,code') && e('阶段33,project33'); // 获取阶段133
|
||||
r($programplan->getByIDTest($planIDList[3])) && p('name,code') && e('阶段34,project34'); // 获取阶段134
|
||||
r($programplan->getByIDTest($planIDList[4])) && p('name,code') && e('阶段35,project35'); // 获取阶段135
|
||||
r($programplan->getByIDTest($planIDList[0])) && p('name,code') && e('项目1,project1'); // 判断项目阶段1的name是否为项目1
|
||||
r($programplan->getByIDTest($planIDList[1])) && p('name,code') && e('项目2,project2'); // 判断项目阶段2的name是否为项目2
|
||||
r($programplan->getByIDTest($planIDList[2])) && p('type') && e('project'); // 判断项目阶段3的type是否为project
|
||||
r($programplan->getByIDTest($planIDList[0])) && p('milestone,setMilestone') && e('0,0'); // 判断项目阶段1的milestone,setMilestone在另外一种情况下是否为0
|
||||
@@ -5,33 +5,16 @@ include dirname(__FILE__, 2) . '/programplan.class.php';
|
||||
zdTable('user')->gen(5);
|
||||
su('admin');
|
||||
|
||||
$execution = zdTable('project');
|
||||
$execution->id->range('1-5');
|
||||
$execution->name->range('瀑布项目1,阶段a,阶段a子1,阶段a子1子1,阶段b');
|
||||
$execution->type->range('project,stage{4}');
|
||||
$execution->project->range('0,1{4}');
|
||||
$execution->parent->range('0,1,2,3,1');
|
||||
$execution->path->range("`,1,`,`,1,2,`,`,1,2,3,`,`,1,2,3,4,`,`,1,5,`");
|
||||
$execution->status->range('doing,doing,doing,closed,suspended');
|
||||
$execution->openedBy->range('admin,user1');
|
||||
$execution->begin->range('20220112 000000:0')->type('timestamp')->format('YY/MM/DD');
|
||||
$execution->end->range('20220212 000000:0')->type('timestamp')->format('YY/MM/DD');
|
||||
$execution->realBegan->range('20220212 000000:0')->type('timestamp')->format('YY/MM/DD');
|
||||
$execution->gen(5);
|
||||
|
||||
/**
|
||||
|
||||
title=测试programplanModel->getSiblings();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
测试id为2时获取兄弟阶段的的名称 >> 阶段b
|
||||
测试id为2时获取自己兄弟阶段的个数 >> 1
|
||||
测试id为4时获取自己兄弟阶段的个数 >> 0
|
||||
|
||||
pid=0
|
||||
*/
|
||||
|
||||
$plan = new programplanTest();
|
||||
zdTable('project')->config('getsiblings')->gen(5);
|
||||
$plan = new programplanTest();
|
||||
|
||||
$topPlan = $plan->getSiblingsTest(2);
|
||||
$topPlanCount = count($topPlan[2]);
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
title: zt_getbyid
|
||||
author: shenshulong
|
||||
version: '1.0'
|
||||
fields:
|
||||
- field: id
|
||||
range: 1-5
|
||||
- field: project
|
||||
range: 1-5
|
||||
- field: name
|
||||
range: 1-5
|
||||
prefix: '项目'
|
||||
- field: code
|
||||
range: 1-5
|
||||
prefix: 'project'
|
||||
- field: model
|
||||
range: scrum
|
||||
- field: parent
|
||||
range: 0-3
|
||||
- field: milestone
|
||||
range: 0-1
|
||||
- field: auth
|
||||
range: '[]'
|
||||
- field: type
|
||||
range: 'project'
|
||||
- field: grade
|
||||
range: 1
|
||||
- field: days
|
||||
range: 1
|
||||
- field: status
|
||||
range: 'wait'
|
||||
- field: desc
|
||||
range: 1-5
|
||||
prefix: '项目描述'
|
||||
- field: budget
|
||||
range: '100000,200000'
|
||||
- field: budgetUnit
|
||||
range: 'CNY'
|
||||
- field: percent
|
||||
range: '0-0'
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
title: zt_getsibiings
|
||||
author: jukui
|
||||
version: '1.0'
|
||||
fields:
|
||||
- field: id
|
||||
range: 1-5
|
||||
- field: project
|
||||
range: 1-5
|
||||
- field: name
|
||||
range: '瀑布项目1,阶段a,阶段a子1,阶段a子1子1,阶段b'
|
||||
- field: parent
|
||||
range: '0,1,2,3,1'
|
||||
- field: type
|
||||
range: '0,1{4}'
|
||||
- field: grade
|
||||
range: 1
|
||||
- field: days
|
||||
range: 1
|
||||
- field: status
|
||||
range: 'doing,doing,doing,closed,suspended'
|
||||
- field: desc
|
||||
range: 1-5
|
||||
prefix: '项目描述'
|
||||
- field: path
|
||||
range: "`,1,`,`,1,2,`,`,1,2,3,`,`,1,2,3,4,`,`,1,5,`"
|
||||
@@ -19,6 +19,8 @@ class programplanTest
|
||||
{
|
||||
$object = $this->objectModel->getByID($planID);
|
||||
|
||||
if(!$object->setMilestone) $object->setMilestone = 0;
|
||||
|
||||
if(dao::isError()) return dao::getError();
|
||||
|
||||
return $object;
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* The zen file of programplan module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
|
||||
* @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
* @author lanzongjun <lanzongjun@easycorp.ltd>
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
class programplanZen extends programplan
|
||||
{
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user