diff --git a/db/update1.3.sql b/db/update1.3.sql
index 98887a6f27..95213fd7ce 100644
--- a/db/update1.3.sql
+++ b/db/update1.3.sql
@@ -34,3 +34,4 @@ ADD `lastEditedDate` DATETIME NOT NULL AFTER `lastEditedBy` ;
UPDATE zt_task SET assignedTo = owner ;
ALTER TABLE `zt_task` DROP `owner`;
ALTER TABLE `zt_task` CHANGE `status` `status` ENUM( 'wait', 'doing', 'done', 'cancel', 'closed' ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'wait';
+ALTER TABLE `zt_task` ADD `closedReason` VARCHAR( 30 ) NOT NULL AFTER `closedDate` ;
diff --git a/module/common/lang/en.php b/module/common/lang/en.php
index 969a6f5b91..0f9710fcda 100644
--- a/module/common/lang/en.php
+++ b/module/common/lang/en.php
@@ -228,6 +228,7 @@ $lang->error->length = array("『%s』length should be『%s』", "『%s
$lang->error->reg = "『%s』should like『%s』";
$lang->error->unique = "『%s』has『%s』already.";
$lang->error->notempty = "『%s』can not be empty.";
+$lang->error->empty = "『%s』 must be empty.";
$lang->error->equal = "『%s』must be『%s』.";
$lang->error->int = array("『%s』should be interger", "『%s』should between『%s-%s』.");
$lang->error->float = "『%s』should be a interger or float.";
diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php
index 56fcb9f6e1..4010279237 100644
--- a/module/common/lang/zh-cn.php
+++ b/module/common/lang/zh-cn.php
@@ -118,7 +118,6 @@ $lang->my->menu->project = '我的项目|my|project|';
$lang->my->menu->profile = array('link' => '我的档案|my|profile|', 'alias' => 'editprofile');
$lang->todo->menu = $lang->my->menu;
-
/* 产品视图设置。*/
$lang->product->menu->list = '%s';
$lang->product->menu->story = array('link' => '需求列表|product|browse|productID=%s', 'subModule' => 'story');
@@ -229,6 +228,7 @@ $lang->error->length = array("『%s』长度错误,应当为『%s』"
$lang->error->reg = "『%s』不符合格式,应当为:『%s』。";
$lang->error->unique = "『%s』已经有『%s』这条记录了。";
$lang->error->notempty = "『%s』不能为空。";
+$lang->error->empty = "『%s』必须为空。";
$lang->error->equal = "『%s』必须为『%s』。";
$lang->error->int = array("『%s』应当是数字。", "『%s』应当介于『%s-%s』之间。");
$lang->error->float = "『%s』应当是数字,可以是小数。";
diff --git a/module/task/lang/en.php b/module/task/lang/en.php
index 0b615f2107..43021d25d9 100644
--- a/module/task/lang/en.php
+++ b/module/task/lang/en.php
@@ -53,12 +53,14 @@ $lang->task->canceledBy = 'Canceled By';
$lang->task->canceledDate = 'Canceled Date';
$lang->task->closedBy = 'Closed By';
$lang->task->closedDate = 'Closed Date';
-$lang->task->lasteEdited = 'Last Edited';
+$lang->task->closedReason = 'Closed Reason';
+$lang->task->lastEdited = 'Last Edited';
$lang->task->statusList['wait'] = 'Waiting';
$lang->task->statusList['doing'] = 'Doing';
$lang->task->statusList['done'] = 'Done';
$lang->task->statusList['cancel'] = 'Canceled';
+$lang->task->statusList['closed'] = 'Closed';
$lang->task->typeList[''] = '';
$lang->task->typeList['design'] = 'Design';
@@ -76,6 +78,10 @@ $lang->task->priList[1] = '1';
$lang->task->priList[2] = '2';
$lang->task->priList[4] = '4';
+$lang->task->reasonList[''] = '';
+$lang->task->reasonList['done'] = 'Done';
+$lang->task->reasonList['cancel'] = 'Canceled';
+
$lang->task->afterChoices['continueAdding'] = 'Continue add task for this story';
$lang->task->afterChoices['toTastList'] = 'To task list';
$lang->task->afterChoices['toStoryList'] = 'To story list';
@@ -92,6 +98,7 @@ $lang->task->buttonDone = 'Done';
$lang->task->legendBasic = 'Basic info';
$lang->task->legendEffort = 'Effort';
+$lang->task->legendLife = 'Lifetime';
$lang->task->legendDesc = 'Desc';
$lang->task->legendAction = 'Action';
diff --git a/module/task/lang/zh-cn.php b/module/task/lang/zh-cn.php
index 9624d4e2f7..35a27c08a9 100644
--- a/module/task/lang/zh-cn.php
+++ b/module/task/lang/zh-cn.php
@@ -53,12 +53,14 @@ $lang->task->canceledBy = '由谁取消';
$lang->task->canceledDate = '取消时间';
$lang->task->closedBy = '由谁关闭';
$lang->task->closedDate = '关闭时间';
-$lang->task->lasteEdited = '最后编辑';
+$lang->task->closedReason = '关闭原因';
+$lang->task->lastEdited = '最后编辑';
$lang->task->statusList['wait'] = '未开始';
$lang->task->statusList['doing'] = '进行中';
$lang->task->statusList['done'] = '已完成';
$lang->task->statusList['cancel'] = '已取消';
+$lang->task->statusList['closed'] = '已关闭';
$lang->task->typeList[''] = '';
$lang->task->typeList['design'] = '设计';
@@ -76,6 +78,10 @@ $lang->task->priList[1] = '1';
$lang->task->priList[2] = '2';
$lang->task->priList[4] = '4';
+$lang->task->reasonList[''] = '';
+$lang->task->reasonList['done'] = '已完成';
+$lang->task->reasonList['cancel'] = '已取消';
+
$lang->task->afterChoices['continueAdding'] = '继续为该需求添加任务';
$lang->task->afterChoices['toTastList'] = '返回任务列表';
$lang->task->afterChoices['toStoryList'] = '返回需求列表';
@@ -92,6 +98,7 @@ $lang->task->buttonDone = '完成';
$lang->task->legendBasic = '基本信息';
$lang->task->legendEffort = '工时信息';
+$lang->task->legendLife = '任务的一生';
$lang->task->legendDesc = '任务描述';
$lang->task->legendAction = '操作';
diff --git a/module/task/model.php b/module/task/model.php
index f9482400c1..f7c83ac814 100644
--- a/module/task/model.php
+++ b/module/task/model.php
@@ -13,7 +13,7 @@
getById($taskID);
- $task = fixer::input('post')
+ $now = helper::now();
+ $task = fixer::input('post')
->striptags('name')
->setDefault('story, estimate, left, consumed', 0)
+ ->setDefault('deadline', '0000-00-00')
->setIF($this->post->story != false and $this->post->story != $oldTask->story, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story))
+
->setIF($this->post->status == 'done', 'left', 0)
+ ->setIF($this->post->status == 'done' and !$this->post->finishedBy, 'finishedBy', $this->app->user->account)
+ ->setIF($this->post->status == 'done' and !$this->post->finishedDate, 'finishedDate', $now)
+
+ ->setIF($this->post->status == 'cancel' and !$this->post->canceledBy, 'canceledBy', $this->app->user->account)
+ ->setIF($this->post->status == 'cancel' and !$this->post->canceledDate, 'canceledDate', $now)
+ ->setIF($this->post->status == 'cancel', 'closedBy', $this->post->canceledBy ? $this->post->canceledBy : $this->app->user->account)
+ ->setIF($this->post->status == 'cancel', 'closedDate', $this->post->canceledDate? $this->post->canceledDate : $now)
+ ->setIF($this->post->status == 'cancel', 'closedReason', 'cancel')
+
+ ->setIF($this->post->status == 'closed' and !$this->post->closedBy, 'closedBy', $this->app->user->account)
+ ->setIF($this->post->status == 'closed' and !$this->post->closedDate, 'closedDate', $now)
->setIF($this->post->consumed > 0 and $this->post->left > 0 and $this->post->status == 'wait', 'status', 'doing')
+
+ ->add('lastEditedBy', $this->app->user->account)
+ ->add('lastEditedDate', $now)
->remove('comment,files,labels')
->get();
$task->statusCustom = strpos(self::CUSTOM_STATUS_ORDER, $task->status) + 1;
@@ -79,12 +96,23 @@ class taskModel extends model
$this->dao->update(TABLE_TASK)->data($task)
->autoCheck()
->batchCheckIF($task->status != 'cancel', $this->config->task->edit->requiredFields, 'notempty')
+
->checkIF($task->estimate != false, 'estimate', 'float')
->checkIF($task->left != false, 'left', 'float')
->checkIF($task->consumed != false, 'consumed', 'float')
+ ->checkIF($task->left == 0 and $task->status != 'cancel' and $task->status != 'closed', 'status', 'equal', 'done')
+
+ ->batchCheckIF($task->status == 'waiting' or $task->status == 'doing', 'finishedBy, finishedDate, closedBy, closedDate, closedReason', 'empty')
+
->checkIF($task->status == 'done', 'consumed', 'notempty')
- ->checkIF($task->left == 0 and $task->status != 'cancel', 'status', 'equal', 'done')
+ ->checkIF($task->status == 'done' and $task->closedReason, 'closedReason', 'equal', 'done')
+
+ ->checkIF($task->status == 'cancel', 'finishedBy', 'empty')
+ ->checkIF($task->status == 'cancel', 'finishedDate','empty')
+
+ ->checkIF($task->status == 'closed', 'closedReason', 'notempty')
->where('id')->eq((int)$taskID)->exec();
+
if($this->post->story != false) $this->loadModel('story')->setStage($this->post->story);
if(!dao::isError()) return common::createChanges($oldTask, $task);
}
@@ -136,6 +164,7 @@ class taskModel extends model
->where('t1.id')->eq((int)$taskID)
->fetch();
if(!$task) return false;
+ foreach($task as $key => $value) if(strpos($key, 'Date') !== false and !(int)substr($value, 0, 4)) $task->$key = '';
if($task->mailto)
{
$task->mailto = ltrim(trim($task->mailto), ','); // remove the first ,
diff --git a/module/task/view/edit.html.php b/module/task/view/edit.html.php
index 517fe13a46..b5688cdcf2 100644
--- a/module/task/view/edit.html.php
+++ b/module/task/view/edit.html.php
@@ -116,6 +116,43 @@ $(function() {
+
diff --git a/module/task/view/view.html.php b/module/task/view/view.html.php
index dfbf1b1b31..fe3799a698 100644
--- a/module/task/view/view.html.php
+++ b/module/task/view/view.html.php
@@ -19,16 +19,15 @@
session->taskList != false ? $app->session->taskList : $this->createLink('project', 'browse', "projectID=$task->project");
- //if(!($task->status != 'closed' and $task->status != 'cancel' and common::printLink('task', 'logEfforts', "taskID=$task->id", $lang->task->buttonLogEfforts))) echo $lang->task->buttonLogEfforts . ' ';
- //if(!($task->status != 'closed' and $task->status != 'cancel' and common::printLink('task', 'close', "taskID=$task->id", $lang->task->buttonClose))) echo $lang->task->buttonClose . ' ';
- //if(!($task->status != 'closed' and $task->status != 'cancel' and common::printLink('task', 'cancel', "taskID=$task->id", $lang->task->buttonCancel))) echo $lang->task->buttonCancel . ' ';
- //if(!($task->status == 'closed' or $task->status == 'cancel' and common::printLink('task', 'activate', "taskID=$task->id", $lang->task->buttonActivate))) echo $lang->task->buttonActivate . ' ';
if(!$task->deleted)
{
- if(!common::printLink('task', 'edit', "taskID=$task->id", $lang->task->buttonEdit)) echo $lang->task->buttonEdit . ' ';
+ //if(!($task->status != 'closed' and $task->status != 'cancel' and common::printLink('task', 'logEfforts', "taskID=$task->id", $lang->task->buttonLogEfforts))) echo $lang->task->buttonLogEfforts . ' ';
if(!(($task->status == 'wait' or $task->status == 'cancel') and common::printLink('task', 'start', "taskID=$task->id", $lang->task->buttonStart))) echo $lang->task->buttonStart . ' ';
if(!(($task->status == 'wait' or $task->status == 'doing') and common::printLink('task', 'complete', "taskID=$task->id", $lang->task->buttonDone))) echo $lang->task->buttonDone . ' ';
if(!(($task->status == 'wait' or $task->status == 'doing') and common::printLink('task', 'cancel', "taskID=$task->id", $lang->task->buttonCancel))) echo $lang->task->buttonCancel . ' ';
+ if(!($task->status != 'closed' and $task->status != 'cancel' and common::printLink('task', 'close', "taskID=$task->id", $lang->task->buttonClose))) echo $lang->task->buttonClose . ' ';
+ if(!($task->status == 'closed' or $task->status == 'cancel' and common::printLink('task', 'activate', "taskID=$task->id", $lang->task->buttonActivate))) echo $lang->task->buttonActivate . ' ';
+ if(!common::printLink('task', 'edit', "taskID=$task->id", $lang->task->buttonEdit)) echo $lang->task->buttonEdit . ' ';
if(!common::printLink('task', 'delete',"projectID=$task->project&taskID=$task->id", $lang->task->buttonDelete, 'hiddenwin')) echo $lang->task->buttonDelete . ' ';
}
echo html::a($browseLink, $lang->goback);
@@ -48,17 +47,16 @@
status != 'closed' and $task->status != 'cancel' and common::printLink('task', 'logEfforts', "taskID=$task->id", $lang->task->buttonLogEfforts))) echo $lang->task->buttonLogEfforts . ' ';
- //if(!($task->status != 'closed' and $task->status != 'cancel' and common::printLink('task', 'close', "taskID=$task->id", $lang->task->buttonClose))) echo $lang->task->buttonClose . ' ';
- //if(!($task->status != 'closed' and $task->status != 'cancel' and common::printLink('task', 'cancel', "taskID=$task->id", $lang->task->buttonCancel))) echo $lang->task->buttonCancel . ' ';
- //if(!($task->status == 'closed' or $task->status == 'cancel' and common::printLink('task', 'activate', "taskID=$task->id", $lang->task->buttonActivate))) echo $lang->task->buttonActivate . ' ';
if(!$task->deleted)
{
- if(!common::printLink('task', 'edit', "taskID=$task->id", $lang->task->buttonEdit)) echo $lang->task->buttonEdit . ' ';
- if(!($task->status == 'wait' and common::printLink('task', 'start', "taskID=$task->id", $lang->task->buttonStart))) echo $lang->task->buttonStart . ' ';
- if(!(($task->status == 'wait' or $task->status == 'doing') and common::printLink('task', 'complete', "taskID=$task->id", $lang->task->buttonDone))) echo $lang->task->buttonDone . ' ';
- if(!(($task->status == 'wait' or $task->status == 'doing') and common::printLink('task', 'cancel', "taskID=$task->id", $lang->task->buttonCancel))) echo $lang->task->buttonCancel . ' ';
+ if(!(($task->status == 'wait' or $task->status == 'cancel') and common::printLink('task', 'start', "taskID=$task->id", $lang->task->buttonStart))) echo $lang->task->buttonStart . ' ';
+ if(!(($task->status == 'wait' or $task->status == 'doing') and common::printLink('task', 'complete', "taskID=$task->id", $lang->task->buttonDone))) echo $lang->task->buttonDone . ' ';
+ if(!(($task->status == 'wait' or $task->status == 'doing') and common::printLink('task', 'cancel', "taskID=$task->id", $lang->task->buttonCancel))) echo $lang->task->buttonCancel . ' ';
+ if(!($task->status != 'closed' and $task->status != 'cancel' and common::printLink('task', 'close', "taskID=$task->id", $lang->task->buttonClose))) echo $lang->task->buttonClose . ' ';
+ if(!($task->status == 'closed' or $task->status == 'cancel' and common::printLink('task', 'activate', "taskID=$task->id", $lang->task->buttonActivate))) echo $lang->task->buttonActivate . ' ';
+ if(!common::printLink('task', 'edit', "taskID=$task->id", $lang->task->buttonEdit)) echo $lang->task->buttonEdit . ' ';
if(!common::printLink('task', 'delete',"projectID=$task->project&taskID=$task->id", $lang->task->buttonDelete, 'hiddenwin')) echo $lang->task->buttonDelete . ' ';
+
}
echo html::a($browseLink, $lang->goback);
?>
@@ -89,7 +87,7 @@
| task->assignedTo;?> |
- assignedToRealName;?>
+ | assignedToRealName . $lang->at . $task->assignedDate;?>
|
| task->type;?> |
@@ -107,7 +105,7 @@
task->mailto;?> |
mailto)); foreach($mailto as $account) echo ' ' . $users[$account]; ?> |
-
+
+
diff --git a/module/upgrade/model.php b/module/upgrade/model.php
index 6d21102a5d..3ab2e6708b 100644
--- a/module/upgrade/model.php
+++ b/module/upgrade/model.php
@@ -390,6 +390,7 @@ class upgradeModel extends model
{
$this->execSQL($this->getUpgradeFile('1.3'));
$this->updateNL1_3();
+ $this->updateTasks();
if(!$this->isError()) $this->setting->updateVersion('1.4');
}
@@ -528,6 +529,86 @@ class upgradeModel extends model
}
}
+ /**
+ * Update task fields.
+ *
+ * @access public
+ * @return void
+ */
+ public function updateTasks()
+ {
+ /* Get all actions of tasks. */
+ $actions = $this->dao->select('*')->from(TABLE_ACTION)
+ ->where('objectType')->eq('task')
+ ->orderBy('id')
+ ->fetchAll('id');
+
+ /* Get histories about status field. */
+ $histories = $this->dao->select()->from(TABLE_HISTORY)
+ ->where('action')->in(array_keys($actions))
+ ->andWhere('field')->eq('status')
+ ->orderBy('id')
+ ->fetchGroup('action');
+
+ $tasks = array();
+ foreach($actions as $action)
+ {
+ if(!isset($tasks[$action->objectID]))
+ {
+ $tasks[$action->objectID] = new stdclass;
+ }
+ $task = $tasks[$action->objectID];
+
+ $task->id = $action->objectID;
+ $actionType = strtolower($action->action);
+
+ /* Set the openedBy info. */
+ if($actionType == 'opened')
+ {
+ $task->openedBy = $action->actor;
+ $task->openedDate = $action->date;
+ }
+ else
+ {
+ if(!isset($histories[$action->id])) continue;
+
+ $actionHistories = $histories[$action->id];
+ foreach($actionHistories as $history)
+ {
+ /* Finished by. */
+ if($history->new == 'done')
+ {
+ $task->finishedBy = $action->actor;
+ $task->finishedDate = $action->date;
+ $action->action = 'finished';
+ }
+ /* Canceled By. */
+ elseif($history->new == 'cancel')
+ {
+ $task->canceledBy = $action->actor;
+ $task->canceledDate = $action->date;
+ $action->action = 'canceled';
+ }
+ }
+
+ /* Last edited by .*/
+ $task->lastEditedBy = $action->actor;
+ $task->lastEditedDate = $action->date;
+
+ /* Update action type. */
+ $this->dao->update(TABLE_ACTION)->set('action')->eq($action->action)->where('id')->eq($action->id)->exec(false);
+ }
+ }
+
+ /* Update db. */
+ foreach($tasks as $task)
+ {
+ $this->dao->update(TABLE_TASK)->data($task, false)->where('id')->eq($task->id)->exec(false);
+ }
+
+ /* Update action name. */
+ }
+
/**
* Get the upgrade sql file.
*