From fc5403b90d591df73cf7e510cbcb97fdd13a5af2 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Tue, 15 Jul 2025 02:33:08 +0000 Subject: [PATCH 1/3] * [feedback#9756] Update stage by product when edit waterfall project. --- module/project/model.php | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/module/project/model.php b/module/project/model.php index dee8eb4f00..259ac5a085 100755 --- a/module/project/model.php +++ b/module/project/model.php @@ -1437,18 +1437,41 @@ class projectModel extends model * Update product stage by project. * * @param int $projectID - * @param string $stageBy * @param object $postProductData * @access public * @return bool */ - public function updateProductStage(int $projectID, string $stageBy, object $postProductData): bool + public function updateProductStage(int $projectID, object $postProductData): bool { - /* 如果项目的阶段为由按产品创建,则更新此项目下每个产品。*/ - if($stageBy == 'project') return true; + if(empty($postProductData)) return false; - $executions = $this->loadModel('execution')->getPairs($projectID); - foreach(array_keys($executions) as $executionID) $this->execution->updateProducts($executionID, $postProductData); // 更新项目下所有产品的阶段。 + $stageParis = $this->loadModel('execution')->getPairs($projectID); + $stageProducts = $this->dao->select('project, product')->from(TABLE_PROJECTPRODUCT) + ->where('project')->in(array_keys($stageParis)) + ->fetchPairs('project', 'product'); + + $products = zget($postProductData, 'products', array()); + $branches = zget($postProductData, 'branch', array(0)); + $plans = zget($postProductData, 'plans', array()); + + $productBranches = array(); + foreach($products as $i => $productID) $productBranches[$productID] = zget($branches, $i, array(0)); + + foreach($stageProducts as $stageID => $productID) + { + foreach($productBranches[$productID] as $branchID) + { + $data = new stdclass(); + $data->project = (int)$stageID; + $data->product = (int)$productID; + $data->branch = (int)$branchID; + $data->plan = isset($plans[$productID]) ? implode(',', $plans[$productID]) : ''; + $data->plan = trim($data->plan, ','); + $data->plan = empty($data->plan) ? 0 : ",$data->plan,"; + + $this->dao->replace(TABLE_PROJECTPRODUCT)->data($data)->exec(); + } + } return !dao::isError(); } @@ -1492,7 +1515,7 @@ class projectModel extends model $this->updatePlans($projectID, (array)$this->post->plans); // 更新关联的计划列表。 if($oldProject->hasProduct > 0) $this->updateProducts($projectID, (array)$this->post->products, $postProductData); // 更新关联的产品列表。 $this->updateTeamMembers($project, $oldProject, zget($_POST, 'teamMembers', array())); // 更新关联的用户信息。 - if(!empty((array)$postProductData) && in_array($oldProject->model, array('waterfall', 'waterfallplus'))) $this->updateProductStage($projectID, (string)$oldProject->stageBy, $postProductData); // 更新关联的所有产品的阶段。 + if($oldProject->stageBy == 'product' && in_array($oldProject->model, array('waterfall', 'waterfallplus'))) $this->updateProductStage($projectID, $postProductData); // 更新多套阶段 $this->file->updateObjectID((string)$this->post->uid, $projectID, 'project'); // 通过uid更新文件id。 From ec80b7931bdbc327a50177235cba955a9addb472 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Tue, 15 Jul 2025 05:33:23 +0000 Subject: [PATCH 2/3] * [unittest] Add the unit test file of projectModel::updateProductStage. --- .../test/lib/project.unittest.class.php | 31 ++++++++ .../project/test/model/updateproductstage.php | 78 +++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100755 module/project/test/model/updateproductstage.php diff --git a/module/project/test/lib/project.unittest.class.php b/module/project/test/lib/project.unittest.class.php index d0d6255ade..db38dc2e83 100644 --- a/module/project/test/lib/project.unittest.class.php +++ b/module/project/test/lib/project.unittest.class.php @@ -705,4 +705,35 @@ class Project return $this->project->getDisabledProducts($project, $linkedProducts); } + + /** + * 更新项目下的所有产品的阶段。 + * Update product stage by project. + * + * @param int $projectID + * @param object $postProductData + * @access public + * @return bool + */ + public function updateProductStageTest(int $projectID, object $postProductData): array + { + $this->project->updateProductStage($projectID, $postProductData); + $linkInfo = $this->project->dao->select('*')->from(TABLE_PROJECTPRODUCT)->fetchAll(); + + $result = array(); + foreach($linkInfo as $data) + { + if(!isset($result[$data->project])) $result[$data->project] = array(); + if(!isset($result[$data->project]['product'])) $result[$data->project]['product'] = array(); + if(!isset($result[$data->project]['branch'])) $result[$data->project]['branch'] = array(); + if(!isset($result[$data->project]['plan'])) $result[$data->project]['plan'] = array(); + $result[$data->project]['product'][$data->product] = $data->product; + $result[$data->project]['branch'][$data->branch] = $data->branch; + if(!empty(trim($data->plan, ','))) + { + foreach(explode(',', $data->plan) as $planID) $result[$data->project]['plan'][$planID] = $planID; + } + } + return $result; + } } diff --git a/module/project/test/model/updateproductstage.php b/module/project/test/model/updateproductstage.php new file mode 100755 index 0000000000..d23119327b --- /dev/null +++ b/module/project/test/model/updateproductstage.php @@ -0,0 +1,78 @@ +#!/usr/bin/env php +updateProductStage(); +timeout=0 +cid=1 + +- 检查阶段一关联产品一第product条的1属性 @1 +- 检查阶段一关联分支第branch条的0属性 @0 +- 检查阶段一关联计划第plan条的1属性 @1 +- 检查阶段二关联产品二第product条的2属性 @2 +- 检查阶段二关联分支 + - 第branch条的0属性 @0 + - 第branch条的1属性 @1 + - 第branch条的2属性 @2 +- 检查阶段二关联计划第plan条的2属性 @2 +- 检查阶段三关联产品三第product条的3属性 @3 +- 检查阶段三关联分支 + - 第branch条的0属性 @0 + - 第branch条的3属性 @3 + - 第branch条的4属性 @4 +- 检查阶段三关联计划第plan条的3属性 @3 +- 检查阶段四关联产品四第product条的4属性 @4 +- 检查阶段四关联分支 + - 第branch条的0属性 @0 + - 第branch条的5属性 @5 +- 检查阶段四关联计划第plan条的4属性 @4 + +*/ + +zenData('projectproduct')->gen(0); + +$project = zenData('project'); +$project->id->range('1-5'); +$project->project->range('0,1{4}'); +$project->model->range("waterfall,[]{4}"); +$project->type->range('project,stage{4}'); +$project->parent->range('0,1{4}'); +$project->path->range('`,1,`,`,1,2,`,`,1,3,`,`,1,4,`,`,1,5,`'); +$project->grade->range('1,2{4}'); +$project->name->range('瀑布项目,阶段一,阶段二,阶段三,阶段四,阶段五'); +$project->code->range('waterfall,stage1,stage2,stage3,stage4,stage5'); +$project->hasProduct->range(1); +$project->status->range('wait'); +$project->stageBy->range('product'); +$project->linkType->range('plan'); +$project->gen(5); + +$projectProduct = zenData('projectproduct'); +$projectProduct->project->range('2,3,4,5'); +$projectProduct->product->range('1,2,3,4'); +$projectProduct->branch->range('0'); +$projectProduct->plan->range(''); +$projectProduct->gen(4); + +$postData = new stdClass(); +$postData->products = array(1, 2, 3, 4); +$postData->branch = array(array(0), array(1, 2), array(3, 4), array(5)); +$postData->plans = array(1 => array(1), 2 => array(2), 3 => array(3), 4 => array(4)); + +$projectTester = new Project(); +r($projectTester->updateProductStageTest(1, $postData)[2]) && p('product:1') && e('1'); //检查阶段一关联产品一 +r($projectTester->updateProductStageTest(1, $postData)[2]) && p('branch:0') && e('0'); //检查阶段一关联分支 +r($projectTester->updateProductStageTest(1, $postData)[2]) && p('plan:1') && e('1'); //检查阶段一关联计划 +r($projectTester->updateProductStageTest(1, $postData)[3]) && p('product:2') && e('2'); //检查阶段二关联产品二 +r($projectTester->updateProductStageTest(1, $postData)[3]) && p('branch:0,1,2') && e('0,1,2'); //检查阶段二关联分支 +r($projectTester->updateProductStageTest(1, $postData)[3]) && p('plan:2') && e('2'); //检查阶段二关联计划 +r($projectTester->updateProductStageTest(1, $postData)[4]) && p('product:3') && e('3'); //检查阶段三关联产品三 +r($projectTester->updateProductStageTest(1, $postData)[4]) && p('branch:0,3,4') && e('0,3,4'); //检查阶段三关联分支 +r($projectTester->updateProductStageTest(1, $postData)[4]) && p('plan:3') && e('3'); //检查阶段三关联计划 +r($projectTester->updateProductStageTest(1, $postData)[5]) && p('product:4') && e('4'); //检查阶段四关联产品四 +r($projectTester->updateProductStageTest(1, $postData)[5]) && p('branch:0,5') && e('0,5'); //检查阶段四关联分支 +r($projectTester->updateProductStageTest(1, $postData)[5]) && p('plan:4') && e('4'); //检查阶段四关联计划 From 296d2cbb4d76365d4271de8105238d79d5a04940 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Tue, 15 Jul 2025 05:47:16 +0000 Subject: [PATCH 3/3] * [feedback#9756] Add the default value to function of updateProductStage. --- module/project/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/project/model.php b/module/project/model.php index 259ac5a085..ab66ee6335 100755 --- a/module/project/model.php +++ b/module/project/model.php @@ -1441,7 +1441,7 @@ class projectModel extends model * @access public * @return bool */ - public function updateProductStage(int $projectID, object $postProductData): bool + public function updateProductStage(int $projectID, ?object $postProductData = null): bool { if(empty($postProductData)) return false;