* Refactor project-create method.

This commit is contained in:
sunguangming
2023-04-27 19:29:00 +08:00
parent eaf718d7a6
commit e6586c84a2
11 changed files with 338 additions and 236 deletions
+18 -3
View File
@@ -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
View File
@@ -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&section=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)));
}
}
+7 -5
View File
@@ -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";
+7 -5
View File
@@ -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";
+7 -5
View File
@@ -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";
+7 -5
View File
@@ -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
View File
@@ -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. */
+57 -35
View File
@@ -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('『计划开始』不能为空。');
+4 -4
View File
@@ -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
+2 -5
View File
@@ -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
View File
@@ -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.
*