znt/module/stakeholder/model.php

610 lines
23 KiB
PHP

<?php
declare(strict_types=1);
class stakeholderModel extends model
{
/**
* 创建一个干系人。
* Create a stakeholder.
*
* @param object $data
* @access public
* @return int|bool
*/
public function create(object $data): int|bool
{
$account = $this->replaceUserInfo($data);
if(dao::isError()) return false;
$stakeholder = new stdclass();
$stakeholder->user = $account;
$stakeholder->objectType = $data->objectType;
$stakeholder->objectID = $data->objectID;
$stakeholder->key = $data->key;
$stakeholder->from = $data->from;
$stakeholder->type = $data->from == 'outside' ? 'outside' : 'inside';
$stakeholder->createdBy = $this->app->user->account;
$stakeholder->createdDate = helper::now();
$this->dao->insert(TABLE_STAKEHOLDER)->data($stakeholder)->check('user', 'unique', "objectID = {$stakeholder->objectID} AND deleted = '0'")->autoCheck()->exec();
$stakeholderID = $this->dao->lastInsertID();
if(dao::isError()) return false;
$userList = empty($stakeholder->user) ? array() : array($stakeholder->user);
$this->loadModel('user')->updateUserView(array($stakeholder->objectID), $stakeholder->objectType, $userList);
/* Update linked products view. */
if($stakeholder->objectType == 'project' && $stakeholder->objectID)
{
$this->loadModel('project')->updateInvolvedUserView($stakeholder->objectID, $userList);
}
if($stakeholder->objectType == 'program' && $stakeholder->objectID)
{
$programID = $stakeholder->objectID;
/* Update children user view. */
$childPrograms = $this->dao->select('id')->from(TABLE_PROJECT)->where('path')->like("%,$programID,%")->andWhere('type')->eq('program')->fetchPairs();
$childProjects = $this->dao->select('id')->from(TABLE_PROJECT)->where('path')->like("%,$programID,%")->andWhere('type')->eq('project')->fetchPairs();
$childProducts = $this->dao->select('id')->from(TABLE_PRODUCT)->where('program')->eq($programID)->fetchPairs();
if(!empty($childPrograms)) $this->user->updateUserView($childPrograms, 'program', array($stakeholder->user));
if(!empty($childProjects)) $this->user->updateUserView($childProjects, 'project', array($stakeholder->user));
if(!empty($childProducts)) $this->user->updateUserView($childProducts, 'product', array($stakeholder->user));
}
return $stakeholderID;
}
/**
* 更新/插入用户信息。
* Update/insert user info.
*
* @param object $data
* @access public
* @return bool|string
*/
public function replaceUserInfo(object $data): bool|string
{
$account = isset($data->user) ? $data->user : '';
if($data->from != 'outside')
{
if(!$account) return dao::$errors['user'] = sprintf($this->lang->error->notempty, $this->lang->stakeholder->user);
$user = new stdclass();
$user->nature = $data->nature;
$user->analysis = $data->analysis;
$user->strategy = $data->strategy;
$this->dao->update(TABLE_USER)->data($user)->where('account')->eq($account)->exec();
return $account;
}
if($account) return $account;
/* If it's an outsider and it's added for the first time, insert to user table. */
if(!$data->newUser && !$account) return dao::$errors['user'] = sprintf($this->lang->error->notempty, $this->lang->stakeholder->user);
if(!$data->name) return dao::$errors['name'] = sprintf($this->lang->error->notempty, $this->lang->stakeholder->name);
if(!$data->newCompany && !$data->company) return dao::$errors['company'] = sprintf($this->lang->error->notempty, $this->lang->stakeholder->company);
if($data->newCompany && !$data->companyName) return dao::$errors['company'] = sprintf($this->lang->error->notempty, $this->lang->stakeholder->company);
$companyID = $data->company;
if(isset($data->newCompany) && $data->companyName)
{
$company = new stdclass();
$company->name = $data->companyName;
$this->dao->insert(TABLE_COMPANY)->data($company)->autoCheck()->exec();
$companyID = $this->dao->lastInsertID();
}
/* Create new user. */
$user = new stdclass();
$user->type = 'outside';
$user->realname = $data->name;
$user->account = mt_rand(1111, 99999);
$user->company = $companyID;
$user->phone = $data->phone;
$user->qq = $data->qq;
$user->weixin = $data->weixin;
$user->email = $data->email;
$user->nature = $data->nature;
$user->analysis = $data->analysis;
$user->strategy = $data->strategy;
$this->dao->insert(TABLE_USER)->data($user)->exec();
$userID = $this->dao->lastInsertID();
$account = 'u' . $userID;
$this->dao->update(TABLE_USER)->set('account')->eq($account)->where('id')->eq($userID)->exec();
if(dao::isError()) return false;
return $account;
}
/**
* 批量创建项目的干系人。
* Batch create stakeholders for a project.
*
* @param int $projectID
* @param array $accounts
* @access public
* @return array
*/
public function batchCreate(int $projectID, array $accounts): array
{
$this->loadModel('action');
$members = $this->loadModel('user')->getTeamMemberPairs($projectID, 'project');
$accounts = array_unique($accounts);
$oldJoin = $this->dao->select('`user`, createdDate')->from(TABLE_STAKEHOLDER)->where('objectID')->eq($projectID)->andWhere('objectType')->eq('project')->fetchPairs();
$this->dao->delete()->from(TABLE_STAKEHOLDER)->where('objectID')->eq($projectID)->andWhere('objectType')->eq('project')->exec();
$stakeholderList = array();
foreach($accounts as $account)
{
if(empty($account)) continue;
$stakeholder = new stdclass();
$stakeholder->objectID = $projectID;
$stakeholder->objectType = 'project';
$stakeholder->user = $account;
$stakeholder->type = in_array($account, array_keys($members)) ? 'inside' : 'outside';
$stakeholder->from = $stakeholder->type == 'inside' ? 'team' : 'company';
$stakeholder->createdBy = $this->app->user->account;
$stakeholder->createdDate = isset($oldJoin[$account]) ? $oldJoin[$account] : helper::now();
$this->dao->insert(TABLE_STAKEHOLDER)->data($stakeholder)->exec();
$stakeholderID = $this->dao->lastInsertId();
$stakeholderList[] = $stakeholderID;
$this->action->create('stakeholder', $stakeholderID, 'added');
if(!empty($accounts) && $stakeholder->objectType == 'program' && $stakeholder->objectID)
{
/* Update children user view. */
$programID = $stakeholder->objectID;
$childPrograms = $this->dao->select('id')->from(TABLE_PROJECT)->where('path')->like("%,$programID,%")->andWhere('type')->eq('program')->fetchPairs();
$childProjects = $this->dao->select('id')->from(TABLE_PROJECT)->where('path')->like("%,$programID,%")->andWhere('type')->eq('project')->fetchPairs();
$childProducts = $this->dao->select('id')->from(TABLE_PRODUCT)->where('program')->eq($programID)->fetchPairs();
if(!empty($childPrograms)) $this->user->updateUserView($childPrograms, 'program', $stakeholder->user);
if(!empty($childProjects)) $this->user->updateUserView($childProjects, 'project', $stakeholder->user);
if(!empty($childProducts)) $this->user->updateUserView($childProducts, 'product', $stakeholder->user);
}
}
/* Only changed account update userview. */
$oldAccounts = array_keys($oldJoin);
$changedAccounts = array_diff($accounts, $oldAccounts);
$changedAccounts = array_merge($changedAccounts, array_diff($oldAccounts, $accounts));
$changedAccounts = array_unique($changedAccounts);
$this->loadModel('user')->updateUserView(array($projectID), 'project', $changedAccounts);
$this->loadModel('project')->updateInvolvedUserView($projectID, $changedAccounts);
return $stakeholderList;
}
/**
* 编辑一个干系人。
* Edit a stakeholder.
*
* @param int $stakeholderID
* @param object $data
* @access public
* @return bool|array
*/
public function edit(int $stakeholderID, object $data): bool|array
{
$oldStakeholder = $this->getByID($stakeholderID);
if(!$oldStakeholder) return false;
$user = new stdclass();
if($oldStakeholder->from == 'outside')
{
if(empty($data->name))
{
dao::$errors['name'] = sprintf($this->lang->error->notempty, $this->lang->stakeholder->name);
return false;
}
$user->realname = $data->name;
$user->phone = $data->phone;
$user->qq = $data->qq;
$user->weixin = $data->weixin;
$user->email = $data->email;
}
$user->nature = $data->nature;
$user->analysis = $data->analysis;
$user->strategy = $data->strategy;
$this->dao->update(TABLE_USER)->data($user)->where('account')->eq($oldStakeholder->user)->exec();
if(dao::isError()) return false;
$stakeholder = new stdclass();
$stakeholder->key = $data->key;
$stakeholder->editedBy = $this->app->user->account;
$stakeholder->editedDate = helper::now();
$this->dao->update(TABLE_STAKEHOLDER)->data($stakeholder)
->autoCheck()
->where('id')->eq($stakeholderID)
->exec();
if(dao::isError()) return false;
return common::createChanges($oldStakeholder, $stakeholder);
}
/**
* 获取干系人列表数据。
* Get stakeholder list.
*
* @param int $projectID
* @param string $browseType all|inside|outside|key
* @param string $orderBy
* @param object $pager
* @access public
* @return array
*/
public function getStakeholders(int $projectID, string $browseType = 'all', string $orderBy = 'id_desc', ?object $pager = null): array
{
return $this->dao->select('t1.*, t2.role, t2.phone, t2.realname as name, t2.email, t2.qq, t2.weixin, t2.nature, t2.analysis, t2.strategy, t3.name as companyName, t4.model as projectModel')->from(TABLE_STAKEHOLDER)->alias('t1')
->leftJoin(TABLE_USER)->alias('t2')->on('t1.user=t2.account')
->leftJoin(TABLE_COMPANY)->alias('t3')->on('t2.company=t3.id')
->leftJoin(TABLE_PROJECT)->alias('t4')->on('t1.objectID=t4.id')
->where('t1.deleted')->eq('0')
->andWhere('t1.objectID')->eq($projectID)
->beginIF($browseType == 'inside')->andWhere('t1.type')->eq('inside')->fi()
->beginIF($browseType == 'outside')->andWhere('t1.type')->eq('outside')->fi()
->beginIF($browseType == 'key')->andWhere('t1.key')->ne('0')->fi()
->orderBy($orderBy)
->page($pager)
->fetchAll('id');
}
/**
* 获取干系人account => realname键值对。
* Get the stakeholder account => realname key-value pair.
*
* @param int $objectID
* @access public
* @return array
*/
public function getStakeHolderPairs(int $objectID): array
{
return $this->dao->select('t1.user, t2.realname')->from(TABLE_STAKEHOLDER)->alias('t1')
->leftJoin(TABLE_USER)->alias('t2')->on('t1.user=t2.account')
->where('t1.deleted')->eq('0')
->andWhere('t1.objectID')->eq($objectID)
->orderBy('t1.id_desc')
->fetchPairs();
}
/**
* 获取按照对象ID分组的干系人列表。
* Get stakeholder group by object id.
*
* @param array $objectIdList
* @access public
* @return array
*/
public function getStakeholderGroup(array $objectIdList): array
{
$stakeholders = $this->dao->select('objectID, user')->from(TABLE_STAKEHOLDER)->where('objectID')->in($objectIdList)->andWhere('deleted')->eq('0')->fetchAll();
$stakeholderGroup = array();
foreach($stakeholders as $stakeholder)
{
$stakeholderGroup[$stakeholder->objectID][$stakeholder->user] = $stakeholder->user;
}
return $stakeholderGroup;
}
/**
* 获取父项目集/父项目的干系人列表。
* Get the stakeholder list for the parent program / parent project.
*
* @param array $objectIdList
* @access public
* @return array
*/
public function getParentStakeholderGroup(array $objectIdList): array
{
$parents = array();
$objects = $this->loadModel('project')->getListByAcl('private,program', $objectIdList);
foreach($objects as $object)
{
if($object->parent == 0) continue;
foreach(explode(',', $object->path) as $objectID)
{
if(empty($objectID)) continue;
if($objectID == $object->id) continue;
$parents[$objectID][] = $object->id;
}
}
if(empty($parents)) return array();
/* Get all parent stakeholders. */
$parentStakeholders = $this->dao->select('objectID, user')->from(TABLE_STAKEHOLDER)->where('objectID')->in(array_keys($parents))->andWhere('deleted')->eq('0')->fetchAll();
$parentStakeholderGroup = array();
foreach($parentStakeholders as $parentStakeholder)
{
$subPrograms = zget($parents, $parentStakeholder->objectID, array());
foreach($subPrograms as $subProgramID) $parentStakeholderGroup[$subProgramID][$parentStakeholder->user] = $parentStakeholder->user;
}
return $parentStakeholderGroup;
}
/**
* 获取项目按照人员类型分组的干系人列表。
* Get stakeholder group by type.
*
* @access public
* @return array
*/
public function getListByType(): array
{
return $this->dao->select('t2.realname as name, t2.account, t1.type, t2.role')->from(TABLE_STAKEHOLDER)->alias('t1')
->leftJoin(TABLE_USER)->alias('t2')->on('t1.user=t2.account')
->where('t1.deleted')->eq('0')
->andWhere('t1.objectID')->eq($this->session->project)
->fetchGroup('type');
}
/**
* 获取干系人信息。
* Get stakeholder by id.
*
* @param int $stakeholderID
* @access public
* @return object|bool
*/
public function getByID(int $stakeholderID): object|bool
{
return $this->dao->select('t1.*, t2.phone, t2.realname as name, t2.email, t2.qq, t2.weixin, t2.nature, t2.analysis, t2.strategy, t3.name as companyName, t3.id as company')->from(TABLE_STAKEHOLDER)->alias('t1')
->leftJoin(TABLE_USER)->alias('t2')->on('t1.user=t2.account')
->leftJoin(TABLE_COMPANY)->alias('t3')->on('t2.company=t3.id')
->where('t1.id')->eq($stakeholderID)
->fetch();
}
/**
* 获取项目按照进度分组的活动列表。
* Get group activities.
*
* @access public
* @return array
*/
public function getProcessGroup(): array
{
return $this->dao->select('process, activity')->from(TABLE_PROGRAMACTIVITY)
->where('project')->eq($this->session->project)
->andWhere('result')->eq('yes')
->fetchGroup('process');
}
/**
* 获取进度id=>name的键值对。
* Get the key-value pair of progress id=>name.
*
* @access public
* @return array
*/
public function getProcess(): array
{
return $this->dao->select('id, name')->from(TABLE_PROCESS)
->where('deleted')->eq(0)
->fetchPairs();
}
/**
* 获取项目的干预列表信息。
* Get intervention list.
*
* @access public
* @return array
*/
public function getPlans(): array
{
return $this->dao->select('*')->from(TABLE_INTERVENTION)
->where('deleted')->eq(0)
->andWhere('project')->eq($this->session->project)
->fetchAll('activity');
}
/**
* 获取项目下干系人提出的问题列表。
* Get a list of issues owner by stakeholders under the project.
*
* @access public
* @return array
*/
public function getIssues(): array
{
$stakeholders = $this->getStakeHolderPairs($this->session->project);
return $this->dao->select('*')->from(TABLE_ISSUE)
->where('deleted')->eq(0)
->andWhere('project')->eq($this->session->project)
->andWhere('owner')->in(array_keys($stakeholders))
->orWhere('activity')->ne('')
->orderBy('id_desc')
->fetchAll('id');
}
/**
* 获取活动 id=>name 的键值对。
* Get the key-value pair for the activity id=>name.
*
* @access public
* @return array
*/
public function getActivities(): array
{
return $this->dao->select('id, name')->from(TABLE_ACTIVITY)
->where('deleted')->eq(0)
->fetchPairs();
}
/**
* 添加一条期望记录。
* Add a expect record.
*
* @param object $data
* @access public
* @return int|bool
*/
public function expect(object $data): int|bool
{
$this->dao->insert(TABLE_EXPECT)->data($data)
->autoCheck()
->batchCheck($this->config->stakeholder->expect->requiredFields, 'notempty')
->exec();
if(dao::isError()) return false;
return $this->dao->lastInsertID();
}
/**
* 获取期望列表数据。
* Get expect list.
*
* @param string $browseType all|bysearch
* @param int $queryID
* @param string $orderBy
* @param object $pager
* @access public
* @return array
*/
public function getExpectList(string $browseType = 'all', int $queryID = 0, string $orderBy = 'id_desc', ?object $pager = null): array
{
$stakeholderQuery = '';
if($browseType == 'bysearch')
{
$query = $queryID ? $this->loadModel('search')->getQuery($queryID) : '';
if($query)
{
$this->session->set('stakeholderQuery', $query->sql);
$this->session->set('stakeholderForm', $query->form);
}
if($this->session->stakeholderQuery == false) $this->session->set('stakeholderQuery', ' 1=1');
$stakeholderQuery = $this->session->stakeholderQuery;
}
return $this->dao->select('t1.*,t2.key,t3.realname')->from(TABLE_EXPECT)->alias('t1')
->leftJoin(TABLE_STAKEHOLDER)->alias('t2')->on('t1.userID=t2.id')
->leftJoin(TABLE_USER)->alias('t3')->on('t2.user=t3.account')
->where('t1.project')->eq($this->session->project)
->beginIF($browseType == 'bysearch')
->andWhere($stakeholderQuery)
->fi()
->andWhere('t1.deleted')->eq('0')
->orderBy($orderBy)
->page($pager)
->fetchAll();
}
/**
* 删除一个期望。
* Delete a expect.
*
* @param int $expectID
* @access public
* @return bool
*/
public function deleteExpect(int $expectID): bool
{
$this->dao->update(TABLE_EXPECT)->set('deleted')->eq('1')->where('id')->eq($expectID)->exec();
return !dao::isError();
}
/**
* 获取项目下干系人field=>realname的键值对。
* Get a key-value pair for stakeholder field=>realname under the project.
*
* @access public
* @return array
*/
public function getStakeholderUsers(string $field = 'id'): array
{
return $this->dao->select("t1.{$field}, CONCAT_WS('/', t3.name,t2.realname) as realname")->from(TABLE_STAKEHOLDER)->alias('t1')
->leftJoin(TABLE_USER)->alias('t2')->on('t1.user=t2.account')
->leftJoin(TABLE_COMPANY)->alias('t3')->on('t2.company=t3.id')
->where('t1.objectID')->eq($this->session->project)
->andWhere('t1.deleted')->eq('0')
->fetchPairs($field, 'realname');
}
/**
* 通过ID获取期望详情。
* Get expect detail by ID.
*
* @param int $expectID
* @access public
* @return object|bool
*/
public function getExpectByID(int $expectID = 0): object|bool
{
return $this->dao->select('*')->from(TABLE_EXPECT)->where('id')->eq($expectID)->andWhere('deleted')->eq('0')->fetch();
}
/**
* 获取给定用户ID的期望信息。
* Get the expect information by user ID.
*
* @param int $userID
* @access public
* @return array
*/
public function getExpectByUser(int $userID = 0): array
{
return $this->dao->select('*')->from(TABLE_EXPECT)
->where('userID')->eq($userID)
->andWhere('deleted')->eq('0')
->orderBy('id_desc')
->fetchAll('id', false);
}
/**
* 获取给定干系人在当前项目下的问题信息。
* Get the issue information by account.
*
* @param string $account
* @access public
* @return array
*/
public function getStakeholderIssue(string $account): array
{
return $this->dao->select('*')->from(TABLE_ISSUE)
->where('project')->eq($this->session->project)
->andWhere('owner')->eq($account)
->andWhere('deleted')->eq('0')
->orderBy('id_desc')
->fetchAll();
}
/**
* 判断当前操作按钮是否可以点击。
* Judge the action is clickable.
*
* @param object $stakeholder
* @param string $action
* @access public
* @return bool
*/
public static function isClickable(object $stakeholder, string $action): bool
{
/* Judge the object whether can be changed. */
$canChange = common::canBeChanged('stakeholder', $stakeholder);
if(!$canChange) return false;
global $config;
$action = strtolower($action);
/* Special action can be set its own condition. */
if($action == 'notexists') return false;
if($action == 'userissue' && !in_array($config->edition, array('max', 'ipd'))) return false;
/* The action is clickable by default. */
return true;
}
}