diff --git a/module/execution/model.php b/module/execution/model.php index 1e21566f6d..b27463f5d3 100755 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -2864,10 +2864,11 @@ class executionModel extends model { $this->loadModel('task'); + $dateExceed = ''; $taskStories = array(); $parents = array(); $execution = $this->getByID($executionID); - $tasks = $this->dao->select('id,execution,assignedTo,story,consumed,status,parent')->from(TABLE_TASK)->where('id')->in($this->post->tasks)->fetchAll('id'); + $tasks = $this->dao->select('id,execution,assignedTo,story,consumed,status,parent,estStarted,deadline')->from(TABLE_TASK)->where('id')->in($this->post->tasks)->fetchAll('id'); foreach($tasks as $task) { /* Save the assignedToes and stories, should linked to execution. */ @@ -2887,6 +2888,13 @@ class executionModel extends model $data->canceledDate = null; } + if(!empty($this->config->limitTaskDate)) + { + if($task->estStarted < $execution->begin or $task->estStarted > $execution->end or $task->deadline > $execution->end or $task->deadline < $execution->begin) $dateExceed .= "#{$task->id},"; + if($task->estStarted < $execution->begin or $task->estStarted > $execution->end) $data->estStarted = $execution->begin; + if($task->deadline > $execution->end or $task->deadline < $execution->begin) $data->deadline = $execution->end; + } + /* Update tasks. */ $this->dao->update(TABLE_TASK)->data($data)->where('id')->eq($task->id)->exec(); unset($data->status); @@ -2895,6 +2903,12 @@ class executionModel extends model $this->loadModel('action')->create('task', $task->id, 'moved', '', $task->execution); } + if(!empty($dateExceed)) + { + $dateExceed = trim($dateExceed, ','); + echo js::alert(sprintf($this->lang->task->error->dateExceed, $dateExceed)); + } + /* Get stories of children task. */ if(!empty($parents)) { @@ -3045,6 +3059,12 @@ class executionModel extends model return false; } + if(!empty($this->config->limitTaskDate)) + { + $this->task->checkEstStartedAndDeadline($executionID, $task->estStarted, $task->deadline); + if(dao::isError()) return false; + } + $tasks[$key] = $task; } diff --git a/module/story/model.php b/module/story/model.php index 340af0adf3..c966219470 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -2489,6 +2489,13 @@ class storyModel extends model dao::$errors['message'][] = sprintf($this->lang->error->notempty, $this->lang->task->$field); return false; } + + if(!empty($this->config->limitTaskDate)) + { + $this->task->checkEstStartedAndDeadline($executionID, $task->estStarted, $task->deadline); + if(dao::isError()) return false; + } + if($task->estimate) $task->estimate = (float)$task->estimate; } diff --git a/module/task/lang/de.php b/module/task/lang/de.php index cf366874e1..27ed9c5da6 100644 --- a/module/task/lang/de.php +++ b/module/task/lang/de.php @@ -294,6 +294,9 @@ $lang->task->error->leftEmptyAB = 'When the task status is %s, "Hours Left $lang->task->error->leftEmpty = 'Task#%sWhen the task status is %s, "Left" cannot be 0'; $lang->task->error->notempty = '%s must be > 0.'; $lang->task->error->teamLeftEmpty = 'Please maintain team hours.'; +$lang->task->error->beginLtExecution = "The 'StartDate' of the task must be greater than or equal the 'Planned Begin' of %s to %s."; +$lang->task->error->endGtExecution = "The 'Deadline' of the task must be less than or equal the 'Planned End' of %s to %s."; +$lang->task->error->dateExceed = "Because the scheduled date of task %s exceeds the scheduled date of {$lang->execution->common}, it is automatically changed to the scheduled date of {$lang->execution->common}"; /* Report. */ $lang->task->report = new stdclass(); diff --git a/module/task/lang/en.php b/module/task/lang/en.php index d16288a64d..a648e2f19d 100755 --- a/module/task/lang/en.php +++ b/module/task/lang/en.php @@ -294,6 +294,9 @@ $lang->task->error->leftEmptyAB = 'When the task status is %s, "Hours Left $lang->task->error->leftEmpty = 'Task#%sWhen the task status is %s, "Left" cannot be 0'; $lang->task->error->notempty = '%s must be > 0.'; $lang->task->error->teamLeftEmpty = 'Please maintain team hours.'; +$lang->task->error->beginLtExecution = "The 'StartDate' of the task must be greater than or equal the 'Planned Begin' of %s to %s."; +$lang->task->error->endGtExecution = "The 'Deadline' of the task must be less than or equal the 'Planned End' of %s to %s."; +$lang->task->error->dateExceed = "Because the scheduled date of task %s exceeds the scheduled date of {$lang->execution->common}, it is automatically changed to the scheduled date of {$lang->execution->common}"; /* Report. */ $lang->task->report = new stdclass(); diff --git a/module/task/lang/fr.php b/module/task/lang/fr.php index c58f8d7265..56824bc1d3 100644 --- a/module/task/lang/fr.php +++ b/module/task/lang/fr.php @@ -294,6 +294,9 @@ $lang->task->error->leftEmptyAB = 'When the task status is %s, "Hours Left $lang->task->error->leftEmpty = 'Task#%sWhen the task status is %s, "Left" cannot be 0'; $lang->task->error->notempty = '%s must be > 0.'; $lang->task->error->teamLeftEmpty = 'Please maintain team hours.'; +$lang->task->error->beginLtExecution = "The 'StartDate' of the task must be greater than or equal the 'Planned Begin' of %s to %s."; +$lang->task->error->endGtExecution = "The 'Deadline' of the task must be less than or equal the 'Planned End' of %s to %s."; +$lang->task->error->dateExceed = "Because the scheduled date of task %s exceeds the scheduled date of {$lang->execution->common}, it is automatically changed to the scheduled date of {$lang->execution->common}"; /* Report. */ $lang->task->report = new stdclass(); diff --git a/module/task/lang/zh-cn.php b/module/task/lang/zh-cn.php index 6e7aabde02..37527a6428 100755 --- a/module/task/lang/zh-cn.php +++ b/module/task/lang/zh-cn.php @@ -294,6 +294,9 @@ $lang->task->error->leftEmptyAB = '任务状态为%s时,预计剩余不 $lang->task->error->leftEmpty = 'Task#%s任务状态为%s时,剩余不能为0'; $lang->task->error->notempty = '%s必须大于0。'; $lang->task->error->teamLeftEmpty = '请维护团队工时。'; +$lang->task->error->beginLtExecution = "任务开始日期应大于等于%s的开始日期:%s。"; +$lang->task->error->endGtExecution = "任务结束日期应小于等于%s的结束日期:%s。"; +$lang->task->error->dateExceed = "任务%s的计划日期超过该{$lang->execution->common}计划日期,将自动改为{$lang->execution->common}的计划日期。"; /* Report. */ $lang->task->report = new stdclass(); diff --git a/module/task/model.php b/module/task/model.php index 080051259e..84238fa0af 100755 --- a/module/task/model.php +++ b/module/task/model.php @@ -28,6 +28,12 @@ class taskModel extends model return false; } + if(!empty($this->config->limitTaskDate)) + { + $this->checkEstStartedAndDeadline($executionID, $this->post->estStarted, $this->post->deadline); + if(dao::isError()) return false; + } + $executionID = (int)$executionID; $estStarted = '0000-00-00'; $deadline = '0000-00-00'; @@ -52,6 +58,19 @@ class taskModel extends model $deadline = (!isset($this->post->testDeadline[$i]) or (isset($this->post->deadlineDitto[$i]) and $this->post->deadlineDitto[$i] == 'on')) ? $deadline : $this->post->testDeadline[$i]; $assignedTo = (!isset($this->post->testAssignedTo[$i]) or $this->post->testAssignedTo[$i] == 'ditto') ? $assignedTo : $this->post->testAssignedTo[$i]; + if(!empty($this->config->limitTaskDate)) + { + $this->checkEstStartedAndDeadline($executionID, $estStarted, $deadline); + if(dao::isError()) + { + foreach(dao::getError() as $field => $error) + { + dao::$errors[] = $error; + return false; + } + } + } + if($estStarted > $deadline) { dao::$errors[] = "ID: $storyID {$this->lang->task->error->deadlineSmall}"; @@ -402,6 +421,12 @@ class taskModel extends model /* check data. */ foreach($data as $i => $task) { + if(!empty($this->config->limitTaskDate)) + { + $this->checkEstStartedAndDeadline($executionID, $task->estStarted, $task->deadline); + return false; + } + if(!helper::isZeroDate($task->deadline) and $task->deadline < $task->estStarted) { dao::$errors['message'][] = $this->lang->task->error->deadlineSmall; @@ -1063,6 +1088,12 @@ class taskModel extends model return false; } + if(!empty($this->config->limitTaskDate)) + { + $this->checkEstStartedAndDeadline($oldTask->execution, $this->post->estStarted, $this->post->deadline); + if(dao::isError()) return false; + } + if(!empty($_POST['lastEditedDate']) and $oldTask->lastEditedDate != $this->post->lastEditedDate) { dao::$errors[] = $this->lang->error->editedByOther; @@ -1369,6 +1400,12 @@ class taskModel extends model return false; } + if(!empty($this->config->limitTaskDate)) + { + $this->checkEstStartedAndDeadline($oldTask->execution, $task->estStarted, $task->deadline, "task:{$taskID} "); + return false; + } + if(empty($task->closedReason) and $task->status == 'closed') { if($oldTask->status == 'done') $task->closedReason = 'done'; @@ -4451,4 +4488,24 @@ class taskModel extends model $teamMembers = $this->dao->select('account')->from(TABLE_TASKTEAM)->where('task')->eq($taskID)->fetchPairs(); return empty($teamMembers) ? $teamMembers : array_keys($teamMembers); } + + /** + * Check estStarted and deadline date. + * + * @param int $executionID + * @param string $estStarted + * @param string $deadline + * @param string $pre + * @access public + * @return void + */ + public function checkEstStartedAndDeadline($executionID, $estStarted, $deadline, $pre = '') + { + $execution = $this->loadModel('execution')->getByID($executionID); + if(empty($execution) or empty($this->config->limitTaskDate)) return false; + if(empty($execution->multiple)) $this->lang->execution->common = $this->lang->project->common; + + if(!empty($estStarted) and $estStarted < $execution->begin) dao::$errors['estStarted'][] = $pre . sprintf($this->lang->task->error->beginLtExecution, $this->lang->execution->common, $execution->begin); + if(!empty($deadline) and $deadline > $execution->end) dao::$errors['deadline'][] = $pre . sprintf($this->lang->task->error->endGtExecution, $this->lang->execution->common, $execution->end); + } } diff --git a/test/class/task.class.php b/test/class/task.class.php index 88815aa511..0a6fb333f3 100644 --- a/test/class/task.class.php +++ b/test/class/task.class.php @@ -1490,4 +1490,22 @@ class taskTest return $object; } + + /** + * Get the users who finished the multiple task. + * @param int $executionID + * @param string $estStarted + * @param string $deadline + * + * @access public + * @return array + */ + public function checkEstStartedAndDeadlineTest($executionID, $estStarted, $deadline) + { + $object = $this->objectModel->checkEstStartedAndDeadline($executionID, $estStarted, $deadline); + + if(dao::isError()) return dao::getError(); + + return $object; + } } diff --git a/test/model/task/checkeeststartedanddeadline.php b/test/model/task/checkeeststartedanddeadline.php new file mode 100644 index 0000000000..eb30737223 --- /dev/null +++ b/test/model/task/checkeeststartedanddeadline.php @@ -0,0 +1,62 @@ +#!/usr/bin/env php +id->range('1-11'); +$execution->name->setFields(array( + array('field' => 'name1', 'range' => '项目{2},执行{3},迭代{2},阶段{2},看板{2}'), + array('field' => 'name2', 'range' => '1-3'), +)); +$execution->code->setFields(array( + array('field' => 'name1', 'range' => '项目{2},执行{3},迭代{2},阶段{2},看板{2}'), + array('field' => 'name2', 'range' => '1-3'), +)); +$execution->type->range('project{2},sprint{5},waterfall{2},kanban{2}'); +$execution->status->range('doing{11}'); +$execution->parent->range('0'); +$execution->begin->range('20230102 000000:0')->type('timestamp')->format('YY/MM/DD'); +$execution->end->range('20230212 000000:0')->type('timestamp')->format('YY/MM/DD'); +$execution->gen(5); + + +/** + +title=测试 taskModel->checkEstStartedAndDeadline(); +cid=1 +pid=1 + +测试获取执行4 任务开始日期 2000-01-02 结束日期 2040-01-02 是否可以保存 >> 任务开始日期应大于等于迭代的开始日期:2023-01-02。,任务结束日期应小于等于迭代的结束日期:2023-02-12。 +测试获取执行4 任务开始日期 2000-01-02 结束日期 空 是否可以保存 >> 任务开始日期应大于等于迭代的开始日期:2023-01-02。, +测试获取执行4 任务开始日期 2000-01-02 结束日期 2023-01-15 是否可以保存 >> 任务开始日期应大于等于迭代的开始日期:2023-01-02。, +测试获取执行4 任务开始日期 空 结束日期 2040-01-02 是否可以保存 >> ,任务结束日期应小于等于迭代的结束日期:2023-02-12。 +测试获取执行4 任务开始日期 空 结束日期 空 是否可以保存 >> 0 +测试获取执行4 任务开始日期 空 结束日期 2023-01-15 是否可以保存 >> 0 +测试获取执行4 任务开始日期 2023-01-15 结束日期 2040-01-02 是否可以保存 >> ,任务结束日期应小于等于迭代的结束日期:2023-02-12。 +测试获取执行4 任务开始日期 2023-01-15 结束日期 空 是否可以保存 >> 0 +测试获取执行4 任务开始日期 2023-01-15 结束日期 2023-01-15 是否可以保存 >> 0 + +*/ + +$executionID = '4'; +$estStarted = array('2000-01-02', '', '2023-01-15'); +$deadline = array('2040-01-02', '', '2023-01-15'); + +$task = new taskTest(); + +global $tester; +$tester->loadModel('setting')->setItem('system.common.limitTaskDate', 1); + +r($task->checkEstStartedAndDeadlineTest($executionID, $estStarted[0], $deadline[0])) && p('estStarted,deadline') && e('任务开始日期应大于等于迭代的开始日期:2023-01-02。,任务结束日期应小于等于迭代的结束日期:2023-02-12。'); // 测试获取执行4 任务开始日期 2000-01-02 结束日期 2040-01-02 是否可以保存 +r($task->checkEstStartedAndDeadlineTest($executionID, $estStarted[0], $deadline[1])) && p('estStarted,deadline') && e('任务开始日期应大于等于迭代的开始日期:2023-01-02。,'); // 测试获取执行4 任务开始日期 2000-01-02 结束日期 空 是否可以保存 +r($task->checkEstStartedAndDeadlineTest($executionID, $estStarted[0], $deadline[2])) && p('estStarted,deadline') && e('任务开始日期应大于等于迭代的开始日期:2023-01-02。,'); // 测试获取执行4 任务开始日期 2000-01-02 结束日期 2023-01-15 是否可以保存 +r($task->checkEstStartedAndDeadlineTest($executionID, $estStarted[1], $deadline[0])) && p('estStarted,deadline') && e(',任务结束日期应小于等于迭代的结束日期:2023-02-12。'); // 测试获取执行4 任务开始日期 空 结束日期 2040-01-02 是否可以保存 +r($task->checkEstStartedAndDeadlineTest($executionID, $estStarted[1], $deadline[1])) && p('estStarted,deadline') && e(0); // 测试获取执行4 任务开始日期 空 结束日期 空 是否可以保存 +r($task->checkEstStartedAndDeadlineTest($executionID, $estStarted[1], $deadline[2])) && p('estStarted,deadline') && e(0); // 测试获取执行4 任务开始日期 空 结束日期 2023-01-15 是否可以保存 +r($task->checkEstStartedAndDeadlineTest($executionID, $estStarted[2], $deadline[0])) && p('estStarted,deadline') && e(',任务结束日期应小于等于迭代的结束日期:2023-02-12。'); // 测试获取执行4 任务开始日期 2023-01-15 结束日期 2040-01-02 是否可以保存 +r($task->checkEstStartedAndDeadlineTest($executionID, $estStarted[2], $deadline[1])) && p('estStarted,deadline') && e(0); // 测试获取执行4 任务开始日期 2023-01-15 结束日期 空 是否可以保存 +r($task->checkEstStartedAndDeadlineTest($executionID, $estStarted[2], $deadline[2])) && p('estStarted,deadline') && e(0); // 测试获取执行4 任务开始日期 2023-01-15 结束日期 2023-01-15 是否可以保存 + +$tester->setting->setItem('system.common.limitTaskDate', 0);