232 lines
8.6 KiB
PHP
232 lines
8.6 KiB
PHP
<?php
|
|
namespace zin;
|
|
|
|
$confirmDeleteLang['project'] = $lang->project->confirmDelete;
|
|
jsVar('confirmDeleteLang', $confirmDeleteLang);
|
|
jsVar('programBudgetLang', $lang->program->programBudget);
|
|
jsVar('projectBudgetLang', $lang->program->projectBudget);
|
|
jsVar('sumSubBudgetLang', $lang->program->sumSubBudget);
|
|
jsVar('exceededBudgetLang', $lang->program->exceededBudget);
|
|
jsVar('remainingBudgetLang', $lang->program->remainingBudget);
|
|
jsVar('langManDay', $lang->program->manDay);
|
|
jsVar('privPrograms', explode(',', $app->user->view->programs));
|
|
jsVar('isAdmin', $app->user->admin);
|
|
|
|
if($config->edition != 'open') $config->program->browse->dtable->fieldList['workflowGroup']['map'] = $this->loadModel('workflowGroup')->getPairs('project', 'all');
|
|
|
|
$this->loadModel('project');
|
|
$cols = $this->loadModel('datatable')->getSetting('program');
|
|
$data = array();
|
|
$parents = array();
|
|
$showCheckbox = false;
|
|
foreach($programs as $program)
|
|
{
|
|
if($program->type == 'project') $showCheckbox = true;
|
|
|
|
if(empty($program->parent)) $program->parent = 0;
|
|
if(empty($program->workflowGroup)) $program->workflowGroup = '';
|
|
|
|
/* Delay status. */
|
|
if($program->status != 'done' and $program->status != 'closed' and $program->status != 'suspended')
|
|
{
|
|
$delay = helper::diffDate(helper::today(), $program->end);
|
|
if($delay > 0)
|
|
{
|
|
$program->postponed = true;
|
|
$program->delayInfo = sprintf($lang->project->delayInfo, $delay);
|
|
}
|
|
}
|
|
|
|
/* Set the program manager and avatar. */
|
|
if(!empty($program->PM))
|
|
{
|
|
$userName = zget($users, $program->PM, '');
|
|
$program->PMAvatar = $usersAvatar[$program->PM];
|
|
$program->PMUserID = $PMList[$program->PM]->id;
|
|
$program->PM = $userName;
|
|
}
|
|
else
|
|
{
|
|
$program->PMAvatar = '';
|
|
$program->PM = '';
|
|
}
|
|
|
|
/* Calculate budget.*/
|
|
$programBudget = $this->project->getBudgetWithUnit($program->budget);
|
|
$program->rawBudget = (int)$program->budget;
|
|
$program->budget = !empty($program->budget) ? zget($lang->project->currencySymbol, $program->budgetUnit) . ' ' . $programBudget : $lang->project->future;
|
|
$parents[$program->parent][] = $program->id;
|
|
|
|
$program->isParent = false;
|
|
if($program->parent > 0 and isset($programs[$program->parent])) $programs[$program->parent]->isParent = true;
|
|
if($program->parent > 0 and !isset($programs[$program->parent]))
|
|
{
|
|
$paths = str_replace(",{$program->parent},{$program->id},", ',', $program->path);
|
|
$paths = explode(',', trim($paths, ','));
|
|
$paths = array_reverse($paths);
|
|
if($paths)
|
|
{
|
|
foreach($paths as $i => $parentID)
|
|
{
|
|
if(isset($programs[$parentID]))
|
|
{
|
|
$program->parent = $parentID;
|
|
break;
|
|
}
|
|
unset($paths[$i]);
|
|
}
|
|
$program->path = ',' . implode(',', $paths) . ",{$program->id},";
|
|
$program->grade = count($paths) + 1;
|
|
}
|
|
}
|
|
|
|
/* Set invested hours. */
|
|
$program->invested = !empty($this->config->execution->defaultWorkhours) ? round($program->consumed / $this->config->execution->defaultWorkhours, 2) : 0;
|
|
|
|
if(!is_null($program->end) && str_contains($program->end, LONG_TIME)) $program->end = $lang->program->longTime;
|
|
|
|
/* Actions. */
|
|
$program->actions = array();
|
|
$actions = $this->program->buildActions($program);
|
|
foreach($actions as $action)
|
|
{
|
|
if(is_object($action)) $action->name = $program->type . '_' . $action->name;
|
|
if(!is_object($action)) $action = $program->type . '_' . $action;
|
|
|
|
if(isset($action->items)) foreach($action->items as $idx => $item) $action->items[$idx]->name = $program->type . '_' . $item->name;
|
|
$program->actions[] = $action;
|
|
}
|
|
|
|
$data[$program->id] = $program;
|
|
}
|
|
|
|
$fnComputeSubBudget = function($programID, $sumBudget) use($parents, $data, &$fnComputeSubBudget)
|
|
{
|
|
if(!isset($parents[$programID]))
|
|
{
|
|
$sumBudget += $data[$programID]->rawBudget;
|
|
}
|
|
else
|
|
{
|
|
foreach($parents[$programID] as $subID) $sumBudget = $fnComputeSubBudget($subID, $sumBudget);
|
|
}
|
|
return $sumBudget;
|
|
};
|
|
|
|
foreach($data as $programID => $program)
|
|
{
|
|
if(!isset($parents[$programID])) continue;
|
|
$program->subBudget = $fnComputeSubBudget($programID, 0);
|
|
}
|
|
|
|
/* Compute remaining budget. */
|
|
foreach($parents as $parentID => $subs)
|
|
{
|
|
if(!isset($data[$parentID])) continue;
|
|
|
|
$parentBudget = $data[$parentID]->rawBudget;
|
|
if(empty($parentBudget)) continue;
|
|
foreach($subs as $subID)
|
|
{
|
|
$subProgram = $data[$subID];
|
|
if($subProgram->type == 'program') continue;
|
|
$subProgram->remainingBudget = $parentBudget;
|
|
array_map(function($programID) use ($data, $subProgram)
|
|
{
|
|
if($programID != $subProgram->id) $subProgram->remainingBudget -= $data[$programID]->rawBudget;
|
|
}, $subs);
|
|
}
|
|
}
|
|
|
|
foreach($data as $programID => $program)
|
|
{
|
|
if($program->rawBudget == 0) continue;
|
|
if($program->type == 'program' && !empty($program->subBudget) && $program->rawBudget < $program->subBudget)
|
|
{
|
|
$program->exceedBudget = $program->subBudget - $program->rawBudget;
|
|
$program->exceedBudget = $this->project->getBudgetWithUnit($program->exceedBudget);
|
|
$program->subBudget = $this->project->getBudgetWithUnit($program->subBudget);
|
|
}
|
|
elseif($program->type == 'project' && !empty($program->remainingBudget) && $program->rawBudget > $program->remainingBudget)
|
|
{
|
|
$program->exceedBudget = $program->rawBudget - $program->remainingBudget;
|
|
$program->exceedBudget = $this->project->getBudgetWithUnit($program->exceedBudget);
|
|
$program->remainingBudget = $this->project->getBudgetWithUnit($program->remainingBudget);
|
|
}
|
|
$program->rawBudget = $this->project->getBudgetWithUnit($program->rawBudget);
|
|
}
|
|
|
|
featureBar
|
|
(
|
|
set::current($status),
|
|
set::linkParams("status={key}&orderBy={$orderBy}"),
|
|
li(searchToggle(set::module('program'), set::open($status == 'bySearch')))
|
|
);
|
|
|
|
$canCreateProject = hasPriv('project', 'create');
|
|
$canCreateProgram = hasPriv('program', 'create');
|
|
|
|
toolbar
|
|
(
|
|
$canCreateProject ? item(set
|
|
([
|
|
'text' => $lang->program->createProject,
|
|
'icon' => 'plus',
|
|
'class' => 'btn secondary create-project-btn',
|
|
'url' => createLink('project', 'createGuide'),
|
|
'data-toggle' => 'modal'
|
|
])) : null,
|
|
$canCreateProgram ? item(set
|
|
([
|
|
'text' => $lang->program->create,
|
|
'icon' => 'plus',
|
|
'class'=> 'btn primary create-program-btn',
|
|
'url' => createLink('program', 'create')
|
|
])) : null
|
|
);
|
|
|
|
$canBatchEdit = common::hasPriv('project', 'batchEdit');
|
|
$canSort = (common::hasPriv('program', 'updateOrder') && strpos($orderBy, 'order_asc') !== false);
|
|
dtable
|
|
(
|
|
setID('projectviews'),
|
|
set::plugins(array('sortable')),
|
|
set::sortable($canSort),
|
|
set::onSortEnd($canSort ? jsRaw('window.onSortEnd') : null),
|
|
set::canSortTo($canSort ? jsRaw('window.canSortTo') : null),
|
|
set::cols($cols),
|
|
set::data(array_values($data)),
|
|
set::userMap($users),
|
|
set::customCols(true),
|
|
set::checkable($canBatchEdit),
|
|
set::nested(true),
|
|
set::className('shadow rounded'),
|
|
set::canRowCheckable(jsRaw("function(rowID){return this.getRowInfo(rowID).data.type == 'project';}")),
|
|
set::onRenderCell(jsRaw('window.renderCell')),
|
|
set::orderBy($orderBy),
|
|
set::sortLink(createLink('program', 'browse', "status={$status}&orderBy={name}_{sortType}&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}¶m={$param}")),
|
|
set::footPager(usePager()),
|
|
set::footToolbar(array
|
|
(
|
|
'type' => 'btn-group',
|
|
'items' => array(
|
|
$canBatchEdit ? array
|
|
(
|
|
'text' => $lang->edit,
|
|
'type' => 'secondary',
|
|
'className' => 'size-sm batch-btn',
|
|
'data-page' => 'batch',
|
|
'data-formaction' => $this->createLink('project', 'batchEdit')
|
|
) : null
|
|
)
|
|
)),
|
|
set::checkInfo(jsRaw("function(checkedIDList){ return window.footerSummary(this, checkedIDList);}")),
|
|
set::emptyTip($lang->program->noProgram),
|
|
set::createTip($lang->program->create),
|
|
set::createLink($canCreateProgram ? createLink('program', 'create') : ''),
|
|
!$canBatchEdit ? set::footer([jsRaw("function(){return {html: '{$summary}'};}"), 'flex', 'pager']) : null,
|
|
set::customData(array('pageSummary' => $summary, 'checkedSummary' => $lang->program->checkedProjects))
|
|
);
|
|
|
|
render();
|