* Split program plan edit function.

This commit is contained in:
liuchenglong
2023-05-06 01:41:38 +00:00
parent e6849ef172
commit 158152c119
6 changed files with 228 additions and 116 deletions
+14
View File
@@ -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());
+14 -37
View File
@@ -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);
}
/**
+93 -79
View File
@@ -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;
}
}
+36
View File
@@ -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();
}
}
+70
View File
@@ -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();
}
}