* Refactor project-create method.
This commit is contained in:
@@ -1,7 +1,22 @@
|
||||
<?php
|
||||
$config->project->form = new stdclass();
|
||||
$config->project->form->start = array();
|
||||
$config->project->form->suspend = array();
|
||||
$config->project->form->create = array();
|
||||
$config->project->form->start = array();
|
||||
|
||||
$config->project->form->create['parent'] = array('type' => 'int', 'required' => false, 'default' => '');
|
||||
$config->project->form->create['name'] = array('type' => 'string', 'required' => true, 'filter' => 'trim');
|
||||
$config->project->form->create['code'] = array('type' => 'string', 'required' => true, 'filter' => 'trim');
|
||||
$config->project->form->create['multiple'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->project->form->create['hasProduct'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->project->form->create['PM'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->project->form->create['budget'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->project->form->create['budgetUnit'] = array('type' => 'string', 'required' => false, 'default' => 'CNY');
|
||||
$config->project->form->create['begin'] = array('type' => 'date', 'required' => true);
|
||||
$config->project->form->create['end'] = array('type' => 'date', 'required' => true);
|
||||
$config->project->form->create['desc'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->project->form->create['acl'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->project->form->create['whitelist'] = array('type' => 'array', 'required' => false, 'default' => '');
|
||||
$config->project->form->create['auth'] = array('type' => 'array', 'required' => false, 'default' => '');
|
||||
$config->project->form->create['model'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
|
||||
$config->project->form->start['realBegan'] = array('type' => 'date', 'required' => true, 'filter' => 'trim');
|
||||
$config->project->form->suspend['realBegan'] = array('type' => 'date', 'required' => true, 'filter' => 'trim');
|
||||
|
||||
+12
-35
@@ -277,7 +277,7 @@ class project extends control
|
||||
|
||||
if($objectType == 'program')
|
||||
{
|
||||
$minChildBegin = $this->dao->select('`begin` as minBegin')->from(TABLE_PROGRAM)->where('id')->ne($objectID)->andWhere('deleted')->eq(0)->andWhere('path')->like("%,{$objectID},%")->orderBy('begin_asc')->fetch('tminBegin');
|
||||
$minChildBegin = $this->dao->select('`begin` as minBegin')->from(TABLE_PROGRAM)->where('id')->ne($objectID)->andWhere('deleted')->eq(0)->andWhere('path')->like("%,{$objectID},%")->orderBy('begin_asc')->fetch('minBegin');
|
||||
$maxChildEnd = $this->dao->select('`end` as maxEnd')->from(TABLE_PROGRAM)->where('id')->ne($objectID)->andWhere('deleted')->eq(0)->andWhere('path')->like("%,{$objectID},%")->andWhere('end')->ne('0000-00-00')->orderBy('end_desc')->fetch('maxEnd');
|
||||
}
|
||||
}
|
||||
@@ -487,48 +487,25 @@ class project extends control
|
||||
$this->loadModel('execution');
|
||||
$this->loadModel('product');
|
||||
|
||||
$this->session->set('projectModel', $model);
|
||||
|
||||
if($model == 'kanban') unset($this->lang->project->authList['reset']);
|
||||
|
||||
if($_POST)
|
||||
{
|
||||
$projectID = $this->project->create();
|
||||
$postData = form::data($this->config->project->form->create);
|
||||
|
||||
$project = $this->projectZen->prepareCreateExtras($postData);
|
||||
|
||||
$projectID = $this->project->create($project, $postData);
|
||||
$projectID = (int)$projectID;
|
||||
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
|
||||
$this->loadModel('action')->create('project', $projectID, 'opened');
|
||||
|
||||
/* Link the plan stories. */
|
||||
if(!empty($_POST['hasProduct']) && !empty($_POST['plans']))
|
||||
{
|
||||
$planIdList = array();
|
||||
foreach($_POST['plans'] as $plans)
|
||||
{
|
||||
foreach($plans as $planID)
|
||||
{
|
||||
$planIdList[$planID] = $planID;
|
||||
}
|
||||
}
|
||||
|
||||
$planStoryGroup = $this->loadModel('story')->getStoriesByPlanIdList($planIdList);
|
||||
foreach($planIdList as $planID)
|
||||
{
|
||||
$planStories = $planProducts = array();
|
||||
$planStory = isset($planStoryGroup[$planID]) ? $planStoryGroup[$planID] : array();
|
||||
if(!empty($planStory))
|
||||
{
|
||||
foreach($planStory as $id => $story)
|
||||
{
|
||||
if($story->status == 'draft' or $story->status == 'reviewing')
|
||||
{
|
||||
unset($planStory[$id]);
|
||||
continue;
|
||||
}
|
||||
$planProducts[$story->id] = $story->product;
|
||||
}
|
||||
$planStories = array_keys($planStory);
|
||||
$this->execution->linkStory($projectID, $planStories, $planProducts);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!empty($_POST['hasProduct']) && !empty($_POST['plans'])) $this->projectZen->linkPlanStories($postData);
|
||||
|
||||
$message = $this->executeHooks($projectID);
|
||||
if($message) $this->lang->saveSuccess = $message;
|
||||
@@ -551,7 +528,7 @@ class project extends control
|
||||
$parent = isset($_POST['parent']) ? $_POST['parent'] : 0;
|
||||
$systemMode = $this->loadModel('setting')->getItem('owner=system&module=common§ion=global&key=mode');
|
||||
if(!empty($systemMode) and $systemMode == 'light') $parent = 0;
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('project', 'browse', "programID=$parent&browseType=all", '', '', $projectID)));
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('project', 'browse', "programID=$parent&browseType=all", '', false, $projectID)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,8 +64,6 @@ $lang->project->daysGreaterProject = "Days cannot be greater than days of {$lan
|
||||
$lang->project->errorHours = 'Hours/Day cannot be greater than『24』';
|
||||
$lang->project->workdaysExceed = 'No more than『%s』working days';
|
||||
$lang->project->teamMembersCount = ', there are %s team members.';
|
||||
$lang->project->budgetNumber = '『Budget』must be numbers.';
|
||||
$lang->project->budgetGe0 = '『Budget』must be greater than or equal to 0.';
|
||||
$lang->project->allProjects = "All {$lang->projectCommon}s";
|
||||
$lang->project->ignore = 'Ignore';
|
||||
$lang->project->disableExecution = "{$lang->projectCommon} of disable {$lang->executionCommon}";
|
||||
@@ -211,8 +209,6 @@ $lang->project->noProgram = "Independent {$lang->projectCommon}s";
|
||||
|
||||
$lang->project->laneColorList = array('#32C5FF', '#006AF1', '#9D28B2', '#FF8F26', '#FFC20E', '#00A78E', '#7FBB00', '#424BAC', '#C0E9FF', '#EC2761');
|
||||
|
||||
$lang->project->productNotEmpty = "Please link {$lang->productCommon}s or create {$lang->productCommon}s.";
|
||||
$lang->project->existProductName = "{$lang->productCommon} name already exists.";
|
||||
$lang->project->changeProgram = "%s > Change {$lang->projectCommon}";
|
||||
$lang->project->changeProgramTip = "Once the program is edited, the {$lang->productCommon} that is linked to this program will be changed. Do you want to edit it?";
|
||||
$lang->project->linkedProjectsTip = "Linked {$lang->projectCommon}s are as follows";
|
||||
@@ -242,6 +238,13 @@ $lang->project->tip->actived = 'The project has been activated. Re-activated
|
||||
$lang->project->tip->group = "It's a Kanban project. Editing privilege group is not available.";
|
||||
$lang->project->tip->whitelist = "It's a public project with open permissions. No need to edit whitelists.";
|
||||
|
||||
$lang->project->error = new stdclass();
|
||||
$lang->project->error->existProductName = "{$lang->productCommon} name already exists.";
|
||||
$lang->project->error->budgetGe0 = '『Budget』must be greater than or equal to 0.';
|
||||
$lang->project->error->budgetNumber = '『Budget』must be numbers.';
|
||||
$lang->project->error->productNotEmpty = "Please link {$lang->productCommon}s or create {$lang->productCommon}s.";
|
||||
$lang->project->error->emptyBranch = 'Branch can not be empty!';
|
||||
|
||||
$lang->project->hundredMillion = 'Hundred Million';
|
||||
|
||||
$lang->project->unitList['CNY'] = 'RMB';
|
||||
@@ -385,7 +388,6 @@ $lang->project->agileplus = 'Agile +';
|
||||
$lang->project->waterfallplus = 'Waterfall +';
|
||||
$lang->project->cannotCreateChild = 'It is not empty, so you cannot add a child. You can add a parent for it, and then create a child.';
|
||||
$lang->project->emptyPM = 'No manager';
|
||||
$lang->project->emptyBranch = 'Branch can not be empty!';
|
||||
$lang->project->cannotChangeToCat = "It is not empty, so you cannot change it to a parent.";
|
||||
$lang->project->cannotCancelCat = "It has child {$lang->projectCommon}s, so you cannot unmark the parent.";
|
||||
$lang->project->parentBeginEnd = "Parent begin&end date: %s ~ %s";
|
||||
|
||||
@@ -64,8 +64,6 @@ $lang->project->daysGreaterProject = "Days cannot be greater than days of {$lan
|
||||
$lang->project->errorHours = 'Hours/Day cannot be greater than『24』';
|
||||
$lang->project->workdaysExceed = 'No more than『%s』working days';
|
||||
$lang->project->teamMembersCount = ', there are %s team members.';
|
||||
$lang->project->budgetNumber = '『Budget』must be numbers.';
|
||||
$lang->project->budgetGe0 = '『Budget』must be greater than or equal to 0.';
|
||||
$lang->project->allProjects = "All {$lang->projectCommon}s";
|
||||
$lang->project->ignore = 'Ignore';
|
||||
$lang->project->disableExecution = "{$lang->projectCommon} of disable {$lang->executionCommon}";
|
||||
@@ -213,8 +211,6 @@ $lang->project->noProgram = "Independent {$lang->projectCommon}s";
|
||||
|
||||
$lang->project->laneColorList = array('#32C5FF', '#006AF1', '#9D28B2', '#FF8F26', '#FFC20E', '#00A78E', '#7FBB00', '#424BAC', '#C0E9FF', '#EC2761');
|
||||
|
||||
$lang->project->productNotEmpty = "Please link {$lang->productCommon}s or create {$lang->productCommon}s.";
|
||||
$lang->project->existProductName = "{$lang->productCommon} name already exists.";
|
||||
$lang->project->changeProgram = "%s > Change {$lang->projectCommon}";
|
||||
$lang->project->changeProgramTip = "Once the program is edited, the {$lang->productCommon} that is linked to this program will be changed. Do you want to edit it?";
|
||||
$lang->project->linkedProjectsTip = "Linked {$lang->projectCommon}s are as follows";
|
||||
@@ -243,6 +239,13 @@ $lang->project->tip->actived = 'The project has been activated. Re-activated
|
||||
$lang->project->tip->group = "It's a Kanban project. Editing privilege group is not available.";
|
||||
$lang->project->tip->whitelist = "It's a public project with open permissions. No need to edit whitelists.";
|
||||
|
||||
$lang->project->error = new stdclass();
|
||||
$lang->project->error->existProductName = "{$lang->productCommon} name already exists.";
|
||||
$lang->project->error->budgetGe0 = '『Budget』must be greater than or equal to 0.';
|
||||
$lang->project->error->budgetNumber = '『Budget』must be numbers.';
|
||||
$lang->project->error->productNotEmpty = "Please link {$lang->productCommon}s or create {$lang->productCommon}s.";
|
||||
$lang->project->error->emptyBranch = 'Branch can not be empty!';
|
||||
|
||||
$lang->project->tenThousand = 'Ten Thousand';
|
||||
$lang->project->hundredMillion = 'Hundred Million';
|
||||
|
||||
@@ -387,7 +390,6 @@ $lang->project->agileplus = 'Agile +';
|
||||
$lang->project->waterfallplus = 'Waterfall +';
|
||||
$lang->project->cannotCreateChild = 'It is not empty, so you cannot add a child. You can add a parent for it, and then create a child.';
|
||||
$lang->project->emptyPM = 'No manager';
|
||||
$lang->project->emptyBranch = 'Branch can not be empty!';
|
||||
$lang->project->cannotChangeToCat = "It is not empty, so you cannot change it to a parent.";
|
||||
$lang->project->cannotCancelCat = "It has child {$lang->projectCommon}s, so you cannot unmark the parent.";
|
||||
$lang->project->parentBeginEnd = "Parent begin&end date: %s ~ %s";
|
||||
|
||||
@@ -64,8 +64,6 @@ $lang->project->daysGreaterProject = "Days cannot be greater than days of {$lan
|
||||
$lang->project->errorHours = 'Hours/Day cannot be greater than『24』';
|
||||
$lang->project->workdaysExceed = 'No more than『%s』working days';
|
||||
$lang->project->teamMembersCount = ', there are %s team members.';
|
||||
$lang->project->budgetNumber = '『Budget』must be numbers.';
|
||||
$lang->project->budgetGe0 = '『Budget』must be greater than or equal to 0.';
|
||||
$lang->project->allProjects = "All {$lang->projectCommon}s";
|
||||
$lang->project->ignore = 'Ignore';
|
||||
$lang->project->disableExecution = "{$lang->projectCommon} of disable {$lang->executionCommon}";
|
||||
@@ -212,8 +210,6 @@ $lang->project->noProgram = "Independent {$lang->projectCommon}s";
|
||||
|
||||
$lang->project->laneColorList = array('#32C5FF', '#006AF1', '#9D28B2', '#FF8F26', '#FFC20E', '#00A78E', '#7FBB00', '#424BAC', '#C0E9FF', '#EC2761');
|
||||
|
||||
$lang->project->productNotEmpty = "Please link {$lang->productCommon}s or create {$lang->productCommon}s.";
|
||||
$lang->project->existProductName = "{$lang->productCommon} name already exists.";
|
||||
$lang->project->changeProgram = "%s > Change {$lang->projectCommon}";
|
||||
$lang->project->changeProgramTip = "Once the program is edited, the {$lang->productCommon} that is linked to this program will be changed. Do you want to edit it?";
|
||||
$lang->project->linkedProjectsTip = "Linked {$lang->projectCommon}s are as follows";
|
||||
@@ -243,6 +239,13 @@ $lang->project->tip->actived = 'The project has been activated. Re-activated
|
||||
$lang->project->tip->group = "It's a Kanban project. Editing privilege group is not available.";
|
||||
$lang->project->tip->whitelist = "It's a public project with open permissions. No need to edit whitelists.";
|
||||
|
||||
$lang->project->error = new stdclass();
|
||||
$lang->project->error->existProductName = "{$lang->productCommon} name already exists.";
|
||||
$lang->project->error->budgetGe0 = '『Budget』must be greater than or equal to 0.';
|
||||
$lang->project->error->budgetNumber = '『Budget』must be numbers.';
|
||||
$lang->project->error->productNotEmpty = "Please link {$lang->productCommon}s or create {$lang->productCommon}s.";
|
||||
$lang->project->error->emptyBranch = 'Branch can not be empty!';
|
||||
|
||||
$lang->project->hundredMillion = 'Hundred Million';
|
||||
|
||||
$lang->project->unitList['CNY'] = 'RMB';
|
||||
@@ -385,7 +388,6 @@ $lang->project->agileplus = 'Agile +';
|
||||
$lang->project->waterfallplus = 'Waterfall +';
|
||||
$lang->project->cannotCreateChild = 'It is not empty, so you cannot add a child. You can add a parent for it, and then create a child.';
|
||||
$lang->project->emptyPM = 'No manager';
|
||||
$lang->project->emptyBranch = 'Branch can not be empty!';
|
||||
$lang->project->cannotChangeToCat = "It is not empty, so you cannot change it to a parent.";
|
||||
$lang->project->cannotCancelCat = "It has child {$lang->projectCommon}s, so you cannot unmark the parent.";
|
||||
$lang->project->parentBeginEnd = "Parent begin&end date: %s ~ %s";
|
||||
|
||||
@@ -64,8 +64,6 @@ $lang->project->daysGreaterProject = "可用工日不能大于{$lang->projectCo
|
||||
$lang->project->errorHours = '可用工时/天不能大于『24』';
|
||||
$lang->project->workdaysExceed = '可用工作日不能超过『%s』天';
|
||||
$lang->project->teamMembersCount = ',团队成员共%s人。';
|
||||
$lang->project->budgetNumber = '『预算』金额必须为数字。';
|
||||
$lang->project->budgetGe0 = '『预算』金额必须大于等于0。';
|
||||
$lang->project->allProjects = "所有{$lang->projectCommon}";
|
||||
$lang->project->ignore = '忽略';
|
||||
$lang->project->disableExecution = "不启用{$lang->executionCommon}的{$lang->projectCommon}";
|
||||
@@ -212,8 +210,6 @@ $lang->project->noProgram = "无项目集归属{$lang->projectCommon}";
|
||||
|
||||
$lang->project->laneColorList = array('#32C5FF', '#006AF1', '#9D28B2', '#FF8F26', '#FFC20E', '#00A78E', '#7FBB00', '#424BAC', '#C0E9FF', '#EC2761');
|
||||
|
||||
$lang->project->productNotEmpty = "请关联{$lang->productCommon}或创建{$lang->productCommon}。";
|
||||
$lang->project->existProductName = "{$lang->productCommon}名称已存在。";
|
||||
$lang->project->changeProgram = '%s > 修改项目集';
|
||||
$lang->project->changeProgramTip = "修改项目集后,该{$lang->projectCommon}关联{$lang->productCommon}的项目集也会被修改,请确认是否修改。";
|
||||
$lang->project->linkedProjectsTip = "关联的{$lang->projectCommon}如下";
|
||||
@@ -234,6 +230,13 @@ $lang->project->allSummary = "本页共 <strong>%s</strong> 个{$lan
|
||||
$lang->project->checkedSummary = "选中 <strong>%total%</strong> 个{$lang->projectCommon}。";
|
||||
$lang->project->checkedAllSummary = "选中 <strong>%total%</strong> 个{$lang->projectCommon},未开始 <strong>%wait%</strong>,进行中 <strong>%doing%</strong>,已挂起 <strong>%suspended%</strong>,已关闭 <strong>%closed%</strong> 。";
|
||||
|
||||
$lang->project->error = new stdclass();
|
||||
$lang->project->error->existProductName = "{$lang->productCommon}名称已存在。";
|
||||
$lang->project->error->budgetGe0 = '『预算』金额必须大于等于0。';
|
||||
$lang->project->error->budgetNumber = '『预算』金额必须为数字。';
|
||||
$lang->project->error->productNotEmpty = "请关联{$lang->productCommon}或创建{$lang->productCommon}。";
|
||||
$lang->project->error->emptyBranch = '分支不能为空!';
|
||||
|
||||
$lang->project->tip = new stdclass();
|
||||
$lang->project->tip->closed = '该项目已是关闭状态,无须关闭。';
|
||||
$lang->project->tip->notSuspend = '该项目已关闭,不可进行挂起操作。';
|
||||
@@ -386,7 +389,6 @@ $lang->project->agileplus = '融合敏捷';
|
||||
$lang->project->waterfallplus = '融合瀑布';
|
||||
$lang->project->cannotCreateChild = "该{$lang->projectCommon}已经有实际的内容,无法直接添加子{$lang->projectCommon}。您可以为当前{$lang->projectCommon}创建一个父{$lang->projectCommon},然后在新的父{$lang->projectCommon}下面添加子{$lang->projectCommon}。";
|
||||
$lang->project->emptyPM = '暂无';
|
||||
$lang->project->emptyBranch = '分支不能为空!';
|
||||
$lang->project->cannotChangeToCat = "该{$lang->projectCommon}已经有实际的内容,无法修改为父{$lang->projectCommon}";
|
||||
$lang->project->cannotCancelCat = "该{$lang->projectCommon}下已经有子{$lang->projectCommon},无法取消父{$lang->projectCommon}标记";
|
||||
$lang->project->parentBeginEnd = "父{$lang->projectCommon}起止时间:%s ~ %s";
|
||||
|
||||
+7
-113
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
class projectModel extends model
|
||||
{
|
||||
/**
|
||||
@@ -1266,120 +1267,13 @@ class projectModel extends model
|
||||
* @access public
|
||||
* @return int|bool
|
||||
*/
|
||||
public function create()
|
||||
public function create(object $project, object $postData)
|
||||
{
|
||||
$project = fixer::input('post')
|
||||
->callFunc('name', 'trim')
|
||||
->setDefault('status', 'wait')
|
||||
->setIF($this->post->delta == 999, 'end', LONG_TIME)
|
||||
->setIF($this->post->delta == 999, 'days', 0)
|
||||
->setIF($this->post->acl == 'open', 'whitelist', '')
|
||||
->setIF(!isset($_POST['whitelist']), 'whitelist', '')
|
||||
->setIF(!isset($_POST['multiple']), 'multiple', '1')
|
||||
->setDefault('openedBy', $this->app->user->account)
|
||||
->setDefault('openedDate', helper::now())
|
||||
->setDefault('team', $this->post->name)
|
||||
->setDefault('lastEditedBy', $this->app->user->account)
|
||||
->setDefault('lastEditedDate', helper::now())
|
||||
->setDefault('days', '0')
|
||||
->add('type', 'project')
|
||||
->join('whitelist', ',')
|
||||
->stripTags($this->config->project->editor->create['id'], $this->config->allowedTags)
|
||||
->remove('uid,products,branch,plans,delta,newProduct,productName,future,contactListMenu,teamMembers')
|
||||
->get();
|
||||
if(!isset($this->config->setCode) or $this->config->setCode == 0) unset($project->code);
|
||||
|
||||
/* Lean mode relation defaultProgram. */
|
||||
if($this->config->systemMode == 'light') $project->parent = $this->config->global->defaultProgram;
|
||||
|
||||
$linkedProductsCount = 0;
|
||||
if($project->hasProduct && isset($_POST['products']))
|
||||
{
|
||||
foreach($_POST['products'] as $product)
|
||||
{
|
||||
if(!empty($product)) $linkedProductsCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if($_POST['products'])
|
||||
{
|
||||
$topProgramID = $this->loadModel('program')->getTopByID($project->parent);
|
||||
$multipleProducts = $this->loadModel('product')->getMultiBranchPairs($topProgramID);
|
||||
foreach($_POST['products'] as $index => $productID)
|
||||
{
|
||||
if(isset($multipleProducts[$productID]) and empty($_POST['branch'][$index]))
|
||||
{
|
||||
dao::$errors[] = $this->lang->project->emptyBranch;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$program = new stdClass();
|
||||
if($project->parent)
|
||||
{
|
||||
$program = $this->dao->select('*')->from(TABLE_PROGRAM)->where('id')->eq($project->parent)->fetch();
|
||||
|
||||
/* Judge products not empty. */
|
||||
if($project->hasProduct && empty($linkedProductsCount) and !isset($_POST['newProduct']))
|
||||
{
|
||||
dao::$errors['products0'] = $this->lang->project->productNotEmpty;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Judge workdays is legitimate. */
|
||||
$workdays = helper::diffDate($project->end, $project->begin) + 1;
|
||||
if(isset($project->days) and $project->days > $workdays)
|
||||
{
|
||||
dao::$errors['days'] = sprintf($this->lang->project->workdaysExceed, $workdays);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!empty($project->budget))
|
||||
{
|
||||
if(!is_numeric($project->budget))
|
||||
{
|
||||
dao::$errors['budget'] = sprintf($this->lang->project->budgetNumber);
|
||||
return false;
|
||||
}
|
||||
else if(is_numeric($project->budget) and ($project->budget < 0))
|
||||
{
|
||||
dao::$errors['budget'] = sprintf($this->lang->project->budgetGe0);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$project->budget = round((float)$this->post->budget, 2);
|
||||
}
|
||||
}
|
||||
|
||||
/* When select create new product, product name cannot be empty and duplicate. */
|
||||
if($project->hasProduct && isset($_POST['newProduct']))
|
||||
{
|
||||
if(empty($_POST['productName']))
|
||||
{
|
||||
$this->app->loadLang('product');
|
||||
dao::$errors['productName'] = sprintf($this->lang->error->notempty, $this->lang->product->name);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$programID = isset($project->parent) ? $project->parent : 0;
|
||||
$existProductName = $this->dao->select('name')->from(TABLE_PRODUCT)->where('name')->eq($_POST['productName'])->andWhere('program')->eq($programID)->fetch('name');
|
||||
if(!empty($existProductName))
|
||||
{
|
||||
dao::$errors['productName'] = $this->lang->project->existProductName;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$requiredFields = $this->config->project->create->requiredFields;
|
||||
if($this->post->delta == 999) $requiredFields = trim(str_replace(',end,', ',', ",{$requiredFields},"), ',');
|
||||
if($postData->rawdata->delta == 999) $requiredFields = trim(str_replace(',end,', ',', ",{$requiredFields},"), ',');
|
||||
|
||||
$this->lang->error->unique = $this->lang->error->repeat;
|
||||
$project = $this->loadModel('file')->processImgURL($project, $this->config->project->editor->create['id'], $this->post->uid);
|
||||
$project = $this->loadModel('file')->processImgURL($project, $this->config->project->editor->create['id'], $postData->rawdata->uid);
|
||||
$this->dao->insert(TABLE_PROJECT)->data($project)
|
||||
->autoCheck()
|
||||
->batchcheck($requiredFields, 'notempty')
|
||||
@@ -1460,9 +1354,9 @@ class projectModel extends model
|
||||
{
|
||||
/* If parent not empty, link products or create products. */
|
||||
$product = new stdclass();
|
||||
$product->name = $project->hasProduct && $this->post->productName ? $this->post->productName : $project->name;
|
||||
$product->name = $project->hasProduct && $postData->rawdata->productName ? $postData->rawdata->productName : $project->name;
|
||||
$product->shadow = zget($project, 'vision', 'rnd') == 'rnd' ? (int)empty($project->hasProduct) : 1;
|
||||
$product->bind = $this->post->parent ? 0 : 1;
|
||||
$product->bind = $postData->rawdata->parent ? 0 : 1;
|
||||
$product->program = $project->parent ? current(array_filter(explode(',', $program->path))) : 0;
|
||||
$product->acl = $project->acl == 'open' ? 'open' : 'private';
|
||||
$product->PO = $project->PM;
|
||||
@@ -1510,7 +1404,7 @@ class projectModel extends model
|
||||
|
||||
/* Save order. */
|
||||
$this->dao->update(TABLE_PROJECT)->set('`order`')->eq($projectID * 5)->where('id')->eq($projectID)->exec();
|
||||
$this->file->updateObjectID($this->post->uid, $projectID, 'project');
|
||||
$this->file->updateObjectID($postData->rawdata->uid, $projectID, 'project');
|
||||
$this->loadModel('program')->setTreePath($projectID);
|
||||
|
||||
/* Add project admin. */
|
||||
|
||||
@@ -4,55 +4,77 @@ include dirname(__FILE__, 5) . "/test/lib/init.php";
|
||||
include dirname(__FILE__, 2) . '/project.class.php';
|
||||
su('admin');
|
||||
|
||||
$program = zdTable('project');
|
||||
$program->id->range('1');
|
||||
$program->name->range('项目集一');
|
||||
$program->model->range('program');
|
||||
$program->code->range('项目集代号');
|
||||
$program->desc->range('测试项目集');
|
||||
$program->gen(1);
|
||||
|
||||
/**
|
||||
|
||||
title=测试 projectModel->create();
|
||||
timeout=0
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
创建新项目 >> 测试新增项目一
|
||||
项目名称为空时 >> 『项目名称』不能为空。
|
||||
项目的完成时间为空 >> 『计划完成』不能为空。
|
||||
项目的计划完成时间大于计划开始时间 >> 『计划完成』应当大于『2022-02-07』。
|
||||
项目的开始时间为空 >> 『计划开始』不能为空。
|
||||
- 执行projectClass模块的cr方法,参数是$normalProject, $postData,属性name @测试新增项目一
|
||||
- 执行projectClass模块的cr方法,参数是$emptyNameProject, $postData,属性name @『项目名称』不能为空。
|
||||
|
||||
- 执行projectClass模块的cr方法,参数是$emptyEndProject, $postData,属性end @『计划完成』不能为空。
|
||||
|
||||
- 执行projectClass模块的cr方法,参数是$beginGtEndProject, $postData,属性end @『计划完成』应当大于『2022-02-07』。
|
||||
|
||||
- 执行projectClass模块的cr方法,参数是$emptyBeginProject, $postData,属性begin @『计划开始』不能为空。
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
global $tester;
|
||||
$tester->app->loadConfig('execution');
|
||||
$project = new Project();
|
||||
$projectClass = new project();
|
||||
|
||||
$data = array(
|
||||
'parent' => 1,
|
||||
'name' => '测试新增项目一',
|
||||
'budget' => '',
|
||||
'budgetUnit' => 'CNY',
|
||||
'begin' => '2022-02-07',
|
||||
'end' => '2022-03-01',
|
||||
'desc' => '测试项目描述',
|
||||
'acl' => 'private',
|
||||
'whitelist' => '',
|
||||
'PM' => '',
|
||||
'products' => array(1)
|
||||
);
|
||||
$project = new stdclass();
|
||||
$project->parent = 0;
|
||||
$project->name = '测试新增项目一';
|
||||
$project->budget = '';
|
||||
$project->budgetUnit = 'CNY';
|
||||
$project->begin = '2022-02-07';
|
||||
$project->end = '2023-01-01';
|
||||
$project->desc = '测试项目描述';
|
||||
$project->acl = 'private';
|
||||
$project->whitelist = 'user1,user2,user3';
|
||||
$project->PM = 'admin';
|
||||
$project->type = 'project';
|
||||
$project->model = 'scrum';
|
||||
$project->multiple = 1;
|
||||
$project->hasProduct = 1;
|
||||
|
||||
$normalProject = $data;
|
||||
$postData = new stdclass();
|
||||
$postData->rowdata = clone $project;
|
||||
$postData->rowdata->uid = '64dda2xc';
|
||||
$postData->rowdata->delta = 0;
|
||||
$postData->rowdata->products = array(1);
|
||||
|
||||
$emptyNameProject = $data;
|
||||
$emptyNameProject['name'] = '';
|
||||
$normalProject = clone $project;
|
||||
|
||||
$emptyBeginProject = $data;
|
||||
$emptyBeginProject['begin'] = '';
|
||||
$emptyNameProject = clone $project;
|
||||
$emptyNameProject->name = '';
|
||||
|
||||
$emptyEndProject = $data;
|
||||
$emptyEndProject['end'] = '';
|
||||
$emptyBeginProject = clone $project;
|
||||
$emptyBeginProject->name = '测试新增项目二';
|
||||
$emptyBeginProject->begin = '';
|
||||
|
||||
$beginGtEndProject = $data;
|
||||
$beginGtEndProject['end'] = '2022-01-10';
|
||||
$emptyEndProject = clone $project;
|
||||
$emptyEndProject->end = '';
|
||||
$emptyEndProject->name = '测试新增项目三';
|
||||
|
||||
r($project->create($normalProject)) && p('name') && e('测试新增项目一'); // 创建新项目
|
||||
r($project->create($emptyNameProject)) && p('message[name]:0') && e('『项目名称』不能为空。'); // 项目名称为空时
|
||||
r($project->create($emptyEndProject)) && p('message[end]:0') && e('『计划完成』不能为空。'); // 项目的完成时间为空
|
||||
r($project->create($beginGtEndProject)) && p('message[end]:0') && e('『计划完成』应当大于『2022-02-07』。'); // 项目的计划完成时间大于计划开始时间
|
||||
r($project->create($emptyBeginProject)) && p('message[begin]:0') && e('『计划开始』不能为空。'); // 项目的开始时间为空
|
||||
$beginGtEndProject = clone $project;
|
||||
$beginGtEndProject->end = '2021-01-10';
|
||||
$beginGtEndProject->name = '测试新增项目四';
|
||||
|
||||
r($projectClass->create($normalProject, $postData)) && p('name') && e('测试新增项目一');
|
||||
r($projectClass->create($emptyNameProject, $postData)) && p('message[name]:0') && e('『项目名称』不能为空。');
|
||||
r($projectClass->create($emptyEndProject, $postData)) && p('message[end]:0') && e('『计划完成』不能为空。');
|
||||
r($projectClass->create($beginGtEndProject, $postData)) && p('message[end]:0') && e('『计划完成』应当大于『2022-02-07』。');
|
||||
r($projectClass->create($emptyBeginProject, $postData)) && p('message[begin]:0') && e('『计划开始』不能为空。');
|
||||
@@ -12,10 +12,10 @@ title=测试 projectModel->start();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 执行project模块的start方法,参数是11, $data- ,属性0 @status
|
||||
@status
|
||||
- 执行project模块的start方法,参数是12, $data- ,属性0 @doing
|
||||
@doing
|
||||
- 执行project模块的start方法,参数是11, $data,属性0 @status
|
||||
|
||||
- 执行project模块的start方法,参数是12, $data,属性0 @doing
|
||||
|
||||
- 执行project模块的start方法,参数是13, $data
|
||||
- 属性name @0
|
||||
- 属性status @0
|
||||
|
||||
@@ -40,12 +40,9 @@ class Project
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function create($params)
|
||||
public function create($project, $postData)
|
||||
{
|
||||
$_POST = $params;
|
||||
|
||||
$projectID = $this->project->create();
|
||||
unset($_POST);
|
||||
$projectID = $this->project->create($project, $postData);
|
||||
|
||||
if(dao::isError()) return array('message' => dao::getError());
|
||||
|
||||
|
||||
+210
-21
@@ -10,8 +10,148 @@ declare(strict_types=1);
|
||||
*/
|
||||
class projectZen extends project
|
||||
{
|
||||
/**
|
||||
* Append extras data to post data.
|
||||
*
|
||||
* @param object $postData
|
||||
* @access protected
|
||||
* @return int|object
|
||||
*/
|
||||
protected function prepareCreateExtras(object $postData): object
|
||||
{
|
||||
$rawdata = $postData->rawdata;
|
||||
$project = $postData->setDefault('status', 'wait')
|
||||
->setIF($rawdata->delta == 999, 'end', LONG_TIME)
|
||||
->setIF($rawdata->delta == 999, 'days', 0)
|
||||
->setIF($rawdata->acl == 'open', 'whitelist', '')
|
||||
->setIF(!isset($rawdata->whitelist), 'whitelist', '')
|
||||
->setIF(!isset($rawdata->multiple), 'multiple', '1')
|
||||
->setDefault('openedBy', $this->app->user->account)
|
||||
->setDefault('openedDate', helper::now())
|
||||
->setDefault('team', $rawdata->name)
|
||||
->setDefault('lastEditedBy', $this->app->user->account)
|
||||
->setDefault('lastEditedDate', helper::now())
|
||||
->setDefault('days', '0')
|
||||
->add('type', 'project')
|
||||
->join('whitelist', ',')
|
||||
->join('auth', ',')
|
||||
->stripTags($this->config->project->editor->create['id'], $this->config->allowedTags)
|
||||
->get();
|
||||
|
||||
if(!isset($this->config->setCode) or $this->config->setCode == 0) unset($project->code);
|
||||
|
||||
/* Lean mode relation defaultProgram. */
|
||||
if($this->config->systemMode == 'light') $project->parent = $this->config->global->defaultProgram;
|
||||
|
||||
if(!$this->checkProductAndBranch($rawdata, $project)) return false;
|
||||
if(!$this->checkDaysAndBudget($rawdata, $project)) return false;
|
||||
if(!$this->checkProductNameUnqiue($rawdata, $project)) return false;
|
||||
|
||||
return $project;
|
||||
}
|
||||
|
||||
private function checkProductAndBranch(object $rawdata, object $project): bool
|
||||
{
|
||||
$linkedProductsCount = 0;
|
||||
if($project->hasProduct && isset($rawdata->products))
|
||||
{
|
||||
foreach($rawdata->products as $product)
|
||||
{
|
||||
if(!empty($product)) $linkedProductsCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if($rawdata->products)
|
||||
{
|
||||
$topProgramID = $this->loadModel('program')->getTopByID($project->parent);
|
||||
$multipleProducts = $this->loadModel('product')->getMultiBranchPairs($topProgramID);
|
||||
foreach($rawdata->products as $index => $productID)
|
||||
{
|
||||
if(isset($multipleProducts[$productID]) and empty($rawdata->branch[$index]))
|
||||
{
|
||||
dao::$errors[] = $this->lang->project->error->emptyBranch;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$program = new stdClass();
|
||||
if($project->parent)
|
||||
{
|
||||
$program = $this->dao->select('*')->from(TABLE_PROGRAM)->where('id')->eq($project->parent)->fetch();
|
||||
|
||||
/* Judge products not empty. */
|
||||
if($project->hasProduct && empty($linkedProductsCount) and !isset($rawdata->newProduct))
|
||||
{
|
||||
dao::$errors['products0'] = $this->lang->project->error->productNotEmpty;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function checkDaysAndBudget(object $rawdata, object $project): bool
|
||||
{
|
||||
/* Judge workdays is legitimate. */
|
||||
$workdays = helper::diffDate($project->end, $project->begin) + 1;
|
||||
if(isset($project->days) and $project->days > $workdays)
|
||||
{
|
||||
dao::$errors['days'] = sprintf($this->lang->project->workdaysExceed, $workdays);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!empty($project->budget))
|
||||
{
|
||||
if(!is_numeric($project->budget))
|
||||
{
|
||||
dao::$errors['budget'] = sprintf($this->lang->project->error->budgetNumber);
|
||||
return false;
|
||||
}
|
||||
else if(is_numeric($project->budget) and ($project->budget < 0))
|
||||
{
|
||||
dao::$errors['budget'] = sprintf($this->lang->project->error->budgetGe0);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$project->budget = round((float)$rawdata->budget, 2);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function checkProductNameUnqiue(object $rawdata, object $project): bool
|
||||
{
|
||||
/* When select create new product, product name cannot be empty and duplicate. */
|
||||
if($project->hasProduct && isset($rawdata->newProduct))
|
||||
{
|
||||
if(empty($rawdata->productName))
|
||||
{
|
||||
$this->app->loadLang('product');
|
||||
dao::$errors['productName'] = sprintf($this->lang->error->notempty, $this->lang->product->name);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$programID = isset($project->parent) ? $project->parent : 0;
|
||||
$existProductName = $this->dao->select('name')->from(TABLE_PRODUCT)->where('name')->eq($rawdata->productName)->andWhere('program')->eq($programID)->fetch('name');
|
||||
if(!empty($existProductName))
|
||||
{
|
||||
dao::$errors['productName'] = $this->lang->project->error->existProductName;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send variables to create page.
|
||||
*
|
||||
* @param string $model
|
||||
* @param int $programID
|
||||
* @param int $copyProjectID
|
||||
@@ -19,9 +159,10 @@ class projectZen extends project
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function buildCreateForm(string $model, int $programID, int $copyProjectID, string $extra):void
|
||||
protected function buildCreateForm(string $model, int $programID, int $copyProjectID, string $extra): void
|
||||
{
|
||||
$this->loadModel('product');
|
||||
$this->loadModel('program');
|
||||
|
||||
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
|
||||
parse_str($extra, $output);
|
||||
@@ -29,20 +170,9 @@ class projectZen extends project
|
||||
if($this->app->tab == 'program' and $programID) $this->loadModel('program')->setMenu($programID);
|
||||
if($this->app->tab == 'product' and !empty($output['productID'])) $this->loadModel('product')->setMenu($output['productID']);
|
||||
if($this->app->tab == 'doc') unset($this->lang->doc->menu->project['subMenu']);
|
||||
$this->session->set('projectModel', $model);
|
||||
|
||||
if($copyProjectID)
|
||||
{
|
||||
$copyProject = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($copyProjectID)->fetch();
|
||||
$products = $this->product->getProducts($copyProjectID);
|
||||
|
||||
if(!$copyProject->hasProduct) $shadow = 1;
|
||||
foreach($products as $product)
|
||||
{
|
||||
$branches = implode(',', $product->branches);
|
||||
$copyProject->productPlans[$product->id] = $this->loadModel('productplan')->getPairs($product->id, $branches, 'noclosed', true);
|
||||
}
|
||||
}
|
||||
if($copyProjectID) $copyProject = $this->copyProject((int)$copyProjectID);
|
||||
$shadow = empty($copyProject->hasProduct) ? 1 : 0;
|
||||
|
||||
if($this->view->globalDisableProgram) $programID = $this->config->global->defaultProgram;
|
||||
$topProgramID = $this->program->getTopByID($programID);
|
||||
@@ -53,10 +183,6 @@ class projectZen extends project
|
||||
$this->lang->project->subAclList = $this->lang->project->kanbanSubAclList;
|
||||
}
|
||||
|
||||
$sprintConcept = empty($this->config->custom->sprintConcept) ?
|
||||
$this->config->executionCommonList[$this->app->getClientLang()][0] :
|
||||
$this->config->executionCommonList[$this->app->getClientLang()][1];
|
||||
|
||||
$withProgram = $this->config->systemMode == 'ALM' ? true : false;
|
||||
$allProducts = array('0' => '') + $this->program->getProductPairs($programID, 'all', 'noclosed', '', $shadow, $withProgram);
|
||||
$parentProgram = $this->loadModel('program')->getByID($programID);
|
||||
@@ -66,13 +192,10 @@ class projectZen extends project
|
||||
$this->view->model = $model;
|
||||
$this->view->pmUsers = $this->loadModel('user')->getPairs('noclosed|nodeleted|pmfirst');
|
||||
$this->view->users = $this->user->getPairs('noclosed|nodeleted');
|
||||
$this->view->products = $products;
|
||||
$this->view->programID = $programID;
|
||||
$this->view->productID = isset($output['productID']) ? $output['productID'] : 0;
|
||||
$this->view->branchID = isset($output['branchID']) ? $output['branchID'] : 0;
|
||||
$this->view->allProducts = $allProducts;
|
||||
$this->view->productPlans = array('0' => '') + $productPlans;
|
||||
$this->view->branchGroups = $this->loadModel('branch')->getByProducts(array_keys($products), 'noclosed');
|
||||
$this->view->multiBranchProducts = $this->product->getMultiBranchPairs($topProgramID);
|
||||
$this->view->copyProjects = $this->project->getPairsByModel($model);
|
||||
$this->view->copyProjectID = $copyProjectID;
|
||||
@@ -85,6 +208,72 @@ class projectZen extends project
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get copy project and send variables to create page.
|
||||
*
|
||||
* @param int $copyProjectID
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
private function getCopyProject(int $copyProjectID): object
|
||||
{
|
||||
$copyProject = $this->project->getByID($copyProjectID);
|
||||
$products = $this->product->getProducts($copyProjectID);
|
||||
|
||||
foreach($products as $product)
|
||||
{
|
||||
$branches = implode(',', $product->branches);
|
||||
$copyProject->productPlans[$product->id] = $this->loadModel('productplan')->getPairs($product->id, $branches, 'noclosed', true);
|
||||
}
|
||||
|
||||
$this->view->branchGroups = $this->loadModel('branch')->getByProducts(array_keys($products), 'noclosed');
|
||||
$this->view->products = $products;
|
||||
$this->view->copyProject = $copyProject;
|
||||
|
||||
return $copyProject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Link plan's stories after create a project.
|
||||
*
|
||||
* @param object $postData
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function linkPlanStories(object $postData)
|
||||
{
|
||||
$planIdList = array();
|
||||
foreach($postData->rawdata->plans as $plans)
|
||||
{
|
||||
foreach($plans as $planID)
|
||||
{
|
||||
$planIdList[$planID] = $planID;
|
||||
}
|
||||
}
|
||||
|
||||
$planStoryGroup = $this->loadModel('story')->getStoriesByPlanIdList($planIdList);
|
||||
foreach($planIdList as $planID)
|
||||
{
|
||||
$planStories = $planProducts = array();
|
||||
$planStory = isset($planStoryGroup[$planID]) ? $planStoryGroup[$planID] : array();
|
||||
if(!empty($planStory))
|
||||
{
|
||||
foreach($planStory as $id => $story)
|
||||
{
|
||||
if($story->status == 'draft' or $story->status == 'reviewing')
|
||||
{
|
||||
unset($planStory[$id]);
|
||||
continue;
|
||||
}
|
||||
$planProducts[$story->id] = $story->product;
|
||||
}
|
||||
|
||||
$planStories = array_keys($planStory);
|
||||
$this->loadModel('execution')->linkStory($projectID, $planStories, $planProducts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append extras data to post data.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user