* Split program plan edit function.
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
$config->programplan->edit = new stdClass();
|
||||
$config->programplan->edit->form = array();
|
||||
$config->programplan->edit->form['begin'] = array('required' => false, 'type' => 'string', 'default' => '0000-00-00');
|
||||
$config->programplan->edit->form['end'] = array('required' => false, 'type' => 'string', 'default' => '0000-00-00');
|
||||
$config->programplan->edit->form['realBegan'] = array('required' => false, 'type' => 'string', 'default' => '0000-00-00');
|
||||
$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());
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -231,60 +231,37 @@ class programplan extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑阶段内容。
|
||||
* Edit a project plan.
|
||||
*
|
||||
* @param int $planID
|
||||
* @param int $projectID
|
||||
* @param string $planID
|
||||
* @param string $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function edit($planID = 0, $projectID = 0)
|
||||
public function edit(string $planID = 0, string $projectID = 0)
|
||||
{
|
||||
$this->loadModel('project');
|
||||
$this->app->loadLang('execution');
|
||||
$this->app->loadLang('stage');
|
||||
|
||||
$plan = $this->programplan->getByID($planID);
|
||||
|
||||
global $lang;
|
||||
$lang->executionCommon = $lang->execution->stage;
|
||||
include $this->app->getModulePath('', 'execution') . 'lang/' . $this->app->getClientLang() . '.php';
|
||||
$planID = (int)$planID;
|
||||
$projectID = (int)$projectID;
|
||||
$plan = $this->programplan->getByID($planID);
|
||||
|
||||
if($_POST)
|
||||
{
|
||||
$changes = $this->programplan->update($planID, $projectID);
|
||||
$formData = form::data($this->config->programplan->edit->form);
|
||||
$postData = $this->programplanZen->beforeEdit($formData);
|
||||
$postData->id = $planID;
|
||||
|
||||
$changes = $this->programplan->update($planID, $projectID, $postData);
|
||||
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
if($changes)
|
||||
{
|
||||
$actionID = $this->loadModel('action')->create('execution', $planID, 'edited');
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
|
||||
$newPlan = $this->programplan->getByID($planID);
|
||||
if($changes) $this->programplanZen->afterEdit($plan, $changes);
|
||||
|
||||
if($plan->parent != $newPlan->parent)
|
||||
{
|
||||
$this->programplan->computeProgress($planID, 'edit');
|
||||
$this->programplan->computeProgress($plan->parent, 'edit', true);
|
||||
}
|
||||
}
|
||||
$locate = isonlybody() ? 'parent' : inlink('browse', "program=$plan->program&type=lists");
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $locate));
|
||||
}
|
||||
|
||||
$parentStage = $this->project->getByID($plan->parent, 'stage');
|
||||
|
||||
$this->view->title = $this->lang->programplan->edit;
|
||||
$this->view->position[] = $this->lang->programplan->edit;
|
||||
$this->view->isCreateTask = $this->programplan->isCreateTask($planID);
|
||||
$this->view->plan = $plan;
|
||||
$this->view->parentStageList = $this->programplan->getParentStageList($this->session->project, $planID, $plan->product);
|
||||
$this->view->enableOptionalAttr = (empty($parentStage) or (!empty($parentStage) and $parentStage->attribute == 'mix'));
|
||||
$this->view->isTopStage = $this->programplan->checkTopStage($planID);
|
||||
$this->view->isLeafStage = $this->programplan->checkLeafStage($planID);
|
||||
$this->view->PMUsers = $this->loadModel('user')->getPairs('noclosed|nodeleted|pmfirst', $plan->PM);
|
||||
|
||||
$this->display();
|
||||
$this->programplanZen->buildEditView($plan);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1067,86 +1067,25 @@ class programplanModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新阶段。
|
||||
* Update a plan.
|
||||
*
|
||||
* @param int $planID
|
||||
* @param int $projectID
|
||||
* @param int $planID
|
||||
* @param int $projectID
|
||||
* @param object $plan
|
||||
* @access public
|
||||
* @return bool|array
|
||||
*/
|
||||
public function update($planID = 0, $projectID = 0)
|
||||
public function update(int $planID = 0, int $projectID = 0, object $plan): bool|array
|
||||
{
|
||||
/* Get oldPlan and the data from the post. */
|
||||
$oldPlan = $this->getByID($planID);
|
||||
$plan = fixer::input('post')
|
||||
->setDefault('begin', '0000-00-00')
|
||||
->setDefault('end', '0000-00-00')
|
||||
->setDefault('realBegan', '0000-00-00')
|
||||
->setDefault('realEnd', '0000-00-00')
|
||||
->join('output', ',')
|
||||
->get();
|
||||
|
||||
/* Judgment of required items. */
|
||||
if($plan->begin == '0000-00-00') dao::$errors['begin'][] = sprintf($this->lang->error->notempty, $this->lang->programplan->begin);
|
||||
if($plan->end == '0000-00-00') dao::$errors['end'][] = sprintf($this->lang->error->notempty, $this->lang->programplan->end);
|
||||
if(dao::isError()) return false;
|
||||
|
||||
if($plan->parent) $parentStage = $this->getByID($plan->parent);
|
||||
if(isset($parentStage) and $plan->begin < $parentStage->begin)
|
||||
{
|
||||
dao::$errors['begin'] = sprintf($this->lang->programplan->error->letterParent, $parentStage->begin);
|
||||
return false;
|
||||
}
|
||||
if(isset($parentStage) and $plan->end > $parentStage->end)
|
||||
{
|
||||
dao::$errors['end'] = sprintf($this->lang->programplan->error->greaterParent, $parentStage->end);
|
||||
return false;
|
||||
}
|
||||
|
||||
if($projectID) $this->loadModel('execution')->checkBeginAndEndDate($projectID, $plan->begin, $plan->end);
|
||||
if(dao::isError()) return false;
|
||||
|
||||
$setCode = (isset($this->config->setCode) and $this->config->setCode == 1) ? true : false;
|
||||
if($setCode and empty($plan->code))
|
||||
{
|
||||
dao::$errors['code'][] = sprintf($this->lang->error->notempty, $this->lang->execution->code);
|
||||
return false;
|
||||
}
|
||||
if(!$this->checkRequiredItems($oldPlan, $plan, $projectID)) return false;
|
||||
|
||||
$setCode = (isset($this->config->setCode) and $this->config->setCode == 1) ? true : false;
|
||||
$planChanged = ($oldPlan->name != $plan->name || $oldPlan->milestone != $plan->milestone || $oldPlan->begin != $plan->begin || $oldPlan->end != $plan->end);
|
||||
|
||||
$setPercent = isset($this->config->setPercent) and $this->config->setPercent == 1 ? true : false;
|
||||
if($plan->parent > 0)
|
||||
{
|
||||
$plan->attribute = $parentStage->attribute == 'mix' ? $plan->attribute : $parentStage->attribute;
|
||||
$plan->acl = $parentStage->acl;
|
||||
if($setPercent)
|
||||
{
|
||||
$parentPercent = $parentStage->percent;
|
||||
$childrenTotalPercent = $this->getTotalPercent($parentStage, true);
|
||||
$childrenTotalPercent = $plan->parent == $oldPlan->parent ? ($childrenTotalPercent - $oldPlan->percent + $plan->percent) : ($childrenTotalPercent + $plan->percent);
|
||||
if($childrenTotalPercent > 100) return dao::$errors['percent'][] = $this->lang->programplan->error->percentOver;
|
||||
}
|
||||
|
||||
/* If child plan has milestone, update parent plan set milestone eq 0 . */
|
||||
if($plan->milestone and $parentStage->milestone) $this->dao->update(TABLE_PROJECT)->set('milestone')->eq(0)->where('id')->eq($oldPlan->parent)->exec();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Synchronously update sub-phase permissions. */
|
||||
$childrenIDList = $this->dao->select('id')->from(TABLE_PROJECT)->where('parent')->eq($oldPlan->id)->fetchAll('id');
|
||||
if(!empty($childrenIDList)) $this->dao->update(TABLE_PROJECT)->set('acl')->eq($plan->acl)->where('id')->in(array_keys($childrenIDList))->exec();
|
||||
|
||||
/* The workload of the parent plan cannot exceed 100%. */
|
||||
$oldPlan->parent = $plan->parent;
|
||||
if($setPercent)
|
||||
{
|
||||
$totalPercent = $this->getTotalPercent($oldPlan);
|
||||
$totalPercent = $totalPercent + $plan->percent;
|
||||
if($totalPercent > 100) return dao::$errors['percent'][] = $this->lang->programplan->error->percentOver;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set planDuration and realDuration. */
|
||||
if($this->config->edition == 'max')
|
||||
{
|
||||
@@ -1156,7 +1095,6 @@ class programplanModel extends model
|
||||
|
||||
if($planChanged) $plan->version = $oldPlan->version + 1;
|
||||
if(empty($plan->parent)) $plan->parent = $projectID;
|
||||
|
||||
$parentStage = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($plan->parent)->andWhere('type')->eq('stage')->fetch();
|
||||
|
||||
/* Fix bug #22030. Reset field name for show dao error. */
|
||||
@@ -1166,19 +1104,20 @@ class programplanModel extends model
|
||||
$relatedExecutionsID = $this->loadModel('execution')->getRelatedExecutions($planID);
|
||||
$relatedExecutionsID = !empty($relatedExecutionsID) ? implode(',', array_keys($relatedExecutionsID)) : '0';
|
||||
|
||||
$this->dao->update(TABLE_PROJECT)->data($plan)
|
||||
->autoCheck()
|
||||
->batchCheck($this->config->programplan->edit->requiredFields, 'notempty')
|
||||
->checkIF($plan->end != '0000-00-00', 'end', 'ge', $plan->begin)
|
||||
->checkIF(!empty($plan->percent), 'percent', 'float')
|
||||
->checkIF(!empty($plan->name), 'name', 'unique', "id in ({$relatedExecutionsID}) and type in ('sprint','stage') and `project` = {$oldPlan->project} and `deleted` = '0'" . ($parentStage ? " and `parent` = {$oldPlan->parent}" : ''))
|
||||
->checkIF(!empty($plan->code) and $setCode, 'code', 'unique', "id != $planID and type in ('sprint','stage','kanban') and `deleted` = '0'")
|
||||
->where('id')->eq($planID)
|
||||
->exec();
|
||||
$conditions = array();
|
||||
$conditions['requiredFields'] = $this->config->programplan->edit->requiredFields;
|
||||
$conditions['relatedExecutionsID'] = $relatedExecutionsID;
|
||||
$conditions['oldProject'] = $oldPlan->project;
|
||||
$conditions['oldParent'] = $oldPlan->parent;
|
||||
$conditions['parentStage'] = $parentStage;
|
||||
$conditions['setCode'] = $setCode;
|
||||
|
||||
$result = $this->programplanTao->update($plan, $conditions);
|
||||
if(!$result) return false;
|
||||
|
||||
if(dao::isError()) return false;
|
||||
$this->setTreePath($planID);
|
||||
$this->updateSubStageAttr($planID, $plan->attribute);
|
||||
|
||||
if($plan->acl != 'open')
|
||||
{
|
||||
$planIdList = $this->dao->select('id')->from(TABLE_EXECUTION)->where('path')->like("%,$planID,%")->andWhere('type')->ne('project')->fetchAll('id');
|
||||
@@ -1691,4 +1630,79 @@ class programplanModel extends model
|
||||
|
||||
return $siblingStages;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验提交数据是否必须。
|
||||
* Check required items.
|
||||
*
|
||||
* @param object $oldPlan
|
||||
* @param object $plan
|
||||
* @param int $projectID
|
||||
* @access private
|
||||
* @return bool
|
||||
*/
|
||||
private function checkRequiredItems(object $oldPlan, object $plan, int $projectID): bool
|
||||
{
|
||||
if($plan->begin == '0000-00-00') dao::$errors['begin'][] = sprintf($this->lang->error->notempty, $this->lang->programplan->begin);
|
||||
if($plan->end == '0000-00-00') dao::$errors['end'][] = sprintf($this->lang->error->notempty, $this->lang->programplan->end);
|
||||
if(dao::isError()) return false;
|
||||
|
||||
if($plan->parent) $parentStage = $this->getByID($plan->parent);
|
||||
if(isset($parentStage) and $plan->begin < $parentStage->begin)
|
||||
{
|
||||
dao::$errors['begin'] = sprintf($this->lang->programplan->error->letterParent, $parentStage->begin);
|
||||
return false;
|
||||
}
|
||||
if(isset($parentStage) and $plan->end > $parentStage->end)
|
||||
{
|
||||
dao::$errors['end'] = sprintf($this->lang->programplan->error->greaterParent, $parentStage->end);
|
||||
return false;
|
||||
}
|
||||
|
||||
if($projectID) $this->loadModel('execution')->checkBeginAndEndDate($projectID, $plan->begin, $plan->end);
|
||||
if(dao::isError()) return false;
|
||||
|
||||
|
||||
$setCode = (isset($this->config->setCode) and $this->config->setCode == 1) ? true : false;
|
||||
if($setCode and empty($plan->code))
|
||||
{
|
||||
dao::$errors['code'][] = sprintf($this->lang->error->notempty, $this->lang->execution->code);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$setPercent = isset($this->config->setPercent) and $this->config->setPercent == 1 ? true : false;
|
||||
if($plan->parent > 0)
|
||||
{
|
||||
$plan->attribute = $parentStage->attribute == 'mix' ? $plan->attribute : $parentStage->attribute;
|
||||
$plan->acl = $parentStage->acl;
|
||||
if($setPercent)
|
||||
{
|
||||
$parentPercent = $parentStage->percent;
|
||||
$childrenTotalPercent = $this->getTotalPercent($parentStage, true);
|
||||
$childrenTotalPercent = $plan->parent == $oldPlan->parent ? ($childrenTotalPercent - $oldPlan->percent + $plan->percent) : ($childrenTotalPercent + $plan->percent);
|
||||
if($childrenTotalPercent > 100) return dao::$errors['percent'][] = $this->lang->programplan->error->percentOver;
|
||||
}
|
||||
|
||||
/* If child plan has milestone, update parent plan set milestone eq 0 . */
|
||||
if($plan->milestone and $parentStage->milestone) $this->dao->update(TABLE_PROJECT)->set('milestone')->eq(0)->where('id')->eq($oldPlan->parent)->exec();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Synchronously update sub-phase permissions. */
|
||||
$childrenIDList = $this->dao->select('id')->from(TABLE_PROJECT)->where('parent')->eq($oldPlan->id)->fetchAll('id');
|
||||
if(!empty($childrenIDList)) $this->dao->update(TABLE_PROJECT)->set('acl')->eq($plan->acl)->where('id')->in(array_keys($childrenIDList))->exec();
|
||||
|
||||
/* The workload of the parent plan cannot exceed 100%. */
|
||||
$oldPlan->parent = $plan->parent;
|
||||
if($setPercent)
|
||||
{
|
||||
$totalPercent = $this->getTotalPercent($oldPlan);
|
||||
$totalPercent = $totalPercent + $plan->percent;
|
||||
if($totalPercent > 100) return dao::$errors['percent'][] = $this->lang->programplan->error->percentOver;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
class programplanTao extends programplanModel
|
||||
{
|
||||
|
||||
/**
|
||||
* 更新项目阶段。
|
||||
* update program plan.
|
||||
*
|
||||
* @param object $plan
|
||||
* @param array $conditions
|
||||
* @access protected
|
||||
* @return bool
|
||||
*/
|
||||
protected function updateRow(object $plan, array $conditions): bool
|
||||
{
|
||||
$requiredFields = $conditions['requiredFields'] ?? '';
|
||||
$ids = $conditions['ids'] ?? '';
|
||||
$project = $conditions['project'] ?? '';
|
||||
$parentStage = $conditions['parentStage'] ?? '';
|
||||
$parent = $conditions['parent'] ?? '';
|
||||
$setCode = $conditions['setCode'] ?? '';
|
||||
|
||||
$this->dao->update(TABLE_PROJECT)->data($plan)
|
||||
->autoCheck()
|
||||
->batchCheckIF($requiredFields, $requiredFields, 'notempty')
|
||||
->checkIF($plan->end != '0000-00-00', 'end', 'ge', $plan->begin)
|
||||
->checkIF(!empty($plan->percent), 'percent', 'float')
|
||||
->checkIF(!empty($plan->name) && $ids && $project && $parentStage && $parent, 'name', 'unique', "id in ({$ids}) and type in ('sprint','stage') and `project` = {$project} and `deleted` = '0'" . ($parentStage ? " and `parent` = {$parent}" : ''))
|
||||
->checkIF(!empty($plan->code) and $setCode, 'code', 'unique', "id != {$plan->id} and type in ('sprint','stage','kanban') and `deleted` = '0'")
|
||||
->where('id')->eq($plan->id)
|
||||
->exec();
|
||||
|
||||
return !dao::isError();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
class programplanZen extends programplan
|
||||
{
|
||||
/**
|
||||
* 处理编辑阶段的请求数据。
|
||||
* Processing edit request data.
|
||||
*
|
||||
* @param object $formData
|
||||
* @access protected
|
||||
* @return object
|
||||
*/
|
||||
protected function beforeEdit(object $formData): object
|
||||
{
|
||||
$rowData = $formData->rowdata;
|
||||
$plan = $formData->join($rowData->output, ',')->get();
|
||||
return $plan;
|
||||
}
|
||||
|
||||
/**
|
||||
* 阶段编辑后数据处理。
|
||||
* Handle data after edit.
|
||||
*
|
||||
* @param object $plan
|
||||
* @param array $changes
|
||||
* @access protected
|
||||
* @return viod
|
||||
*/
|
||||
protected function afterEdit(object $plan, array $changes)
|
||||
{
|
||||
$actionID = $this->loadModel('action')->create('execution', $plan->id, 'edited');
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
|
||||
$newPlan = $this->programplan->getByID($plan->id);
|
||||
|
||||
if($plan->parent != $newPlan->parent)
|
||||
{
|
||||
$this->programplan->computeProgress($plan->id, 'edit');
|
||||
$this->programplan->computeProgress($plan->parent, 'edit', true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成编辑阶段数据。
|
||||
* Build edit view data.
|
||||
*
|
||||
* @param object $plan
|
||||
* @access protected
|
||||
* @return viod
|
||||
*/
|
||||
protected function buildEditView(object $plan)
|
||||
{
|
||||
$this->loadModel('project');
|
||||
$this->app->loadLang('execution');
|
||||
$this->app->loadLang('stage');
|
||||
|
||||
$parentStage = $this->project->getByID($plan->parent, 'stage');
|
||||
|
||||
$this->view->title = $this->lang->programplan->edit;
|
||||
$this->view->position[] = $this->lang->programplan->edit;
|
||||
$this->view->isCreateTask = $this->programplan->isCreateTask($plan->id);
|
||||
$this->view->plan = $plan;
|
||||
$this->view->parentStageList = $this->programplan->getParentStageList($this->session->project, $plan->id, $plan->product);
|
||||
$this->view->enableOptionalAttr = (empty($parentStage) or (!empty($parentStage) and $parentStage->attribute == 'mix'));
|
||||
$this->view->isTopStage = $this->programplan->checkTopStage($plan->id);
|
||||
$this->view->isLeafStage = $this->programplan->checkLeafStage($plan->id);
|
||||
$this->view->PMUsers = $this->loadModel('user')->getPairs('noclosed|nodeleted|pmfirst', $plan->PM);
|
||||
$this->display();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user