793 lines
31 KiB
PHP
793 lines
31 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
/**
|
|
* The control file of program module of ZenTaoPMS.
|
|
*
|
|
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
|
|
* @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
|
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
|
* @package program
|
|
* @link https://www.zentao.net
|
|
*/
|
|
class program extends control
|
|
{
|
|
/**
|
|
* Construct
|
|
*
|
|
* @param string $moduleName
|
|
* @param string $methodName
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function __construct($moduleName = '', $methodName = '')
|
|
{
|
|
parent::__construct($moduleName, $methodName);
|
|
$this->loadModel('project');
|
|
}
|
|
|
|
/**
|
|
* Program list.
|
|
*
|
|
* @param string $status
|
|
* @param string $orderBy
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function browse(string $status = 'unclosed', string $orderBy = 'order_asc', int $recTotal = 0, int $recPerPage = 100, int $pageID = 1, int $param = 0)
|
|
{
|
|
$uri = $this->app->getURI(true);
|
|
$this->session->set('programList', $uri, 'program');
|
|
$this->session->set('projectList', $uri, 'program');
|
|
$this->session->set('createProjectLocate', $uri, 'program');
|
|
|
|
$this->app->loadClass('pager', $static = true);
|
|
$pager = new pager($recTotal, $recPerPage, $pageID);
|
|
|
|
$programs = $this->programZen->getProgramsByType($status, $orderBy, (int)$param, $pager);
|
|
$PMList = $this->programZen->getPMListByPrograms($programs);
|
|
|
|
/* Build the search form. */
|
|
$actionURL = $this->createLink('program', 'browse', "status=bySearch&orderBy={$orderBy}&recTotal={$recTotal}&recPerPage={$recPerPage}&pageID={$pageID}¶m=myQueryID");
|
|
$this->config->program->search['actionURL'] = $actionURL;
|
|
$this->loadModel('search')->setSearchParams($this->config->program->search);
|
|
|
|
$this->view->title = $this->lang->program->browse;
|
|
$this->view->programs = $programs;
|
|
$this->view->status = $status;
|
|
$this->view->orderBy = $orderBy;
|
|
$this->view->pager = $pager;
|
|
$this->view->users = $this->loadModel('user')->getPairs('noletter');
|
|
$this->view->usersAvatar = $this->user->getAvatarPairs('');
|
|
$this->view->PMList = $PMList;
|
|
$this->view->param = $param;
|
|
|
|
$this->display();
|
|
}
|
|
|
|
/**
|
|
* 项目集看板。
|
|
* Program kanban list.
|
|
*
|
|
* @param string $browseType
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function kanban($browseType = 'my')
|
|
{
|
|
$this->view->title = $this->lang->program->kanban->common;
|
|
$this->view->kanbanList = $this->programZen->getKanbanList($browseType);
|
|
$this->view->browseType = $browseType;
|
|
$this->display();
|
|
}
|
|
|
|
/**
|
|
* 项目集下产品列表。
|
|
* Program products list.
|
|
*
|
|
* @param int $programID
|
|
* @param string $browseType
|
|
* @param string $orderBy
|
|
* @param int $recTotal
|
|
* @param int $recPerPage
|
|
* @param int $pageID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function product(int $programID = 0, string $browseType = 'noclosed', string $orderBy = 'order_asc', int $recTotal = 0, int $recPerPage = 15, int $pageID = 1)
|
|
{
|
|
$programPairs = $this->program->getPairs();
|
|
if($programID && !isset($programPairs[$programID]))
|
|
{
|
|
if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'fail', 'message' => '404 Not found'));
|
|
return $this->send(array('result' => 'success', 'load' => array('alert' => $this->lang->notFound, 'locate' => $this->createLink('program', 'browse'))));
|
|
}
|
|
|
|
$programID = $this->program->checkAccess($programID, $programPairs);
|
|
|
|
helper::setcookie("lastProgram", (string)$programID);
|
|
common::setMenuVars('program', $programID);
|
|
|
|
/* Get the top programID. */
|
|
if($programID)
|
|
{
|
|
$program = $this->program->getByID($programID);
|
|
$path = explode(',', $program->path);
|
|
$path = array_filter($path);
|
|
$programID = (int)current($path);
|
|
|
|
$this->view->program = $program;
|
|
}
|
|
|
|
/* Load pager. */
|
|
$this->app->loadClass('pager', true);
|
|
$pager = new pager($recTotal, $recPerPage, $pageID);
|
|
|
|
$products = $this->loadModel('product')->getList($programID, $browseType);
|
|
$this->view->products = $this->product->getStats(array_keys($products), $orderBy, $pager, 'story', $programID);
|
|
|
|
$this->view->title = $this->lang->program->product;
|
|
$this->view->programID = $programID;
|
|
$this->view->browseType = $browseType;
|
|
$this->view->orderBy = $orderBy;
|
|
$this->view->pager = $pager;
|
|
$this->view->users = $this->loadModel('user')->getPairs('noletter');
|
|
$this->view->userIdPairs = $this->user->getPairs('noletter|showid');
|
|
$this->view->usersAvatar = $this->user->getAvatarPairs('');
|
|
$this->display();
|
|
}
|
|
|
|
/**
|
|
* Create a program.
|
|
*
|
|
* @param int $parentProgramID
|
|
* @param int $charterID
|
|
* @param string $extra
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function create(int $parentProgramID = 0, int $charterID = 0, string $extra = '')
|
|
{
|
|
$parentProgram = $this->program->getByID($parentProgramID);
|
|
|
|
if($_POST)
|
|
{
|
|
$program = $this->programZen->buildProgramForCreate();
|
|
$programID = $this->program->create($program);
|
|
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
|
|
|
$this->loadModel('action')->create('program', $programID, 'opened');
|
|
$locateLink = $this->session->programList ? $this->session->programList : $this->createLink('program', 'browse');
|
|
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $programID, 'load' => $locateLink));
|
|
}
|
|
|
|
$originExtra = $extra;
|
|
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
|
|
parse_str($extra, $output);
|
|
|
|
$this->view->title = isset($parentProgram->id) ? $this->lang->program->children : $this->lang->program->create;
|
|
$this->view->gobackLink = (isset($output['from']) && $output['from'] == 'global') ? $this->createLink('program', 'browse') : '';
|
|
$this->view->pmUsers = $this->loadModel('user')->getPairs('noclosed|nodeleted|pmfirst');
|
|
$this->view->poUsers = $this->user->getPairs('noclosed|nodeleted|pofirst');
|
|
$this->view->users = $this->user->getPairs('noclosed|nodeleted');
|
|
$this->view->parentProgram = $parentProgram;
|
|
$this->view->parents = $this->program->getParentPairs();
|
|
$this->view->programList = $this->program->getList();
|
|
$this->view->budgetUnitList = $this->project->getBudgetUnitList();
|
|
$this->view->budgetLeft = empty($parentProgram) ? 0 : $this->program->getBudgetLeft($parentProgram);
|
|
$this->view->loadUrl = $this->createLink('program', 'create', "parentProgramID={parent}&charterID=0" . (empty($originExtra) ? '' : "&extra=$originExtra"));
|
|
|
|
$this->display();
|
|
}
|
|
|
|
/**
|
|
* 编辑项目集。
|
|
* Edit the program.
|
|
*
|
|
* @param int $programID
|
|
* @param int $parentProgramID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function edit(int $programID = 0, int $parentProgramID = 0)
|
|
{
|
|
if($_POST)
|
|
{
|
|
$program = $this->programZen->buildProgramForEdit($programID);
|
|
$changes = $this->program->update($programID, $program);
|
|
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
|
if($changes)
|
|
{
|
|
$actionID = $this->loadModel('action')->create('program', $programID, 'edited');
|
|
$this->action->logHistory($actionID, $changes);
|
|
}
|
|
|
|
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->session->programList ? $this->session->programList : inLink('browse')));
|
|
}
|
|
|
|
$program = $this->program->getByID($programID);
|
|
|
|
if($parentProgramID) $program->parent = $parentProgramID;
|
|
$parentProgram = $program->parent ? $this->program->getByID($program->parent) : new stdclass();
|
|
$parents = $this->program->getParentPairs();
|
|
$parents = $this->programZen->removeSubjectToCurrent($parents, $programID);
|
|
$disableParent = false;
|
|
|
|
if(!isset($parents[$program->parent]))
|
|
{
|
|
$disableParent = true;
|
|
if(!empty($program->parent)) $parents = array($parentProgram->id => $parentProgram->name);
|
|
}
|
|
|
|
$this->view->title = $this->lang->program->edit;
|
|
|
|
$this->view->pmUsers = $this->loadModel('user')->getPairs('noclosed|nodeleted|pmfirst', $program->PM);
|
|
$this->view->program = $program;
|
|
$this->view->parents = $parents;
|
|
$this->view->disableParent = $disableParent;
|
|
$this->view->budgetUnitList = $this->loadModel('project')->getBudgetUnitList();
|
|
$this->view->parentProgram = $parentProgram;
|
|
$this->view->loadUrl = $this->createLink('program', 'edit', "programID=$programID&parentProgramID={parent}");
|
|
|
|
$this->display();
|
|
}
|
|
|
|
/**
|
|
* 关闭一个项目集。
|
|
* Close a program.
|
|
*
|
|
* @param int $programID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function close(int $programID)
|
|
{
|
|
$this->loadModel('action');
|
|
$program = $this->program->getByID($programID);
|
|
|
|
if(!empty($_POST))
|
|
{
|
|
/* Only when all subprograms and subprojects are closed can the program be closed. */
|
|
$hasUnfinished = $this->program->hasUnfinishedChildren($program);
|
|
if($hasUnfinished) return $this->send(array('result' => 'fail', 'callback' => "zui.Modal.alert('{$this->lang->program->closeErrorMessage}');"));
|
|
|
|
$programData = form::data(null, $programID)
|
|
->add('closedBy', $this->app->user->account)
|
|
->add('lastEditedBy', $this->app->user->account)
|
|
->get();
|
|
|
|
$changes = $this->program->close($programData, $program);
|
|
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
|
|
|
if($this->post->comment != '' || !empty($changes))
|
|
{
|
|
$actionID = $this->action->create('program', $programID, 'Closed', $this->post->comment);
|
|
$this->action->logHistory($actionID, $changes);
|
|
}
|
|
|
|
$this->executeHooks($programID);
|
|
return $this->sendSuccess(array('closeModal' => true, 'load' => true));
|
|
}
|
|
|
|
$this->view->title = $this->lang->program->close;
|
|
$this->view->program = $program;
|
|
$this->view->users = $this->loadModel('user')->getPairs('noletter');
|
|
$this->view->actions = $this->action->getList('program', $programID);
|
|
|
|
$this->display();
|
|
}
|
|
|
|
/**
|
|
* 启动项目集。
|
|
* Start a program.
|
|
*
|
|
* @param int $programID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function start(int $programID)
|
|
{
|
|
$this->loadModel('action');
|
|
$program = $this->project->getByID($programID);
|
|
|
|
if(!empty($_POST))
|
|
{
|
|
$postData = form::data($this->config->program->form->start, $programID);
|
|
$postData = $this->programZen->prepareStartExtras($postData);
|
|
$changes = $this->project->start($programID, $postData);
|
|
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
|
|
|
if($this->post->comment != '' or !empty($changes))
|
|
{
|
|
$actionID = $this->action->create('program', $programID, 'Started', $this->post->comment);
|
|
$this->action->logHistory($actionID, $changes);
|
|
}
|
|
|
|
$this->loadModel('common')->syncPPEStatus($programID);
|
|
$this->executeHooks($programID);
|
|
return $this->sendSuccess(array('closeModal' => true, 'load' => true));
|
|
}
|
|
|
|
$this->view->title = $this->lang->program->start;
|
|
$this->view->project = $program;
|
|
$this->view->users = $this->loadModel('user')->getPairs('noletter');
|
|
$this->view->actions = $this->action->getList('program', $programID);
|
|
$this->display('project', 'start');
|
|
}
|
|
|
|
/**
|
|
* 激活一个项目集。
|
|
* Activate a program.
|
|
*
|
|
* @param int $programID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function activate(int $programID = 0)
|
|
{
|
|
$this->loadModel('action');
|
|
$program = $this->program->getByID($programID);
|
|
|
|
if(!empty($_POST))
|
|
{
|
|
$programData = form::data(null, $programID)->add('lastEditedBy', $this->app->user->account)->get();
|
|
$changes = $this->program->activate($programData, $program);
|
|
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
|
|
|
if($this->post->comment != '' || !empty($changes))
|
|
{
|
|
$actionID = $this->action->create('program', $programID, 'Activated', $this->post->comment);
|
|
$this->action->logHistory($actionID, $changes);
|
|
}
|
|
return $this->sendSuccess(array('closeModal' => true, 'load' => true));
|
|
}
|
|
|
|
$newBegin = date('Y-m-d');
|
|
$dateDiff = helper::diffDate($newBegin, $program->begin);
|
|
$newEnd = date('Y-m-d', strtotime($program->end) + $dateDiff * 24 * 3600);
|
|
|
|
$this->view->title = $this->lang->program->activate;
|
|
$this->view->program = $program;
|
|
$this->view->users = $this->loadModel('user')->getPairs('noletter');
|
|
$this->view->actions = $this->action->getList('program', $programID);
|
|
$this->view->newBegin = $newBegin;
|
|
$this->view->newEnd = $newEnd;
|
|
$this->display();
|
|
}
|
|
|
|
/**
|
|
* 挂起项目集。
|
|
* Suspend a program.
|
|
*
|
|
* @param int $programID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function suspend(int $programID)
|
|
{
|
|
$this->loadModel('action');
|
|
|
|
$this->extendRequireFields($programID);
|
|
if(!empty($_POST))
|
|
{
|
|
$postData = fixer::input('post')
|
|
->add('id', $programID)
|
|
->setDefault('status', 'suspended')
|
|
->setDefault('lastEditedBy', $this->app->user->account)
|
|
->setDefault('lastEditedDate', helper::now())
|
|
->setDefault('suspendedDate', helper::today())
|
|
->stripTags($this->config->program->editor->suspend['id'], $this->config->allowedTags)
|
|
->get();
|
|
|
|
$isSucceed = $this->program->suspend($programID, $postData);
|
|
if(!$isSucceed) return $this->sendError(dao::getError(), true);
|
|
|
|
$this->executeHooks($programID);
|
|
return $this->sendSuccess(array('closeModal' => true, 'load' => true));
|
|
}
|
|
|
|
$this->view->title = $this->lang->program->suspend;
|
|
$this->view->users = $this->loadModel('user')->getPairs('noletter');
|
|
$this->view->actions = $this->action->getList('program', $programID);
|
|
$this->view->program = $this->program->getByID($programID);
|
|
|
|
$this->display();
|
|
}
|
|
|
|
/**
|
|
* 删除一个项目集。
|
|
* Delete a program.
|
|
*
|
|
* @param int $programID
|
|
* @param string $confirm
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function delete(int $programID, string $confirm = 'no')
|
|
{
|
|
/* The program can NOT be deleted if it has a child program. */
|
|
$childrenPairs = $this->program->getChildrenPairsByID($programID);
|
|
if(count($childrenPairs))
|
|
{
|
|
if($this->viewType == 'json' or (defined('RUN_MODE') && RUN_MODE == 'api')) return $this->send(array('result' => 'fail', 'message' => 'Can not delete the program has children.'));
|
|
return $this->send(array('result' => 'fail', 'callback' => "zui.Modal.alert({icon: 'icon-exclamation-sign', iconClass: 'warning-pale rounded-full icon-2x', message: '{$this->lang->program->hasChildren}'})"));
|
|
}
|
|
|
|
/* The program can NOT be deleted if it has a product. */
|
|
$productPairs = $this->program->getProductPairsByID($programID);
|
|
if(count($productPairs)) return $this->send(array('result' => 'fail', 'callback' => "zui.Modal.alert({icon: 'icon-exclamation-sign', iconClass: 'warning-pale rounded-full icon-2x', message: '{$this->lang->program->hasProduct}'})"));
|
|
|
|
/* Mark the program is deleted and record the action log. */
|
|
$program = $this->dao->select('*')->from(TABLE_PROGRAM)->where('id')->eq($programID)->andWhere('deleted')->eq('0')->fetch();
|
|
if($confirm == 'no')
|
|
{
|
|
return $this->send(array('result' => 'fail', 'callback' => "zui.Modal.confirm({icon: 'icon-exclamation-sign', iconClass: 'warning-pale rounded-full icon-2x', message: '" . sprintf($this->lang->program->confirmDelete, $program->name) . "'}).then((res) => {if(res) $.ajaxSubmit({url: '" . $this->createLink('program', 'delete', "programID={$programID}&confirm=yes") . "'});});"));
|
|
}
|
|
else
|
|
{
|
|
if($program)
|
|
{
|
|
$this->dao->update(TABLE_PROGRAM)->set('deleted')->eq('1')->where('id')->eq($programID)->exec();
|
|
$this->loadModel('action')->create('program', $programID, 'deleted', '', actionModel::CAN_UNDELETED);
|
|
}
|
|
return $this->send(array('result' => 'success', 'load' => true));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取项目集下的项目。
|
|
* Program project list.
|
|
*
|
|
* @param int $programID
|
|
* @param string $browseType
|
|
* @param string $orderBy
|
|
* @param int $recTotal
|
|
* @param int $recPerPage
|
|
* @param int $pageID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function project(int $programID = 0, string $browseType = 'doing', string $orderBy = 'order_desc', int $recTotal = 0, int $recPerPage = 15, int $pageID = 1)
|
|
{
|
|
$programID = $this->program->checkAccess($programID, $this->program->getPairs());
|
|
helper::setcookie("lastProgram", (string)$programID);
|
|
common::setMenuVars('program', $programID);
|
|
|
|
/* Set back link. */
|
|
$uri = $this->app->getURI(true);
|
|
$this->app->session->set('programProject', $uri, 'program');
|
|
$this->app->session->set('projectList', $uri, 'program');
|
|
$this->app->session->set('createProjectLocate', $uri, 'program');
|
|
|
|
/* Load pager. */
|
|
$this->app->loadClass('pager', $static = true);
|
|
$pager = new pager($recTotal, $recPerPage, $pageID);
|
|
|
|
$programTitle = $this->loadModel('setting')->getItem('owner=' . $this->app->user->account . '&module=program&key=programTitle');
|
|
$order = explode('_', $orderBy);
|
|
$sortField = zget($this->config->program->sortFields, $order[0], 'id') . '_' . $order[1];
|
|
$projectStats = $this->program->getProjectStats($programID, $browseType, 0, $sortField, $programTitle, false, $pager);
|
|
|
|
$this->view->title = $this->lang->program->project;
|
|
$this->view->projectStats = $projectStats;
|
|
$this->view->pager = $pager;
|
|
$this->view->programID = $programID;
|
|
$this->view->users = $this->loadModel('user')->getPairs('noletter|pofirst|nodeleted');
|
|
$this->view->PMList = $this->user->getListByAccounts(helper::arrayColumn($projectStats, 'PM'), 'account');
|
|
$this->view->browseType = $browseType;
|
|
$this->view->orderBy = $orderBy;
|
|
$this->display();
|
|
}
|
|
|
|
/**
|
|
* 项目集下的干系人列表。
|
|
* Program stakeholder list.
|
|
*
|
|
* @param int $programID
|
|
* @param string $orderBy
|
|
* @param int $recTotal
|
|
* @param int $recPerPage
|
|
* @param int $pageID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function stakeholder(int $programID = 0, string $orderBy = 't1.id_desc', int $recTotal = 0, int $recPerPage = 15, int $pageID = 1)
|
|
{
|
|
$this->app->loadLang('stakeholder');
|
|
common::setMenuVars('program', $programID);
|
|
|
|
$this->app->loadClass('pager', true);
|
|
$pager = new pager($recTotal, $recPerPage, $pageID);
|
|
|
|
$sort = $orderBy;
|
|
if(strpos($sort, 'name_') !== false) $sort = str_replace('name_', 'realname_', $sort);
|
|
|
|
$this->view->title = $this->lang->program->stakeholder;
|
|
$this->view->pager = $pager;
|
|
$this->view->stakeholders = $this->program->getStakeholders($programID, $sort, $pager);
|
|
$this->view->programID = $programID;
|
|
$this->view->program = $this->program->getByID($programID);
|
|
$this->view->users = $this->loadModel('user')->getPairs('noletter|pofirst|nodeleted');
|
|
$this->view->orderBy = $orderBy;
|
|
|
|
$this->display();
|
|
}
|
|
|
|
/**
|
|
* 创建项目集干系人。
|
|
* Create program stakeholder.
|
|
*
|
|
* @param int $programID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function createStakeholder(int $programID = 0)
|
|
{
|
|
return print($this->fetch('stakeholder', 'create', "objectID=$programID"));
|
|
}
|
|
|
|
/**
|
|
* 解除干系人跟项目集的关联关系。
|
|
* Unlink stakeholder from the program.
|
|
*
|
|
* @param int $programID
|
|
* @param int $stakeholderID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function unlinkStakeholder(int $programID, int $stakeholderID)
|
|
{
|
|
$this->program->batchUnlinkStakeholders($programID, array($stakeholderID));
|
|
|
|
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
|
return $this->send(array('result' => 'success', 'load' => true));
|
|
}
|
|
|
|
/**
|
|
* 批量移除项目集下的关系人。
|
|
* Batch unlink program stakeholders.
|
|
*
|
|
* @param int $programID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function batchUnlinkStakeholders(int $programID = 0)
|
|
{
|
|
if(!$this->post->stakeholderIdList) return $this->send(array('load' => true));
|
|
|
|
$this->program->batchUnlinkStakeholders($programID, $this->post->stakeholderIdList);
|
|
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
|
|
|
return $this->sendSuccess(array('load' => true));
|
|
}
|
|
|
|
/**
|
|
* 导出项目集。
|
|
* Export program.
|
|
*
|
|
* @param string $status
|
|
* @param string $orderBy
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function export(string $status, string $orderBy)
|
|
{
|
|
if($_POST)
|
|
{
|
|
/* Create field lists. */
|
|
$fields = $this->post->exportFields ? $this->post->exportFields : explode(',', $this->config->program->list->exportFields);
|
|
foreach($fields as $key => $fieldName)
|
|
{
|
|
$fieldName = trim($fieldName);
|
|
$fields[$fieldName] = zget($this->lang->program, $fieldName);
|
|
unset($fields[$key]);
|
|
}
|
|
|
|
/* Get and process program list. */
|
|
$users = $this->loadModel('user')->getPairs('noletter');
|
|
$programs = $this->program->getList($status, $orderBy);
|
|
$products = $this->program->getProductByProgram(array_keys($programs));
|
|
foreach($programs as $programID => $program)
|
|
{
|
|
$program->PM = zget($users, $program->PM);
|
|
$program->status = $this->processStatus('project', $program);
|
|
$program->model = zget($this->lang->project->modelList, $program->model);
|
|
$program->product = empty($products[$programID]) ? '' : implode(",", helper::arrayColumn($products[$programID], 'name'));
|
|
$program->budget = $program->budget . zget($this->lang->project->unitList, $program->budgetUnit);
|
|
|
|
if($this->post->exportType == 'selected')
|
|
{
|
|
$checkedItem = $this->post->checkedItem;
|
|
if(strpos(",$checkedItem,", ",{$program->id},") === false) unset($programs[$programID]);
|
|
}
|
|
}
|
|
|
|
if($this->config->edition != 'open') list($fields, $projectStats) = $this->loadModel('workflowfield')->appendDataFromFlow($fields, $projectStats);
|
|
|
|
$this->post->set('fields', $fields);
|
|
$this->post->set('rows', $programs);
|
|
$this->post->set('kind', 'program');
|
|
$this->fetch('file', 'export2' . $this->post->fileType);
|
|
}
|
|
|
|
$this->display();
|
|
}
|
|
|
|
/**
|
|
* 获取项目集下1.5级导航数据。
|
|
* Get sub navigation data of program.
|
|
*
|
|
* @param int $programID
|
|
* @param string $module
|
|
* @param string $method
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function ajaxGetDropMenu(int $programID, string $module, string $method)
|
|
{
|
|
$programs = $this->program->getList('all', 'order_asc');
|
|
foreach($programs as $programID => $program)
|
|
{
|
|
if($program->type != 'program') unset($programs[$programID]);
|
|
if($module == 'program' && $method == 'product' && $program->parent != 0) unset($programs[$programID]);
|
|
}
|
|
|
|
$this->view->programTree = $this->programZen->buildTree($programs);
|
|
$this->view->link = $this->programZen->getLink($module, $method, '{id}', '', 'program');
|
|
$this->display();
|
|
}
|
|
|
|
/**
|
|
* 更新项目集排序。
|
|
* Update program order.
|
|
*
|
|
* @access public
|
|
* @return string
|
|
*/
|
|
public function updateOrder()
|
|
{
|
|
$programIdList = json_decode($this->post->programIdList, true);
|
|
if(!$programIdList) return $this->send(array('result' => 'success'));
|
|
|
|
asort($programIdList);
|
|
$programIdList = array_flip($programIdList);
|
|
|
|
$oldOrders = $this->dao->select('id,`order`')->from(TABLE_PROJECT)->where('id')->in($programIdList)->orderBy('`order`')->fetchPairs('id', 'order');
|
|
if(count($programIdList) != count($oldOrders)) return $this->send(array('result' => 'success'));
|
|
|
|
$newOrders = array_combine($programIdList, $oldOrders);
|
|
foreach($newOrders as $programID => $order)
|
|
{
|
|
if($order != $oldOrders[$programID]) $this->dao->update(TABLE_PROJECT)->set('`order`')->eq($order)->where('id')->eq($programID)->exec();
|
|
}
|
|
|
|
return $this->send(array('result' => 'success', 'load' => true));
|
|
}
|
|
|
|
/*
|
|
* 移除项目集白名单成员。
|
|
* Removing users from the white list.
|
|
*
|
|
* @param int $aclID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function unbindWhitelist(int $aclID)
|
|
{
|
|
echo $this->fetch('personnel', 'unbindWhitelist', "id={$aclID}&confirm=yes");
|
|
}
|
|
|
|
/**
|
|
* 查看项目集详情。
|
|
* View program detail.
|
|
*
|
|
* @param int $programID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function view(int $programID)
|
|
{
|
|
$program = $this->program->getByID($programID);
|
|
if(!$program) return $this->sendError($this->lang->notFound, true);
|
|
|
|
if(common::hasPriv('program', 'product')) $this->locate(inlink('product', "programID=$programID"));
|
|
if(common::hasPriv('program', 'project')) $this->locate(inlink('project', "programID=$programID"));
|
|
}
|
|
|
|
/**
|
|
* 设置显示非当前项目集的项目信息。
|
|
* Set to display project information other than the current project set.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function ajaxSetShowSetting()
|
|
{
|
|
if($this->post->showAllProjects !== false) $this->loadModel('setting')->updateItem("{$this->app->user->account}.program.showAllProjects", $this->post->showAllProjects);
|
|
}
|
|
|
|
/**
|
|
* 以产品视角查看项目集。
|
|
* Show program list in product view.
|
|
* copied from all() function of product module.
|
|
*
|
|
* @param string $browseType
|
|
* @param string $orderBy
|
|
* @param int $param
|
|
* @param int $recTotal
|
|
* @param int $recPerPage
|
|
* @param int $pageID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function productView(string $browseType = 'unclosed', string $orderBy = 'program_asc', int $param = 0, int $recTotal = 0, int $recPerPage = 100, int $pageID = 1)
|
|
{
|
|
/* Load module and set session. */
|
|
$this->loadModel('product');
|
|
$this->loadModel('user');
|
|
$this->session->set('productList', $this->app->getURI(true), 'program');
|
|
|
|
$this->app->loadClass('pager', true);
|
|
$pager = new pager($recTotal, $recPerPage, $pageID);
|
|
|
|
/* Process product structure. */
|
|
if($this->config->systemMode == 'light' and $orderBy == 'program_asc') $orderBy = 'order_asc';
|
|
|
|
$products = $this->product->getList();
|
|
if(strtolower($browseType) == 'bysearch')
|
|
{
|
|
$programs = $this->program->getListBySearch('id', (int)$param);
|
|
array_map(function($product) use($programs, &$products){ if(!isset($programs[$product->program])) unset($products[$product->id]);}, $products);
|
|
}
|
|
$products = $this->programZen->getProductsByBrowseType($browseType, $products); /* Filter the program by browse type. */
|
|
|
|
$productStats = $this->product->getStats(array_keys($products), $orderBy, $pager); /* The product stats list with program data and product data. */
|
|
$productStructure = $this->product->statisticProgram($productStats);
|
|
$productLines = $this->dao->select('*')->from(TABLE_MODULE)->where('type')->eq('line')->andWhere('deleted')->eq(0)->orderBy('`order` asc')->fetchAll();
|
|
$programLines = array();
|
|
|
|
foreach($productLines as $productLine)
|
|
{
|
|
if(!isset($programLines[$productLine->root])) $programLines[$productLine->root] = array();
|
|
$programLines[$productLine->root][$productLine->id] = $productLine->name;
|
|
}
|
|
|
|
$actionURL = $this->createLink('program', 'productview', "browseType=bySearch&orderBy=order_asc&queryID=myQueryID");
|
|
$this->config->program->search['actionURL'] = $actionURL;
|
|
$this->loadModel('search')->setSearchParams($this->config->program->search);
|
|
|
|
$this->view->title = $this->lang->product->common;
|
|
$this->view->productStats = $productStats;
|
|
$this->view->productStructure = $productStructure;
|
|
$this->view->productLines = $productLines;
|
|
$this->view->programLines = $programLines;
|
|
$this->view->users = $this->user->getPairs('noletter');
|
|
$this->view->orderBy = $orderBy;
|
|
$this->view->browseType = $browseType;
|
|
$this->view->pager = $pager;
|
|
$this->view->checkedEditProduct = !empty((int)$this->cookie->checkedEditProduct);
|
|
$this->view->param = $param;
|
|
|
|
$this->render();
|
|
}
|
|
|
|
/**
|
|
* 刷新项目集统计数据。
|
|
* Refresh program stats.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function refreshStats()
|
|
{
|
|
$this->program->refreshStats();
|
|
|
|
if(dao::isError())
|
|
{
|
|
echo json_encode(dao::getError());
|
|
return true;
|
|
}
|
|
|
|
echo 'success';
|
|
}
|
|
}
|