diff --git a/module/branch/control.php b/module/branch/control.php index f38cc8ed15..217cbd670f 100644 --- a/module/branch/control.php +++ b/module/branch/control.php @@ -113,7 +113,7 @@ class branch extends control */ public function ajaxGetBranches($productID, $oldBranch = 0, $param = '') { - $product = $this->loadModel('product')->getById($productID, $param); + $product = $this->loadModel('product')->getById($productID); if(empty($product) or $product->type == 'normal') die(); $branches = $this->branch->getPairs($productID, $param); diff --git a/module/product/model.php b/module/product/model.php index 1009366af7..8070495ab7 100644 --- a/module/product/model.php +++ b/module/product/model.php @@ -445,7 +445,7 @@ class productModel extends model * @access public * @return array */ - public function getAbnormalProductPairs($programID = 0) + public function getMultiBranchPairs($programID = 0) { return $this->dao->select('id')->from(TABLE_PRODUCT) ->where('deleted')->eq(0) diff --git a/module/productplan/model.php b/module/productplan/model.php index 8939a4fe90..3a6e3da46f 100644 --- a/module/productplan/model.php +++ b/module/productplan/model.php @@ -178,13 +178,13 @@ class productplanModel extends model * @access public * @return array */ - public function getPairs($product = 0, $branch = 0, $expired = '', $skipParent = false) + public function getPairs($product = 0, $branch = '', $expired = '', $skipParent = false) { $date = date('Y-m-d'); $plans = $this->dao->select('id,title,parent,begin,end')->from(TABLE_PRODUCTPLAN) ->where('product')->in($product) ->andWhere('deleted')->eq(0) - ->andWhere('branch')->eq($branch) + ->beginIF($branch !== '')->andWhere('branch')->eq($branch)->fi() ->beginIF($expired == 'unexpired')->andWhere('end')->ge($date)->fi() ->beginIF($skipParent)->andWhere('parent')->ne(-1)->fi() ->orderBy('begin desc') @@ -307,6 +307,42 @@ class productplanModel extends model return array('' => '') + $planPairs; } + /** + * Get plan group by product id list. + * + * @param string|array $products + * @access public + * @return array + */ + public function getGroupByProduct($products = '') + { + $plans = $this->dao->select('id,title,parent,begin,end,product,branch')->from(TABLE_PRODUCTPLAN) + ->where('deleted')->eq(0) + ->beginIF($products)->andWhere('product')->in($products)->fi() + ->fetchAll('id'); + + if(!empty($plans)) $plans = $this->reorder4Children($plans); + + $parent = 0; + $parentTitle = ''; + $planGroup = array(); + foreach($plans as $plan) + { + if(!isset($planGroup[$plan->product])) $planGroup[$plan->product] = array(); + if(!isset($planGroup[$plan->product][$plan->branch])) $planGroup[$plan->product][$plan->branch] = array('' => ''); + + if($plan->parent == '-1') + { + $parent = $plan->id; + $parentTitle = $plan->title; + } + if($plan->parent > 0 and $plan->parent == $parent) $plan->title = $parentTitle . ' /' . $plan->title; + $planGroup[$plan->product][$plan->branch][$plan->id] = $plan->title . " [{$plan->begin} ~ {$plan->end}]"; + if($plan->begin == '2030-01-01' and $plan->end == '2030-01-01') $planGroup[$plan->product][$plan->branch][$plan->id] = $plan->title . ' ' . $this->lang->productplan->future; + } + return $planGroup; + } + /** * Get Children plan. * diff --git a/module/project/control.php b/module/project/control.php index 2895cf0c1c..e4739122af 100644 --- a/module/project/control.php +++ b/module/project/control.php @@ -353,26 +353,28 @@ class project extends control $this->loadModel('action')->create('project', $projectID, 'opened'); /* Link the plan stories. */ - $newPlans = $this->dao->select('plan')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($projectID)->andWhere('plan')->ne(0)->fetchPairs('plan'); - if(!empty($newPlans)) + if(!empty($_POST['plans'])) { - foreach($newPlans as $planID) + foreach($_POST['plans'] as $plans) { - $planStories = $planProducts = array(); - $planStory = $this->loadModel('story')->getPlanStories($planID); - if(!empty($planStory)) + foreach($plans as $planID) { - foreach($planStory as $id => $story) + $planStories = $planProducts = array(); + $planStory = $this->loadModel('story')->getPlanStories($planID); + if(!empty($planStory)) { - if($story->status == 'draft') + foreach($planStory as $id => $story) { - unset($planStory[$id]); - continue; + if($story->status == 'draft') + { + unset($planStory[$id]); + continue; + } + $planProducts[$story->id] = $story->product; } - $planProducts[$story->id] = $story->product; + $planStories = array_keys($planStory); + $this->execution->linkStory($projectID, $planStories, $planProducts); } - $planStories = array_keys($planStory); - $this->execution->linkStory($projectID, $planStories, $planProducts); } } } @@ -442,29 +444,29 @@ class project extends control $this->view->title = $this->lang->project->create; $this->view->position[] = $this->lang->project->create; - $this->view->gobackLink = (isset($output['from']) and $output['from'] == 'global') ? $this->createLink('project', 'browse') : ''; - $this->view->pmUsers = $this->loadModel('user')->getPairs('noclosed|nodeleted|pmfirst'); - $this->view->users = $this->user->getPairs('noclosed|nodeleted'); - $this->view->copyProjects = $this->project->getPairsByModel(); - $this->view->products = $products; - $this->view->allProducts = array('0' => '') + $this->program->getProductPairs($programID, 'assign', 'noclosed'); - $this->view->productPlans = array('0' => '') + $productPlans; - $this->view->branchGroups = $this->loadModel('branch')->getByProducts(array_keys($products), 'noclosed'); - $this->view->programID = $programID; - $this->view->abnormalProducts = $this->loadModel('product')->getAbnormalProductPairs($programID); - $this->view->model = $model; - $this->view->name = $name; - $this->view->code = $code; - $this->view->team = $team; - $this->view->acl = $acl; - $this->view->auth = $auth; - $this->view->whitelist = $whitelist; - $this->view->copyProjectID = $copyProjectID; - $this->view->programList = $this->program->getParentPairs(); - $this->view->parentProgram = $parentProgram; - $this->view->URSRPairs = $this->loadModel('custom')->getURSRPairs(); - $this->view->availableBudget = $this->program->getBudgetLeft($parentProgram); - $this->view->budgetUnitList = $this->program->getBudgetUnitList(); + $this->view->gobackLink = (isset($output['from']) and $output['from'] == 'global') ? $this->createLink('project', 'browse') : ''; + $this->view->pmUsers = $this->loadModel('user')->getPairs('noclosed|nodeleted|pmfirst'); + $this->view->users = $this->user->getPairs('noclosed|nodeleted'); + $this->view->copyProjects = $this->project->getPairsByModel(); + $this->view->products = $products; + $this->view->allProducts = array('0' => '') + $this->program->getProductPairs($programID, 'assign', 'noclosed'); + $this->view->productPlans = array('0' => '') + $productPlans; + $this->view->branchGroups = $this->loadModel('branch')->getByProducts(array_keys($products), 'noclosed'); + $this->view->programID = $programID; + $this->view->multiBranchProducts = $this->loadModel('product')->getMultiBranchPairs($programID); + $this->view->model = $model; + $this->view->name = $name; + $this->view->code = $code; + $this->view->team = $team; + $this->view->acl = $acl; + $this->view->auth = $auth; + $this->view->whitelist = $whitelist; + $this->view->copyProjectID = $copyProjectID; + $this->view->programList = $this->program->getParentPairs(); + $this->view->parentProgram = $parentProgram; + $this->view->URSRPairs = $this->loadModel('custom')->getURSRPairs(); + $this->view->availableBudget = $this->program->getBudgetLeft($parentProgram); + $this->view->budgetUnitList = $this->program->getBudgetUnitList(); $this->display(); } @@ -504,7 +506,12 @@ class project extends control } /* Link the plan stories. */ - $newPlans = $this->dao->select('plan')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($projectID)->andWhere('plan')->ne(0)->fetchPairs('plan'); + $newPlans = array(); + foreach($_POST['plans'] as $plans) + { + foreach($plans as $planID) $newPlans[$planID] = $planID; + } + $diffResult = array_diff($oldPlans, $newPlans); if(!empty($newPlans) and !empty($diffResult)) { @@ -523,20 +530,21 @@ class project extends control $linkedProducts = $this->project->getProducts($projectID); $parentProject = $this->program->getByID($project->parent); $branches = $this->project->getBranchesByProject($projectID); + $plans = $this->productplan->getGroupByProduct(array_keys($linkedProducts)); + $projectStories = $this->project->getStoriesByProject($projectID); /* If the story of the product which linked the project, you don't allow to remove the product. */ $unmodifiableProducts = array(); $unmodifiableBranches = array(); foreach($linkedProducts as $productID => $linkedProduct) { - if(!isset($allProducts[$productID])) $allProducts[$product->id] = $product->name; + if(!isset($allProducts[$productID])) $allProducts[$productID] = $product->name; foreach($branches[$productID] as $branchID => $branch) { $linkedBranches[$productID][$branchID] = $branchID; - $productPlans[$productID][$branchID] = $this->productplan->getPairs($productID, $branchID); + $productPlans[$productID][$branchID] = isset($plans[$productID][$branchID]) ? $plans[$productID][$branchID] : array(); - $projectStories = $this->dao->select('*')->from(TABLE_PROJECTSTORY)->where('project')->eq($projectID)->andWhere('product')->eq($productID)->andWhere('branch')->eq($branchID)->fetchAll('story'); - if(!empty($projectStories)) + if(!empty($projectStories[$productID][$branchID])) { array_push($unmodifiableProducts, $productID); array_push($unmodifiableBranches, $branchID); @@ -554,7 +562,7 @@ class project extends control $this->view->program = $this->program->getByID($project->parent); $this->view->projectID = $projectID; $this->view->allProducts = array('0' => '') + $allProducts; - $this->view->abnormalProducts = $this->loadModel('product')->getAbnormalProductPairs(); + $this->view->multiBranchProducts = $this->loadModel('product')->getMultiBranchPairs(); $this->view->productPlans = array_filter($productPlans); $this->view->linkedProducts = $linkedProducts; $this->view->linkedBranches = $linkedBranches; @@ -1697,6 +1705,7 @@ class project extends control $allProducts = $this->program->getProductPairs($project->parent, 'assign', 'noclosed'); $linkedProducts = $this->product->getProducts($projectID); $branches = $this->project->getBranchesByProject($projectID); + $projectStories = $this->project->getStoriesByProject($projectID); /* If the story of the product which linked the project, you don't allow to remove the product. */ $unmodifiableProducts = array(); @@ -1708,8 +1717,7 @@ class project extends control foreach($branches[$productID] as $branchID => $branch) { $linkedBranches[$productID][$branchID] = $branchID; - $projectStories = $this->dao->select('*')->from(TABLE_PROJECTSTORY)->where('project')->eq($projectID)->andWhere('product')->eq($productID)->andWhere('branch')->eq($branchID)->fetchAll('story'); - if(!empty($projectStories)) + if(!empty($projectStories[$productID][$branchID])) { array_push($unmodifiableProducts, $productID); array_push($unmodifiableBranches, $branchID); diff --git a/module/project/js/common.js b/module/project/js/common.js index 20ffd25075..0339022d6c 100644 --- a/module/project/js/common.js +++ b/module/project/js/common.js @@ -142,9 +142,9 @@ function loadBranches(product) $('#productsBox select').each(function() { var $product = $(product); - if($product.val() != 0 && $product.val() == $(this).val() && $product.attr('id') != $(this).attr('id') && !abnormalProducts[$product.val()]) + if($product.val() != 0 && $product.val() == $(this).val() && $product.attr('id') != $(this).attr('id') && !multiBranchProducts[$product.val()]) { - alert(errorSameProducts); + bootbox.alert(errorSameProducts); $product.val(0); $product.trigger("chosen:updated"); return false; diff --git a/module/project/js/create.js b/module/project/js/create.js index 3700cb99c5..1697f5a694 100644 --- a/module/project/js/create.js +++ b/module/project/js/create.js @@ -35,7 +35,7 @@ $(function() { var productID = $(this).val(); products[productID] = new Array(); - if(abnormalProducts[productID]) + if(multiBranchProducts[productID]) { $("#productsBox select[name^='branch']").each(function() { @@ -57,7 +57,7 @@ $(function() if(existedBranch) { - alert(errorSameBranches); + bootbox.alert(errorSameBranches); return false; } }) @@ -145,9 +145,9 @@ function loadBranches(product) $('#productsBox select').each(function() { var $product = $(product); - if($product.val() != 0 && $product.val() == $(this).val() && $product.attr('id') != $(this).attr('id') && !abnormalProducts[$product.val()]) + if($product.val() != 0 && $product.val() == $(this).val() && $product.attr('id') != $(this).attr('id') && !multiBranchProducts[$product.val()]) { - alert(errorSameProducts); + bootbox.alert(errorSameProducts); $product.val(0); $product.trigger("chosen:updated"); return false; diff --git a/module/project/js/edit.js b/module/project/js/edit.js index dcc915a68e..2c56afbf23 100644 --- a/module/project/js/edit.js +++ b/module/project/js/edit.js @@ -81,9 +81,12 @@ $(function() if(isExistedBranch != -1) { var $product = $(this).closest('.has-branch').find("[name^='products']"); - $(this).prop('disabled', true).trigger("chosen:updated"); - $product.prop('disabled', true).trigger("chosen:updated"); - $product.siblings('div').find('span').attr('title', tip); + if($.inArray($product.val(), unmodifiableProducts) != -1) + { + $(this).prop('disabled', true).trigger("chosen:updated"); + $product.prop('disabled', true).trigger("chosen:updated"); + $product.siblings('div').find('span').attr('title', tip); + } } }); @@ -95,12 +98,13 @@ $(function() { var products = []; var existedBranch = false; + /* Determine whether the products of the same branch are linked. */ $("#productsBox select[name^='products']").each(function() { var productID = $(this).val(); products[productID] = new Array(); - if(abnormalProducts[productID]) + if(multiBranchProducts[productID]) { $("#productsBox select[name^='branch']").each(function() { @@ -122,7 +126,7 @@ $(function() if(existedBranch) { - alert(errorSameBranches); + bootbox.alert(errorSameBranches); return false; } }) diff --git a/module/project/model.php b/module/project/model.php index 22a59b3d60..b8d8254a07 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -666,6 +666,21 @@ class projectModel extends model return $pairs; } + /** + * Get stories by project id. + * + * @param int $projectID + * @access public + * @return array + */ + public function getStoriesByProject($projectID = 0) + { + return $this->dao->select('*')->from(TABLE_PROJECTSTORY) + ->where(true) + ->beginIF($projectID)->andWhere('project')->eq($projectID)->fi() + ->fetchGroup('product', 'branch'); + } + /** * Get the tree menu of project. * @@ -1614,7 +1629,7 @@ class projectModel extends model { if(empty($productID)) continue; - $existedProducts[$productID] = array(); + if(!isset($existedProducts[$productID])) $existedProducts[$productID] = array(); $oldPlan = 0; $branch = isset($branches[$i]) ? $branches[$i] : 0; diff --git a/module/project/view/create.html.php b/module/project/view/create.html.php index 6219ae02cf..4f195e90f0 100644 --- a/module/project/view/create.html.php +++ b/module/project/view/create.html.php @@ -20,7 +20,7 @@ project->errorSameProducts);?> project->errorSameBranches);?> project->longTime);?> - + project->create->requiredFields;?>