superedit-BUDGET_ANALYTICS.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. <?php
  2. function BUDGET_ANALYTICS() {
  3. $budgetAnalyticsRouter = new BudgetAnalyticsRouter();
  4. $args = array();
  5. $args['year'] = V::get('zest_year', '', $_REQUEST, 'int');
  6. $args['_print'] = V::get('_print', '', $_REQUEST, 'int');
  7. if (!$args['_print']) {
  8. $budgetAnalyticsRouter->menu($args['year']);
  9. }
  10. if (empty($args['year'])) {
  11. ?>
  12. <div class="alert alert-warning">
  13. Nie wybrano roku.
  14. </div>
  15. <?
  16. return;
  17. }
  18. $costs = $budgetAnalyticsRouter->getCostsByYear($args['year']);
  19. if (empty($costs)) {
  20. ?>
  21. <div class="alert alert-warning">
  22. Brak danych na wybrany rok.
  23. </div>
  24. <?
  25. return;
  26. }
  27. $projTree = $budgetAnalyticsRouter->buildProjectTree($costs);
  28. //$orderby = V::get('orderby', '', $_GET);
  29. //$view_type = V::get('view_type', '', $_GET);
  30. //$budgetAnalyticsRouter->cyfrowe($projekty, $grupyKosztow, $costs, $orderby, $view_type);
  31. $budgetAnalyticsRouter->printCostsForYear($projTree, $costs, $args['year']);
  32. }
  33. class BudgetAnalyticsRouter {
  34. function menu($selectedYear) {
  35. //SE_Layout::menu();
  36. $year = ($selectedYear)? $selectedYear : date("Y");
  37. ?>
  38. <div class="jumbotron">
  39. <div class="container">
  40. <form class="form-inline" method="POST">
  41. <input type="hidden" name="task" value="zest_year" />
  42. <label for="zest_year">Zestawienie kosztów projektów na podstawie korespondencji:</label>
  43. <div class="input-group date" id="fldZestYear">
  44. <input type="text" name="zest_year" class="form-control" value="" />
  45. <span class="input-group-addon"><span class="glyphicon glyphicon-time"></span></span>
  46. </div>
  47. <button type="submit" id="fldZestYearBtn" class="btn btn-primary" autocomplete="off">
  48. Pokaż
  49. </button>
  50. </form>
  51. </div>
  52. </div>
  53. <script type="text/javascript">
  54. jQuery(document).ready(function () {
  55. jQuery('#fldZestYearBtn').on('click', function () {
  56. jQuery(this).text(jQuery(this).text() + '...').attr('disabled', 'disabled');
  57. jQuery(this).parent().submit();
  58. })
  59. jQuery("#fldZestYear").datetimepicker({
  60. format: "YYYY",
  61. defaultDate: new Date(<?php echo $year; ?>, <?php echo intval(date("m")); ?>, 1),
  62. // minDate: new Date(2014, 11, 1),
  63. // maxDate: "<?php echo date("Y"); ?>"
  64. });
  65. });
  66. </script>
  67. <?php
  68. }
  69. function css() {
  70. ?>
  71. <style type="text/css">
  72. .c { text-align:center; }
  73. .r { text-align:right; }
  74. .zestawienie-kosztow-tbl { border-collapse:collapse; border:1px solid #7EC5FF; }
  75. .zestawienie-kosztow-tbl td { border:1px solid #7EC5FF; }
  76. .zestawienie-kosztow-tbl .p2 { padding:0 2px; }
  77. .zestawienie-kosztow-tbl .nr { color:#7A7A7A; }
  78. .zestawienie-kosztow-tbl thead th { border:1px solid #7EC5FF; }
  79. .zestawienie-kosztow-tbl tbody tr:hover td { background:#cafbfd; }
  80. .row-selected td {background-color:#d8fded;}
  81. .showOnlySelected tr { display:none; }
  82. .showOnlySelected tr.row-selected { display:table-row; }
  83. .cost { padding:0 2px; min-width:30px; text-align:right; }
  84. .cost-only_child { color:#777; }
  85. .cost-only_self { color:red; }
  86. .cost-self_and_child { color:orange; }
  87. /* print table background colors */
  88. table td, table th { -webkit-print-color-adjust:exact; }
  89. table { page-break-after:auto }
  90. tr { page-break-inside:avoid; page-break-after:auto; position:relative; }
  91. td { page-break-inside:avoid; page-break-after:auto; position:relative; }
  92. thead { display:table-header-group }
  93. tfoot { display:table-footer-group }
  94. </style>
  95. <?php
  96. }
  97. function printCostsForYear($projOrder, $costs, $year) {
  98. $months = array();
  99. for ($i = 0; $i < 12; $i++) {
  100. $months[] = $i + 1;
  101. }
  102. $this->css();
  103. //echo'<pre style="width:600px;border:1px solid red;max-height:300px;overflow:auto;">';print_r($costs);echo'</pre>';
  104. ?>
  105. <div class="container">
  106. <div style="float:right;color:#aaa;"><?php echo date("Y-m-d"); ?></div>
  107. <h1>Zestawienie kosztów projektów na rok <?php echo $year; ?></h1>
  108. <table cellspacing="0" cellpadding="0" border="0" id="zestawienie-kosztow-projektow" class="zestawienie-kosztow-tbl">
  109. <thead>
  110. <tr>
  111. <td colspan="3" class="p2">
  112. <span class="pull-left">
  113. <input type="checkbox" onclick="return showHideAll(this);"/> pokaż tylko zaznaczone
  114. </span>
  115. <span class="pull-right">miesiąc</span>
  116. </td>
  117. <?php foreach ($months as $month) { ?>
  118. <th class="c"><?php echo $month; ?></th>
  119. <?php } ?>
  120. </tr>
  121. </thead>
  122. <tbody>
  123. <?php $t = 1; ?>
  124. <?php foreach ($projOrder as $projPath => $projId) : ?>
  125. <?php $projectInfo = $costs[$projId]; ?>
  126. <tr class="row-<?php echo ($t = 1 - $t); ?>"
  127. data-projId="<?php echo $projectInfo->ID_PROJECT; ?>"
  128. data-path="<?php echo $projectInfo->path; ?>">
  129. <td class="p2 r nr">
  130. <input type="checkbox" name="selectedProject" onclick="return selectProject(this);" value="<?php echo $projectInfo->ID_PROJECT; ?>" />
  131. </td>
  132. <td class="p2 l nr"><?php echo $projectInfo->path; ?></td>
  133. <td class="p2" style="max-width:300px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;" title="<?php echo $projectInfo->M_DIST_DESC; ?>"><?php echo $projectInfo->M_DIST_DESC; ?></td>
  134. <?php foreach ($months as $month) : ?>
  135. <?php if (array_key_exists($month, $projectInfo->costsByMonth)) : ?>
  136. <?php $vCost = V::get($month, '', $projectInfo->costsByMonth); ?>
  137. <?php if ($vCost->COST_CHILD > 0) : ?>
  138. <?php $title = "Koszt projektu {$vCost->COST_SELF} / koszt podprojektów {$vCost->COST_CHILD}"; ?>
  139. <?php if ($vCost->COST_SELF > 0) : ?>
  140. <td class="cost cost-self_and_child"><span class="ttip" title="<?php echo $title; ?>"><?php echo $vCost->COST_TOTAL; ?></span></td>
  141. <?php else : ?>
  142. <td class="cost cost-only_child"><span class="ttip" title="<?php echo $title; ?>"><?php echo $vCost->COST_TOTAL; ?></span></td>
  143. <?php endif; ?>
  144. <?php else : ?>
  145. <td class="cost cost-only_self"><?php echo $vCost->COST_TOTAL; ?></td>
  146. <?php endif; ?>
  147. <?php else : ?>
  148. <td style="min-width:30px">&nbsp;</td>
  149. <?php endif; ?>
  150. <?php endforeach; ?>
  151. </tr>
  152. <?php endforeach; ?>
  153. </tbody>
  154. </table>
  155. </div>
  156. <script>
  157. jQuery(document).ready(function(){
  158. jQuery('.ttip').tooltip();
  159. });
  160. function selectProject(n) {
  161. var $n = jQuery(n);
  162. var $p = $n.parent().parent();
  163. if (n.checked) {
  164. $p.addClass('row-selected');
  165. } else {
  166. $p.removeClass('row-selected');
  167. }
  168. markSubProjects($p, $p.data('path'), n.checked);
  169. function markSubProjects($p, path, checked) {
  170. var $nextRow = $p.next('tr'),
  171. nextPath = $nextRow.data('path'),
  172. nextCheckbox = $nextRow.find('input[type="checkbox"]').get(0);
  173. if (0 !== nextPath.indexOf(path)) {
  174. return;
  175. }
  176. if (checked) {
  177. $nextRow.addClass('row-selected');
  178. } else {
  179. $nextRow.removeClass('row-selected');
  180. }
  181. nextCheckbox.checked = checked;
  182. markSubProjects($nextRow, path, checked);
  183. }
  184. }
  185. function showHideAll(n) {
  186. if (n.checked) {
  187. jQuery('#zestawienie-kosztow-projektow').find('tbody').addClass('showOnlySelected');
  188. } else {
  189. jQuery('#zestawienie-kosztow-projektow').find('tbody').removeClass('showOnlySelected');
  190. }
  191. }
  192. </script>
  193. <?php
  194. }
  195. public function getCostsByYear($year) {
  196. $db = DB::getDB();
  197. $costs = array();
  198. $sql = "
  199. select
  200. t.`ID_PROJECT`
  201. , t.`M_DIST_DESC`
  202. , t.`P_ID`
  203. , t.`path`
  204. , t.`MONTH`
  205. , t.`COST_SELF`
  206. , t.`COST_CHILD`
  207. , t.`COST_TOTAL`
  208. , t.`INCOME_SELF`
  209. , t.`INCOME_CHILD`
  210. , t.`INCOME_TOTAL`
  211. from `test_budget_project_synthetics_view` as t
  212. where 1=1
  213. and t.`MONTH` like '{$year}-%'
  214. ";
  215. $res = $db->query($sql);
  216. while ($r = $db->fetch($res)) {
  217. if (!array_key_exists($r->ID_PROJECT, $costs)) {
  218. $projectInfo = new stdClass();
  219. $projectInfo->ID_PROJECT = $r->ID_PROJECT;
  220. $projectInfo->M_DIST_DESC = $r->M_DIST_DESC;
  221. $projectInfo->path = $r->path;
  222. $projectInfo->costsByMonth = array();
  223. $costs[$r->ID_PROJECT] = $projectInfo;
  224. }
  225. $cost = new stdClass();
  226. $cost->MONTH = $r->MONTH;
  227. $cost->COST_SELF = $r->COST_SELF;
  228. $cost->COST_CHILD = $r->COST_CHILD;
  229. $cost->COST_TOTAL = $r->COST_TOTAL;
  230. $cost->INCOME_SELF = $r->INCOME_SELF;
  231. $cost->INCOME_CHILD = $r->INCOME_CHILD;
  232. $cost->INCOME_TOTAL = $r->INCOME_TOTAL;
  233. $monthNum = intval(substr($r->MONTH, 5, 2));
  234. $costs[$r->ID_PROJECT]->costsByMonth[$monthNum] = $cost;
  235. }
  236. return $costs;
  237. }
  238. public function buildProjectTree($costs) {
  239. $projPaths = array();
  240. foreach ($costs as $idProject => $projectInfo) {
  241. $projPaths[$projectInfo->path] = $projectInfo->ID_PROJECT;
  242. }
  243. //echo'<pre style="width:600px;border:1px solid red;max-height:300px;overflow:auto;">projPaths: ';print_r($projPaths);echo'</pre>';
  244. uksort($projPaths, array($this, 'sortPathsCallback'));
  245. //echo'<pre style="width:600px;border:1px solid red;max-height:300px;overflow:auto;">projPaths sorted: ';print_r($projPaths);echo'</pre>';
  246. return $projPaths;
  247. }
  248. public function sortPathsCallback($a, $b) {
  249. $ea = explode('-', $a);
  250. $eb = explode('-', $b);
  251. $la = count($ea);
  252. $lb = count($eb);
  253. $lmin = min($la, $lb);
  254. for ($i = 0; $i < $lmin; $i++) {
  255. if ($ea[$i] < $eb[$i]) {
  256. return -1;
  257. } else if ($ea[$i] > $eb[$i]) {
  258. return 1;
  259. }
  260. }
  261. return $la - $lb;
  262. }
  263. public function installView() {
  264. $sql = "
  265. CREATE VIEW `test_budget_project_analytics_view` AS
  266. select `IN7_DZIENNIK_KORESP`.`ID_PROJECT` AS `ID_PROJECT`
  267. , date_format(`IN7_DZIENNIK_KORESP`.`K_DATA_OTRZYMANEJ_KORESP`,'%Y-%m') AS `MONTH`
  268. , sum(`IN7_DZIENNIK_KORESP`.`COST_VALUE`) AS `COST`
  269. , sum(`IN7_DZIENNIK_KORESP`.`INCOME_VALUE`) AS `INCOME`
  270. , 'SELF' AS `TYPE`
  271. from `IN7_DZIENNIK_KORESP`
  272. where ((`IN7_DZIENNIK_KORESP`.`COST_VALUE` > 0) or (`IN7_DZIENNIK_KORESP`.`INCOME_VALUE` > 0))
  273. group by `IN7_DZIENNIK_KORESP`.`ID_PROJECT`
  274. , date_format(`IN7_DZIENNIK_KORESP`.`K_DATA_OTRZYMANEJ_KORESP`,'%Y-%m')
  275. union
  276. select `p`.`ID` AS `ID_PROJECT`
  277. , date_format(`k`.`K_DATA_OTRZYMANEJ_KORESP`,'%Y-%m') AS `MONTH`
  278. , sum(`k`.`COST_VALUE`) AS `COST`,sum(`k`.`INCOME_VALUE`) AS `INCOME`
  279. , 'CHILD' AS `TYPE`
  280. from (`IN7_MK_BAZA_DYSTRYBUCJI` `p`
  281. join `IN7_DZIENNIK_KORESP` `k` on((((`k`.`COST_VALUE` > 0) or (`k`.`INCOME_VALUE` > 0)) and (`k`.`path` like concat('%-',`p`.`ID`,'-%')))))
  282. group by `p`.`ID`, date_format(`k`.`K_DATA_OTRZYMANEJ_KORESP`, '%Y-%m')
  283. ";
  284. $sql = "
  285. CREATE VIEW `test_budget_project_synthetics_view` AS
  286. select `t1`.`ID_PROJECT` AS `ID_PROJECT`
  287. , `p`.`M_DIST_DESC` AS `M_DIST_DESC`
  288. , `p`.`P_ID` AS `P_ID`
  289. , `p`.`path` AS `path`
  290. , `t1`.`MONTH` AS `MONTH`
  291. , cast(sum(if((`t1`.`TYPE` = 'SELF'),`t1`.`COST`,'0')) as decimal(10,2)) AS `COST_SELF`
  292. , cast(sum(if((`t1`.`TYPE` = 'CHILD'),`t1`.`COST`,'0')) as decimal(10,2)) AS `COST_CHILD`
  293. , sum(`t1`.`COST`) AS `COST_TOTAL`
  294. , cast(sum(if((`t1`.`TYPE` = 'SELF'),`t1`.`INCOME`,'0')) as decimal(10,2)) AS `INCOME_SELF`
  295. , cast(sum(if((`t1`.`TYPE` = 'CHILD'),`t1`.`INCOME`,'0')) as decimal(10,2)) AS `INCOME_CHILD`
  296. , sum(`t1`.`INCOME`) AS `INCOME_TOTAL`
  297. from (`test_budget_project_analytics_view` `t1`
  298. join `IN7_MK_BAZA_DYSTRYBUCJI` `p` on((`t1`.`ID_PROJECT` = `p`.`ID`))
  299. )
  300. group by `t1`.`ID_PROJECT`, `t1`.`MONTH`
  301. ";
  302. }
  303. }