diff --git a/module/repo/control.php b/module/repo/control.php
index 526df66378..11baa19d07 100644
--- a/module/repo/control.php
+++ b/module/repo/control.php
@@ -1489,6 +1489,20 @@ class repo extends control
return $this->send(array('status' => 'success', 'rules' => $this->config->repo->rules));
}
+ /**
+ * Ajax get executions.
+ *
+ * @param int $productID
+ * @param int $branch
+ * @access public
+ * @return void
+ */
+ public function ajaxGetExecutions(int $productID, int $branch = 0)
+ {
+ $executions = $this->repo->getExecutionPairs($productID, $branch);
+ echo html::select('execution', $executions, '', 'class="form-control chosen"');
+ }
+
/**
* 下载代码。
* Download zip code.
diff --git a/module/repo/model.php b/module/repo/model.php
index 8d6302ca16..9734152247 100644
--- a/module/repo/model.php
+++ b/module/repo/model.php
@@ -1831,6 +1831,33 @@ class repoModel extends model
return !dao::isError();
}
+ /**
+ * Get execution pairs.
+ *
+ * @param int $product
+ * @param int $branch
+ * @access public
+ * @return array
+ */
+ public function getExecutionPairs(int $product, int $branch = 0): array
+ {
+ $pairs = array();
+ $executions = $this->loadModel('execution')->getList(0, 'all', 'undone', 0, $product, $branch);
+ $parents = $this->dao->select('distinct parent,parent')->from(TABLE_EXECUTION)->where('type')->eq('stage')->andWhere('grade')->gt(1)->andWhere('deleted')->eq(0)->fetchPairs();
+ foreach($executions as $execution)
+ {
+ if(!empty($parents[$execution->id]) or ($execution->type == 'stage' and in_array($execution->attribute, array('request', 'design', 'review')))) continue;
+
+ if($execution->type == 'stage' and $execution->grade > 1)
+ {
+ $parentExecutions = $this->dao->select('id,name')->from(TABLE_EXECUTION)->where('id')->in(trim($execution->path, ','))->andWhere('type')->in('stage,kanban,sprint')->orderBy('grade')->fetchPairs();
+ $execution->name = implode('/', $parentExecutions);
+ }
+ $pairs[$execution->id] = $execution->name;
+ }
+ return $pairs;
+ }
+
/**
* 获取代码库的clone地址。
* Get clone url.
diff --git a/module/repo/test/model/saveeffortforcommit.php b/module/repo/test/model/saveeffortforcommit.php
new file mode 100644
index 0000000000..986ee04a87
--- /dev/null
+++ b/module/repo/test/model/saveeffortforcommit.php
@@ -0,0 +1,50 @@
+#!/usr/bin/env php
+saveEffortForCommit();
+timeout=0
+cid=1
+
+- 工时计算
+ - 属性status @doing
+ - 属性consumed @11
+ - 属性left @3
+
+*/
+
+zdTable('task')->gen(10);
+$bug = zdTable('bug');
+$bug->execution->range('0');
+$bug->gen(10);
+zdTable('repo')->config('repo')->gen(4);
+
+$repoID = 1;
+$repoRoot = '';
+$scm = 'gitlab';
+
+$log = new stdclass();
+$log->revision = '61e51cadb1aa21ef3d2b51e3f193be3cc19cfef6';
+$log->committer = 'root';
+$log->time = '2023-12-29 10:44:36';
+$log->comment = 'Effort Task #8 Cost:1h Left:3h';
+$log->author = 'user4';
+$log->msg = 'Effort Task #8 Cost:1h Left:3h';
+$log->date = '2023-12-29 10:44:36';
+$log->files = array('M' => array('/README.md'));
+$log->change = array('/README.md' => array('action' => 'M', 'kind' => 'file', 'oldPath' => ''));
+
+$action = new stdclass();
+$action->actor = 'user4';
+$action->date = '2023-12-29 13:14:36';
+$action->extra = $scm == 'svn' ? $log->revision : substr($log->revision, 0, 10);
+$action->action = 'gitcommited';
+
+$repo = new repoTest();
+$repo->saveEffortForCommitTest($log, $action, $repoID);
+$result = $tester->loadModel('task')->getById(8);
+r($result) && p('status,consumed,left') && e('doing,11,3'); //工时计算
\ No newline at end of file
diff --git a/module/repo/test/model/saveobjecttopms.php b/module/repo/test/model/saveobjecttopms.php
new file mode 100644
index 0000000000..5669f260af
--- /dev/null
+++ b/module/repo/test/model/saveobjecttopms.php
@@ -0,0 +1,68 @@
+#!/usr/bin/env php
+saveObjectToPms();
+timeout=0
+cid=1
+
+- 开始任务
+ - 第1条的objectID属性 @1
+ - 第1条的objectType属性 @tasks
+- 完成任务
+ - 第8条的objectID属性 @8
+ - 第8条的objectType属性 @tasks
+- 工时计算
+ - 第2条的objectID属性 @2
+ - 第2条的objectType属性 @tasks
+- 修复bug1
+ - 第1条的objectID属性 @1
+ - 第1条的objectType属性 @bugs
+- 修复bug2
+ - 第2条的objectID属性 @2
+ - 第2条的objectType属性 @bugs
+
+*/
+
+zdTable('task')->gen(10);
+$bug = zdTable('bug');
+$bug->execution->range('0');
+$bug->gen(10);
+zdTable('repo')->config('repo')->gen(4);
+$dao->exec("delete from zt_action where action='gitcommited'");
+
+$repoID = 1;
+$repoRoot = '';
+$scm = 'gitlab';
+
+$log = new stdclass();
+$log->revision = '61e51cadb1aa21ef3d2b51e3f193be3cc19cfef6';
+$log->committer = 'root';
+$log->time = '2023-12-29 10:44:36';
+$log->comment = 'Start Task #1 Cost:1h Left:3h,Effort Task #8 Cost:1h Left:3h,Finish Task #2 Cost:10h';
+$log->author = 'user4';
+$log->msg = 'Start Task #1 Cost:1h Left:3h,Effort Task #8 Cost:1h Left:3h,Finish Task #2 Cost:10h';
+$log->date = '2023-12-29 10:44:36';
+$log->files = array('M' => array('/README.md'));
+$log->change = array('/README.md' => array('action' => 'M', 'kind' => 'file', 'oldPath' => ''));
+
+$action = new stdclass();
+$action->actor = 'user4';
+$action->date = '2023-12-29 13:14:36';
+$action->extra = $scm == 'svn' ? $log->revision : substr($log->revision, 0, 10);
+$action->action = 'gitcommited';
+
+$repo = new repoTest();
+$result = $repo->saveObjectToPmsTest($log, $action, $repoID, 'task');
+r($result) && p('1:objectID,objectType') && e('1,tasks'); //开始任务
+r($result) && p('8:objectID,objectType') && e('8,tasks'); //完成任务
+r($result) && p('2:objectID,objectType') && e('2,tasks'); //工时计算
+
+$log->msg = $log->comment = 'Fix bug#1,2';
+$result = $repo->saveObjectToPmsTest($log, $action, $repoID, 'bug');
+r($result) && p('1:objectID,objectType') && e('1,bugs'); //修复bug1
+r($result) && p('2:objectID,objectType') && e('2,bugs'); //修复bug2
diff --git a/module/repo/test/model/setbugstatusbycommit.php b/module/repo/test/model/setbugstatusbycommit.php
new file mode 100644
index 0000000000..2c742d8a6a
--- /dev/null
+++ b/module/repo/test/model/setbugstatusbycommit.php
@@ -0,0 +1,53 @@
+#!/usr/bin/env php
+setBugStatusByCommit();
+timeout=0
+cid=1
+
+- 修复bug1
+ - 第1条的status属性 @resolved
+ - 第1条的resolution属性 @fixed
+- 修复bug2
+ - 第2条的status属性 @resolved
+ - 第2条的resolution属性 @fixed
+
+*/
+
+zdTable('task')->gen(10);
+$bug = zdTable('bug');
+$bug->execution->range('0');
+$bug->gen(10);
+zdTable('repo')->config('repo')->gen(4);
+
+$repoID = 1;
+$repoRoot = '';
+$scm = 'gitlab';
+
+$log = new stdclass();
+$log->revision = '61e51cadb1aa21ef3d2b51e3f193be3cc19cfef6';
+$log->committer = 'root';
+$log->time = '2023-12-29 10:44:36';
+$log->comment = 'Fix bug#1,2';
+$log->author = 'user4';
+$log->msg = 'Fix bug#1,2';
+$log->date = '2023-12-29 10:44:36';
+$log->files = array('M' => array('/README.md'));
+$log->change = array('/README.md' => array('action' => 'M', 'kind' => 'file', 'oldPath' => ''));
+
+$action = new stdclass();
+$action->actor = 'user4';
+$action->date = '2023-12-29 13:14:36';
+$action->extra = $scm == 'svn' ? $log->revision : substr($log->revision, 0, 10);
+$action->action = 'gitcommited';
+
+$repo = new repoTest();
+$repo->setBugStatusByCommitTest($log, $action, $repoID);
+$result = $tester->loadModel('bug')->getByIdList(array(1,2));
+r($result) && p('1:status,resolution') && e('resolved,fixed'); //修复bug1
+r($result) && p('2:status,resolution') && e('resolved,fixed'); //修复bug2
diff --git a/module/repo/test/model/settaskbycommit.php b/module/repo/test/model/settaskbycommit.php
new file mode 100644
index 0000000000..1b05a3f9bb
--- /dev/null
+++ b/module/repo/test/model/settaskbycommit.php
@@ -0,0 +1,68 @@
+#!/usr/bin/env php
+setTaskByCommit();
+timeout=0
+cid=1
+
+- 开始任务
+ - 属性status @doing
+ - 属性consumed @4
+ - 属性left @3
+- 工时计算
+ - 属性status @doing
+ - 属性consumed @11
+ - 属性left @3
+- 完成任务
+ - 属性status @done
+ - 属性consumed @14
+ - 属性left @0
+
+*/
+
+zdTable('task')->gen(10);
+$bug = zdTable('bug');
+$bug->execution->range('0');
+$bug->gen(10);
+zdTable('repo')->config('repo')->gen(4);
+
+$repoID = 1;
+$repoRoot = '';
+$scm = 'gitlab';
+
+$log = new stdclass();
+$log->revision = '61e51cadb1aa21ef3d2b51e3f193be3cc19cfef6';
+$log->committer = 'root';
+$log->time = '2023-12-29 10:44:36';
+$log->comment = 'Start Task #1 Cost:1h Left:3h';
+$log->author = 'user4';
+$log->msg = 'Start Task #1 Cost:1h Left:3h';
+$log->date = '2023-12-29 10:44:36';
+$log->files = array('M' => array('/README.md'));
+$log->change = array('/README.md' => array('action' => 'M', 'kind' => 'file', 'oldPath' => ''));
+
+$action = new stdclass();
+$action->actor = 'user4';
+$action->date = '2023-12-29 13:14:36';
+$action->extra = $scm == 'svn' ? $log->revision : substr($log->revision, 0, 10);
+$action->action = 'gitcommited';
+
+$repo = new repoTest();
+$repo->setTaskByCommitTest($log, $action, $repoID);
+$result = $tester->loadModel('task')->getById(1);
+r($result) && p('status,consumed,left') && e('doing,4,3'); //开始任务
+
+$log->msg = $log->comment = 'Effort Task #8 Cost:1h Left:3h';
+$repo->setTaskByCommitTest($log, $action, $repoID);
+$result = $tester->loadModel('task')->getById(8);
+r($result) && p('status,consumed,left') && e('doing,11,3'); //工时计算
+
+$log->msg = $log->comment = 'Finish Task #2 Cost:10h';
+$repo->setTaskByCommitTest($log, $action, $repoID);
+$result = $tester->loadModel('task')->getById(2);
+r($result) && p('status,consumed,left') && e('done,14,0'); //完成任务
diff --git a/module/repo/test/repo.class.php b/module/repo/test/repo.class.php
index ce0f67e1b8..4a3715a3f1 100644
--- a/module/repo/test/repo.class.php
+++ b/module/repo/test/repo.class.php
@@ -500,7 +500,38 @@ class repoTest
return $objects;
}
- public function saveAction2PMSTest($log, $repoID, $scm = 'git', $gitlabAccountPairs = array())
+ public function saveObjectToPmsTest(object $log, object $action, int $repoID, string $type)
+ {
+ $repo = $this->objectModel->getByID($repoID);
+ $objects = $this->objectModel->parseComment($log->msg);
+ $changes = $this->objectModel->createActionChanges($log, $repo->path, 'git');
+
+ $result = $this->objectModel->saveObjectToPms($objects, $action, $changes);
+
+ if(dao::isError()) return dao::getError();
+
+ if($type == 'task')
+ {
+ $records = $this->objectModel->dao->select('*')->from(TABLE_ACTION)
+ ->where('objectType')->eq('tasks')
+ ->andWhere('objectID')->in('1,2,8')
+ ->andWhere('extra')->eq($action->extra)
+ ->andWhere('action')->eq($action->action)
+ ->fetchAll('objectID');
+ }
+ elseif($type == 'bug')
+ {
+ $records = $this->objectModel->dao->select('*')->from(TABLE_ACTION)
+ ->where('objectType')->eq('bugs')
+ ->andWhere('objectID')->in('1,2')
+ ->andWhere('extra')->eq($action->extra)
+ ->andWhere('action')->eq($action->action)
+ ->fetchAll('objectID');
+ }
+ return $records;
+ }
+
+ public function saveAction2PMSTest(object $log, int $repoID, string $scm = 'git', array $gitlabAccountPairs = array())
{
$repo = $this->objectModel->getByID($repoID);
$objects = $this->objectModel->parseComment($log->msg);
@@ -511,6 +542,65 @@ class repoTest
return $result;
}
+ public function setTaskByCommitTest(object $log, object $action, int $repoID, string $scm = 'git')
+ {
+ $action->comment = $this->objectModel->lang->repo->revisionA . ': #' . $action->extra . "
" . htmlSpecialString($this->objectModel->iconvComment($log->msg, 'utf-8'));
+
+ $repo = $this->objectModel->getByID($repoID);
+ $objects = $this->objectModel->parseComment($log->msg);
+ $changes = $this->objectModel->createActionChanges($log, $repo->path, $scm);
+
+ $actions = $objects['actions'];
+ foreach($actions['task'] as $taskID => $taskActions)
+ {
+ $task = $this->objectModel->loadModel('task')->getById($taskID);
+ if(empty($task)) continue;
+
+ $action->objectType = 'task';
+ $action->objectID = $taskID;
+
+ $result = $this->objectModel->setTaskByCommit($task, $taskActions, $action, $changes, $scm);
+ return $result;
+ }
+ }
+
+ public function saveEffortForCommitTest(object $log, object $action, int $repoID, string $scm = 'git')
+ {
+ $action->comment = $this->objectModel->lang->repo->revisionA . ': #' . $action->extra . "
" . htmlSpecialString($this->objectModel->iconvComment($log->msg, 'utf-8'));
+
+ $repo = $this->objectModel->getByID($repoID);
+ $objects = $this->objectModel->parseComment($log->msg);
+ $changes = $this->objectModel->createActionChanges($log, $repo->path, $scm);
+
+ $actions = $objects['actions'];
+ foreach($actions['task'] as $taskID => $taskActions)
+ {
+ $task = $this->objectModel->loadModel('task')->getById($taskID);
+ if(empty($task)) continue;
+
+ $action->objectType = 'task';
+ $action->objectID = $taskID;
+
+ foreach($taskActions as $taskAction => $params)
+ {
+ $result = $this->objectModel->saveEffortForCommit($task->id, $params, $action, $changes);
+ return $result;
+ }
+ }
+ }
+
+ public function setBugStatusByCommitTest(object $log, object $action, int $repoID, string $scm = 'git')
+ {
+ $action->comment = $this->objectModel->lang->repo->revisionA . ': #' . $action->extra . "
" . htmlSpecialString($this->objectModel->iconvComment($log->msg, 'utf-8'));
+
+ $repo = $this->objectModel->getByID($repoID);
+ $objects = $this->objectModel->parseComment($log->msg);
+ $changes = $this->objectModel->createActionChanges($log, $repo->path, $scm);
+
+ $result = $this->objectModel->setBugStatusByCommit($objects['bugs'], $objects['actions'], $action, $changes);
+ return $result;
+ }
+
public function saveRecordTest(object $action, object $log, string $repoRoot, string $scm, bool $returnHistory = false)
{
$action->comment = $this->objectModel->lang->repo->revisionA . ': #' . $action->extra . "
" . htmlSpecialString($this->objectModel->iconvComment($log->msg, 'utf-8'));