znt/module/pivot/tao.php

524 lines
19 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
class pivotTao extends pivotModel
{
/**
* 获取透视表。
* Fetch pivot by id.
*
* @param int $id
* @param string|null $version
* @access public
* @return object|bool
*/
protected function fetchPivot(int $id, ?string $version = null): object|bool
{
$pivot = $this->dao->select('*')->from(TABLE_PIVOT)->where('id')->eq($id)->andWhere('deleted')->eq('0')->fetch();
if(!$pivot) return false;
if(is_null($version)) return $this->mergePivotSpecData($pivot);
$specData = $this->dao->select('*')->from(TABLE_PIVOTSPEC)->where('pivot')->eq($id)->andWhere('version')->eq($version)->fetch();
if(!$specData) return $pivot;
unset($specData->id);
foreach($specData as $specKey => $specValue) $pivot->$specKey = $specValue;
return $pivot;
}
/**
* 合并 pivotSpec 的数据。
* Merge pivotSpec data to pivot.
*
* @param int $id
* @param bool $isObject
* @access public
* @return object|bool
*/
protected function mergePivotSpecData($pivots, $isObject = true)
{
if($isObject) $pivots = array($pivots);
$pivotIDList = array_column($pivots, 'id');
$pivotSpecs = $this->dao->select('t2.pivot,t2.version,t2.driver,t2.mode,t2.name,t2.desc,t2.sql,t2.fields,t2.langs,t2.vars,t2.objects,t2.settings,t2.filters,t2.createdDate')->from(TABLE_PIVOT)->alias('t1')
->leftJoin(TABLE_PIVOTSPEC)->alias('t2')->on('t1.id = t2.pivot and t1.version = t2.version')
->where('t1.id')->in($pivotIDList)
->fetchAll('pivot', false);
foreach($pivots as $index => $pivot)
{
if(!isset($pivotSpecs[$pivot->id])) continue;
foreach($pivotSpecs[$pivot->id] as $specKey => $specValue) $pivot->$specKey = $specValue;
$pivots[$index] = $pivot;
}
return $isObject ? current($pivots) : $pivots;
}
/**
* 获取产品列表。
* Get product list.
*
* @param string $conditions
* @param array|string $IDList
* @param array $filters
* @access public
* @return array
*/
protected function getProductList(string $conditions, array|string $idList = array(), array $filters = array()): array
{
$productID = isset($filters['productID']) ? $filters['productID'] : 0;
$productStatus = isset($filters['productStatus']) ? $filters['productStatus'] : '';
$productType = isset($filters['productType']) ? $filters['productType'] : '';
return $this->dao->select('t1.id, t1.code, t1.name, t1.PO')->from(TABLE_PRODUCT)->alias('t1')
->leftJoin(TABLE_PROGRAM)->alias('t2')->on('t1.program = t2.id')
->where('t1.deleted')->eq('0')
->andWhere('t1.shadow')->eq('0')
->beginIF(!empty($idList))->andWhere('t1.id')->in($idList)->fi()
->beginIF($productID)->andWhere('t1.id')->eq($productID)->fi()
->beginIF($productStatus)->andWhere('t1.status')->eq($productStatus)->fi()
->beginIF($productType)->andWhere('t1.type')->eq($productType)->fi()
->filterTpl('skip')
->orderBy('t2.order_asc, t1.line_desc, t1.order_asc')
->fetchAll('id');
}
/**
* 补充产品的计划信息。
* Supplement product plan information.
*
* @param array $products
* @access public
* @return array
*/
protected function processProductPlan(array &$products, string $conditions): array
{
/* 获取产品的计划信息并且根据产品id进行分组。 */
/* Get the plan information of the product and group it by product id. */
$plans = $this->dao->select('id, product, branch, parent, title, begin, end')->from(TABLE_PRODUCTPLAN)
->where('deleted')->eq('0')
->andWhere('product')->in(array_keys($products))
->beginIF(strpos($conditions, 'overduePlan') === false)->andWhere('end')->gt(date('Y-m-d'))->fi()
->orderBy('product, parent_desc, begin')
->fetchAll('id');
foreach($plans as $plan)
{
if($plan->parent > 0)
{
$parentPlan = zget($plans, $plan->parent, null);
if($parentPlan)
{
$products[$plan->product]->plans[$parentPlan->id] = $parentPlan;
unset($plans[$parentPlan->id]);
}
$plan->title = '>>' . $plan->title;
}
$products[$plan->product]->plans[$plan->id] = $plan;
}
return $plans;
}
/**
* 获取产品的需求信息。
* Get product demand information.
*
* @param string $storyType
* @param array $plans
* @access public
* @return array
*/
protected function processPlanStories(array &$products, string $storyType, array $plans): array
{
/* 获取所有符合条件的需求。 */
/* Get all the requirements that meet the conditions. */
$plannedStories = array();
$unplannedStories = array();
$stmt = $this->dao->select('id, plan, product, status')->from(TABLE_STORY)
->where('deleted')->eq('0')
->andWhere('parent')->ge(0)
->beginIF($storyType)->andWhere('type')->eq($storyType)->fi()
->query();
/* 根据需求的计划信息,将需求分组到不同的计划中。 */
/* According to the plan information of the demand, the demand is grouped into different plans. */
while($story = $stmt->fetch())
{
if(empty($story->plan))
{
$unplannedStories[$story->id] = $story;
continue;
}
$storyPlans = array();
$storyPlans[] = $story->plan;
if(strpos($story->plan, ',') !== false) $storyPlans = explode(',', trim($story->plan, ','));
foreach($storyPlans as $planID)
{
if(isset($plans[$planID]))
{
$plannedStories[$story->id] = $story;
break;
}
}
}
/* 将需求统计信息添加到产品中。 */
/* Add demand statistics information to the product. */
$this->getPlanStatusStatistics($products, $plans, $plannedStories, $unplannedStories);
return $products;
}
/**
* 获取产品计划的需求统计信息。
* Get product demand statistics information.
*
* @param array $products
* @param array $plans
* @param array $plannedStories
* @param array $unplannedStories
* @access protected
* @return void
*/
protected function getPlanStatusStatistics(array &$products, array $plans, array $plannedStories, array $unplannedStories): void
{
/* 统计已经计划过的产品计划的需求状态信息。 */
/* Statistics of demand status information for planned product plans. */
foreach($plannedStories as $story)
{
$storyPlans = strpos($story->plan, ',') !== false ? $storyPlans = explode(',', trim($story->plan, ',')) : array($story->plan);
foreach($storyPlans as $planID)
{
if(!isset($plans[$planID])) continue;
$plan = $plans[$planID];
$products[$plan->product]->plans[$planID]->status[$story->status] = isset($products[$plan->product]->plans[$planID]->status[$story->status]) ? $products[$plan->product]->plans[$planID]->status[$story->status] + 1 : 1;
}
}
/* 统计还未计划的产品计划的需求状态信息。 */
/* Statistics of demand status information for unplanned product plans. */
foreach($unplannedStories as $story)
{
$product = $story->product;
if(isset($products[$product]))
{
if(!isset($products[$product]->plans[0]))
{
$products[$product]->plans[0] = new stdClass();
$products[$product]->plans[0]->title = $this->lang->pivot->unplanned;
$products[$product]->plans[0]->begin = '';
$products[$product]->plans[0]->end = '';
}
$products[$product]->plans[0]->status[$story->status] = isset($products[$product]->plans[0]->status[$story->status]) ? $products[$product]->plans[0]->status[$story->status] + 1 : 1;
}
}
}
/**
* 获取执行列表。
* Get execution list.
*
* @param string $begin
* @param string $end
* @param array $executionIDList
* @access public
* @return array
*/
protected function getExecutionList(string $begin, string $end, $executionIDList = array()): array
{
return $this->dao->select("t1.project AS projectID, t1.execution AS executionID, t2.multiple, t2.end, IF(t3.multiple = '1', t2.name, '') AS executionName, t3.name AS projectName, ROUND(SUM(t1.estimate), 2) AS estimate, ROUND(SUM(t1.consumed), 2) AS consumed")->from(TABLE_TASK)->alias('t1')
->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.execution = t2.id')
->leftJoin(TABLE_PROJECT)->alias('t3')->on('t1.project = t3.id')
->where('t1.status')->ne('cancel')
->andWhere('t1.deleted')->eq('0')
->andWhere('t1.parent')->lt(1)
->andWhere('t2.deleted')->eq('0')
->andWhere('t2.status')->eq('closed')
->beginIF($begin)->andWhere('t2.realBegan')->ge($begin)->fi()
->beginIF($end)->andWhere('t2.realEnd')->le($end)->fi()
->beginIF(!empty($executionIDList))->andWhere('t2.id')->in($executionIDList)->fi()
->groupBy('t1.project, t1.execution, t2.multiple, t2.end, t2.name, t3.multiple, t3.name')
->orderBy('t2.end_desc')
->fetchAll();
}
/**
* 获取bug分组信息。
* Get bug group information.
*
* @param string $begin
* @param string $end
* @param int $product
* @param int $execution
* @access public
* @return array
*/
protected function getBugGroup(string $begin, string $end, int $product, int $execution): array
{
return $this->dao->select("IF(resolution = '', 'unResolved', resolution) AS resolution, openedBy, status")->from(TABLE_BUG)
->where('deleted')->eq('0')
->andWhere('openedDate')->ge($begin)
->andWhere('openedDate')->le($end)
->beginIF($product)->andWhere('product')->eq($product)->fi()
->beginIF($execution)->andWhere('execution')->eq($execution)->fi()
->fetchGroup('openedBy');
}
/**
* 获取未指派的执行。
* Get unassigned executions.
*
* @param array $deptUsers
* @access public
* @return array
*/
protected function getNoAssignExecution(array $deptUsers): array
{
$assignedToList = $this->dao->select("DISTINCT IF(tt1.mode = '', tt1.assignedTo, tt2.account) AS assignedTo")->from(TABLE_TASK)->alias('tt1')
->leftJoin(TABLE_TASKTEAM)->alias('tt2')->on("tt1.id=tt2.task AND tt1.mode IN ('multi', 'linear')")
->where('tt1.status')->notIn('cancel,closed,done,pause')
->andWhere("IF(tt1.mode = '', tt1.assignedTo, tt2.account)")->ne('')
->andWhere('tt1.execution = t1.`root`')
->get();
return $this->dao->select('t1.account AS user, t2.multiple, t2.id AS executionID, t2.name AS executionName, t3.id AS projectID, t3.name AS projectName')->from(TABLE_TEAM)->alias('t1')
->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t2.id = t1.root')
->leftJoin(TABLE_PROJECT)->alias('t3')->on('t3.id = t2.project')
->where('t1.type')->eq('execution')
->andWhere("t1.account NOT IN ($assignedToList)")
->andWhere('t2.deleted')->eq('0')
->andWhere('t2.status')->notin('cancel, closed, done, suspended')
->beginIF($deptUsers)->andWhere('t1.account')->in($deptUsers)->fi()
->fetchAll();
}
/**
* 获取已指派的执行。
* Get assigned executions.
*
* @param array $deptUsers
* @access public
* @return array
*/
protected function getAssignTask(array $deptUsers): array
{
return $this->dao->select(<<<EOT
t1.id,
t1.isParent,
CASE WHEN t1.mode = '' THEN t1.assignedTo ELSE t4.account END AS user,
CASE WHEN t1.mode = '' THEN ROUND(t1.`left`, 2) ELSE ROUND(t4.`left`, 2) END AS `left`,
t2.multiple,
t2.id AS executionID,
t2.name AS executionName,
t3.id AS projectID,
t3.name AS projectName
EOT)->from(TABLE_TASK)->alias('t1')
->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.execution = t2.id')
->leftJoin(TABLE_PROJECT)->alias('t3')->on('t3.id = t2.project')
->leftJoin(TABLE_TASKTEAM)->alias('t4')->on("t1.id=t4.task and t1.mode IN ('multi', 'linear')")
->where('t1.deleted')->eq('0')
->andWhere('t1.parent')->ge(0)
->andWhere('t1.status')->in('wait,pause,doing')
->andWhere("if(t1.mode = '', t1.assignedTo, t4.account)")->ne('')
->beginIF($deptUsers)->andWhere("if(t1.mode = '', t1.assignedTo, t4.account)")->in($deptUsers)->fi()
->andWhere('t2.deleted')->eq('0')
->andWhere('t2.vision')->like('rnd')
->andWhere('t2.status')->in('wait,suspended,doing')
->fetchAll();
}
/**
* 获取任务相关的团队信息。
* Get team information related to tasks.
*
* @param array $taskIDList
* @access public
* @return array
*/
protected function getTeamTasks(array $taskIDList): array
{
return $this->dao->select('task, SUM(`left`) AS `left`')->from(TABLE_TASKTEAM)
->where('task')->in($taskIDList)
->groupBy('task')
->fetchPairs('task');
}
/**
* 获取指派的bug。
* Get assigned bugs.
*
* @access public
* @return array
*/
protected function getAssignBugGroup(): array
{
return $this->dao->select('product, assignedTo, COUNT(1) AS bugCount')->from(TABLE_BUG)
->where('deleted')->eq('0')
->andWhere('status')->eq('active')
->andWhere('assignedTo')->ne('')
->andWhere('assignedTo')->ne('closed')
->groupBy('product, assignedTo')
->fetchGroup('assignedTo');
}
/**
* 获取产品项目关联关系。
* Get product project association.
*
* @access public
* @return array
*/
protected function getProductProjects(): array
{
return $this->dao->select('t2.product, t2.project')->from(TABLE_PROJECT)->alias('t1')
->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.id = t2.project')
->where('t1.type')->eq('project')
->andWhere('t1.hasProduct')->eq(0)
->fetchPairs();
}
/**
* 获取所有产品的id和name。
* Get the id and name of all products.
*
* @access public
* @return array
*/
protected function getAllProductsIDAndName(): array
{
return $this->dao->select('id, name')->from(TABLE_PRODUCT)
->where('deleted')->eq('0')
->fetchPairs();
}
/**
* 获取产品和执行名称。
* Get product and execution name.
*
* @access public
* @return array
*/
protected function getProjectAndExecutionNameQuery(): array
{
return $this->dao->select('t1.id, t1.name, t2.name as projectname, t1.status, t1.multiple')
->from(TABLE_EXECUTION)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id')
->where('t1.deleted')->eq(0)
->andWhere('t1.type')->in('stage,sprint')
->fetchAll();
}
/**
* 获取一个维度的第一个分组。
* Get the first group of a dimension.
*
* @param int $dimensionID
* @access protected
* @return int
*/
protected function getFirstGroup(int $dimensionID): int
{
return (int)$this->dao->select('id')->from(TABLE_MODULE)
->where('deleted')->eq('0')
->andWhere('type')->eq('pivot')
->andWhere('root')->eq($dimensionID)
->andWhere('grade')->eq(1)
->orderBy('`order`')
->limit(1)
->fetch('id');
}
/**
* 通过维度和路径获取分组。
* Get group by dimension and path.
*
* @param int $dimensionID
* @param string $path
* @access protected
* @return array
*/
protected function getGroupsByDimensionAndPath(int $dimensionID, string $path): array
{
return $this->dao->select('id, grade, name, collector')->from(TABLE_MODULE)
->where('deleted')->eq('0')
->andWhere('root')->eq($dimensionID)
->andWhere('path')->like("{$path}%")
->orderBy('`order`')
->fetchAll();
}
/**
* 根据分组获取对应的透视表id。
* Get the corresponding pivot table id according to the group.
*
* @param int $groupID
* @access protected
* @return int
*/
protected function getPivotID(int $groupID): int
{
$viewableObjects = $this->bi->getViewableObject('pivot');
return (int)$this->dao->select('id')->from(TABLE_PIVOT)
->where("FIND_IN_SET({$groupID}, `group`)")
->andWhere('stage')->ne('draft')
->andWhere('deleted')->eq('0')
->andWhere('id')->in($viewableObjects)
->orderBy('id_desc')
->limit(1)
->fetch('id');
}
/**
* 根据一个分组下的所有透视表。
* Get all pivot tables under a group.
*
* @param int $groupID
* @access protected
* @return array
*/
protected function getAllPivotByGroupID(int $groupID): array
{
$pivots = $this->dao->select('*')->from(TABLE_PIVOT)
->where("FIND_IN_SET({$groupID}, `group`)")
->andWhere('stage')->ne('draft')
->andWhere('deleted')->eq('0')
->orderBy('id_desc')
->fetchAll('', false);
return $this->mergePivotSpecData($pivots, false);
}
/**
* 获取透视表汇总列的下钻配置。
* Get drill config of pivot summary column field.
*
* @param int $pivotID
* @param string $field
* @param string $status
* @access public
* @return object|bool
*/
public function fetchPivotDrills(int $pivotID, string $version, string|array $fields): array
{
if(is_string($fields)) $fields = array($fields);
$records = $this->dao->select('*')->from(TABLE_PIVOTDRILL)
->where('pivot')->eq($pivotID)
->andWhere('version')->eq($version)
->andWhere('field')->in($fields)
->fetchAll('field', false);
foreach($records as $field => $record)
{
$record->condition = json_decode($record->condition, true);
$records[$field] = $record;
}
return $records;
}
}