browse.html.php 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. <?php
  2. namespace zin;
  3. $confirmDeleteLang['project'] = $lang->project->confirmDelete;
  4. jsVar('confirmDeleteLang', $confirmDeleteLang);
  5. jsVar('programBudgetLang', $lang->program->programBudget);
  6. jsVar('projectBudgetLang', $lang->program->projectBudget);
  7. jsVar('sumSubBudgetLang', $lang->program->sumSubBudget);
  8. jsVar('exceededBudgetLang', $lang->program->exceededBudget);
  9. jsVar('remainingBudgetLang', $lang->program->remainingBudget);
  10. jsVar('langManDay', $lang->program->manDay);
  11. jsVar('privPrograms', explode(',', $app->user->view->programs));
  12. jsVar('isAdmin', $app->user->admin);
  13. if($config->edition != 'open') $config->program->browse->dtable->fieldList['workflowGroup']['map'] = $this->loadModel('workflowGroup')->getPairs('project', 'all');
  14. $this->loadModel('project');
  15. $cols = $this->loadModel('datatable')->getSetting('program');
  16. $data = array();
  17. $parents = array();
  18. $showCheckbox = false;
  19. foreach($programs as $program)
  20. {
  21. if($program->type == 'project') $showCheckbox = true;
  22. if(empty($program->parent)) $program->parent = 0;
  23. if(empty($program->workflowGroup)) $program->workflowGroup = '';
  24. /* Delay status. */
  25. if($program->status != 'done' and $program->status != 'closed' and $program->status != 'suspended')
  26. {
  27. $delay = helper::diffDate(helper::today(), $program->end);
  28. if($delay > 0)
  29. {
  30. $program->postponed = true;
  31. $program->delayInfo = sprintf($lang->project->delayInfo, $delay);
  32. }
  33. }
  34. /* Set the program manager and avatar. */
  35. if(!empty($program->PM))
  36. {
  37. $userName = zget($users, $program->PM, '');
  38. $program->PMAvatar = $usersAvatar[$program->PM];
  39. $program->PMUserID = $PMList[$program->PM]->id;
  40. $program->PM = $userName;
  41. }
  42. else
  43. {
  44. $program->PMAvatar = '';
  45. $program->PM = '';
  46. }
  47. /* Calculate budget.*/
  48. $programBudget = $this->project->getBudgetWithUnit($program->budget);
  49. $program->rawBudget = (int)$program->budget;
  50. $program->budget = !empty($program->budget) ? zget($lang->project->currencySymbol, $program->budgetUnit) . ' ' . $programBudget : $lang->project->future;
  51. $parents[$program->parent][] = $program->id;
  52. $program->isParent = false;
  53. if($program->parent > 0 and isset($programs[$program->parent])) $programs[$program->parent]->isParent = true;
  54. if($program->parent > 0 and !isset($programs[$program->parent]))
  55. {
  56. $paths = str_replace(",{$program->parent},{$program->id},", ',', $program->path);
  57. $paths = explode(',', trim($paths, ','));
  58. $paths = array_reverse($paths);
  59. if($paths)
  60. {
  61. foreach($paths as $i => $parentID)
  62. {
  63. if(isset($programs[$parentID]))
  64. {
  65. $program->parent = $parentID;
  66. break;
  67. }
  68. unset($paths[$i]);
  69. }
  70. $program->path = ',' . implode(',', $paths) . ",{$program->id},";
  71. $program->grade = count($paths) + 1;
  72. }
  73. }
  74. /* Set invested hours. */
  75. $program->invested = !empty($this->config->execution->defaultWorkhours) ? round($program->consumed / $this->config->execution->defaultWorkhours, 2) : 0;
  76. if(!is_null($program->end) && strpos($program->end, LONG_TIME) !== false) $program->end = $lang->program->longTime;
  77. /* Actions. */
  78. $program->actions = array();
  79. $actions = $this->program->buildActions($program);
  80. foreach($actions as $action)
  81. {
  82. if(is_object($action)) $action->name = $program->type . '_' . $action->name;
  83. if(!is_object($action)) $action = $program->type . '_' . $action;
  84. if(isset($action->items)) foreach($action->items as $idx => $item) $action->items[$idx]->name = $program->type . '_' . $item->name;
  85. $program->actions[] = $action;
  86. }
  87. $data[$program->id] = $program;
  88. }
  89. $fnComputeSubBudget = function($programID, $sumBudget) use($parents, $data, &$fnComputeSubBudget)
  90. {
  91. if(!isset($parents[$programID]))
  92. {
  93. $sumBudget += $data[$programID]->rawBudget;
  94. }
  95. else
  96. {
  97. foreach($parents[$programID] as $subID) $sumBudget = $fnComputeSubBudget($subID, $sumBudget);
  98. }
  99. return $sumBudget;
  100. };
  101. foreach($data as $programID => $program)
  102. {
  103. if(!isset($parents[$programID])) continue;
  104. $program->subBudget = $fnComputeSubBudget($programID, 0);
  105. }
  106. /* Compute remaining budget. */
  107. foreach($parents as $parentID => $subs)
  108. {
  109. if(!isset($data[$parentID])) continue;
  110. $parentBudget = $data[$parentID]->rawBudget;
  111. if(empty($parentBudget)) continue;
  112. foreach($subs as $subID)
  113. {
  114. $subProgram = $data[$subID];
  115. if($subProgram->type == 'program') continue;
  116. $subProgram->remainingBudget = $parentBudget;
  117. array_map(function($programID) use ($data, $subProgram)
  118. {
  119. if($programID != $subProgram->id) $subProgram->remainingBudget -= $data[$programID]->rawBudget;
  120. }, $subs);
  121. }
  122. }
  123. foreach($data as $programID => $program)
  124. {
  125. if($program->rawBudget == 0) continue;
  126. if($program->type == 'program' && !empty($program->subBudget) && $program->rawBudget < $program->subBudget)
  127. {
  128. $program->exceedBudget = $program->subBudget - $program->rawBudget;
  129. $program->exceedBudget = $this->project->getBudgetWithUnit($program->exceedBudget);
  130. $program->subBudget = $this->project->getBudgetWithUnit($program->subBudget);
  131. }
  132. elseif($program->type == 'project' && !empty($program->remainingBudget) && $program->rawBudget > $program->remainingBudget)
  133. {
  134. $program->exceedBudget = $program->rawBudget - $program->remainingBudget;
  135. $program->exceedBudget = $this->project->getBudgetWithUnit($program->exceedBudget);
  136. $program->remainingBudget = $this->project->getBudgetWithUnit($program->remainingBudget);
  137. }
  138. $program->rawBudget = $this->project->getBudgetWithUnit($program->rawBudget);
  139. }
  140. featureBar
  141. (
  142. set::current($status),
  143. set::linkParams("status={key}&orderBy={$orderBy}"),
  144. li(searchToggle(set::module('program'), set::open($status == 'bySearch')))
  145. );
  146. $canCreateProject = hasPriv('project', 'create');
  147. $canCreateProgram = hasPriv('program', 'create');
  148. toolbar
  149. (
  150. $canCreateProject ? item(set
  151. ([
  152. 'text' => $lang->program->createProject,
  153. 'icon' => 'plus',
  154. 'class' => 'btn secondary create-project-btn',
  155. 'url' => createLink('project', 'createGuide'),
  156. 'data-toggle' => 'modal'
  157. ])) : null,
  158. $canCreateProgram ? item(set
  159. ([
  160. 'text' => $lang->program->create,
  161. 'icon' => 'plus',
  162. 'class'=> 'btn primary create-program-btn',
  163. 'url' => createLink('program', 'create')
  164. ])) : null
  165. );
  166. $canBatchEdit = common::hasPriv('project', 'batchEdit');
  167. $canSort = (common::hasPriv('program', 'updateOrder') && strpos($orderBy, 'order_asc') !== false);
  168. dtable
  169. (
  170. setID('projectviews'),
  171. set::plugins(array('sortable')),
  172. set::sortable($canSort),
  173. set::onSortEnd($canSort ? jsRaw('window.onSortEnd') : null),
  174. set::canSortTo($canSort ? jsRaw('window.canSortTo') : null),
  175. set::cols($cols),
  176. set::data(array_values($data)),
  177. set::userMap($users),
  178. set::customCols(true),
  179. set::checkable($canBatchEdit),
  180. set::nested(true),
  181. set::className('shadow rounded'),
  182. set::canRowCheckable(jsRaw("function(rowID){return this.getRowInfo(rowID).data.type == 'project';}")),
  183. set::onRenderCell(jsRaw('window.renderCell')),
  184. set::orderBy($orderBy),
  185. set::sortLink(createLink('program', 'browse', "status={$status}&orderBy={name}_{sortType}&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}&param={$param}")),
  186. set::footPager(usePager()),
  187. set::footToolbar(array
  188. (
  189. 'type' => 'btn-group',
  190. 'items' => array(
  191. $canBatchEdit ? array
  192. (
  193. 'text' => $lang->edit,
  194. 'type' => 'secondary',
  195. 'className' => 'size-sm batch-btn',
  196. 'data-page' => 'batch',
  197. 'data-formaction' => $this->createLink('project', 'batchEdit')
  198. ) : null
  199. )
  200. )),
  201. set::checkInfo(jsRaw("function(checkedIDList){ return window.footerSummary(this, checkedIDList);}")),
  202. set::emptyTip($lang->program->noProgram),
  203. set::createTip($lang->program->create),
  204. set::createLink($canCreateProgram ? createLink('program', 'create') : ''),
  205. !$canBatchEdit ? set::footer([jsRaw("function(){return {html: '{$summary}'};}"), 'flex', 'pager']) : null,
  206. set::customData(array('pageSummary' => $summary, 'checkedSummary' => $lang->program->checkedProjects))
  207. );
  208. render();