diff --git a/olap.php b/olap.php index cae41c5..1eb4503 100644 --- a/olap.php +++ b/olap.php @@ -68,6 +68,7 @@ class OLAP 'max' => array('name' => 'Максимум', 'sql' => 'MAX($)'), 'stddev' => array('name' => 'Дисперсия', 'sql' => 'STDDEV($)'), 'n_uniq' => array('name' => 'Количество уникальных', 'sql' => 'COUNT(DISTINCT $)'), + 'sum_rnd' => array('name' => 'Сумма округлённая', 'sql' => 'ROUND(SUM($))'), ); static $group_types = array( 'tables' => 'Несколько таблиц', @@ -80,7 +81,7 @@ class OLAP var $request; var $current_srcid, $current_src; var $time_start, $nfields, $build, $csv; - var $where, $where_nosql, $group_fields, $cell; + var $tables, $where, $where_nosql, $group_fields, $cell; var $is_html_format = true; var $add_spanned; var $graph_scale = 600; /* пикселей */ @@ -161,10 +162,15 @@ class OLAP foreach ($v['options'] as &$o) $v['options_hash'][$o['id']] = $o['name']; } + if (is_object($v['sql']) && get_class($v['sql']) === 'Closure') + { + $v['sql'] = $v['sql']($this); + } } unset($v); // читаем параметры запроса + $this->tables = array(); $this->where = array(); $this->where_nosql = array(); $this->group_fields = array(); @@ -187,6 +193,8 @@ class OLAP } if (!$fd || !strlen($v)) continue; + if (!empty($fd['join'])) + $this->tables += $fd['join']; $this->request[$k] = $v; if (!empty($fd['is_time'])) $v = VMXTemplate::timestamp($v, $this->current_src['fielddescs'][$f]['format']); @@ -388,15 +396,16 @@ class OLAP $group_fields = $output[0]['group_by']; $fields = array(); $group_by = array(); + $tables = array(); foreach ($group_fields as $i => &$v) { - $v['sql'] = $this->sql_trans_field($v['field'], $v['func']); + $v['sql'] = $this->sql_trans_field($v['field'], $v['func'], $tables); $v['keys'] = array(); $fields[] = $v['sql'].' f'.$i; $group_by[] = $v['sql']; } - $sql = $this->sql_trans_field($field, $func); + $sql = $this->sql_trans_field($field, $func, $tables); $fields[] = str_replace('$', $sql, self::$aggregates[$aggr]['sql']).' c'; $code = 'while($r = $result->fetch_assoc()) { '; @@ -410,7 +419,7 @@ class OLAP $code .= '}'; $result = $this->mysql()->select( - $this->current_src['tables'], $fields, + $this->current_src['tables'] + $this->tables + $tables, $fields, array_merge($this->current_src['where'], $this->where), array('GROUP BY' => $group_by), MS_RESULT @@ -876,9 +885,11 @@ class OLAP return $c; } - function sql_trans_field($field, $func) + function sql_trans_field($field, $func, &$tables) { $fd = &$this->current_src['fielddescs'][$field]; + if (!empty($fd['join'])) + $tables += $fd['join']; if (empty($field) && $field !== '0') $sql = '1'; else @@ -987,6 +998,18 @@ class OLAP $aggr += $value; } + // Сумма округлённая - обновление + static function aggr_update_sum_rnd(&$aggr, &$value) + { + $aggr += $value; + } + + // Сумма округлённая - обновление + static function aggr_finish_sum_rnd(&$aggr) + { + $aggr = round($aggr); + } + // Среднее - обновление static function aggr_update_avg(&$aggr, &$value) { diff --git a/olap_config.php b/olap_config.php index 411e152..7dc578c 100644 --- a/olap_config.php +++ b/olap_config.php @@ -1,10 +1,5 @@ 0)); -} - OLAP::$sources = array( 'mediawiki_history' => array( 'id' => 'mediawiki_history', @@ -36,7 +31,10 @@ OLAP::$sources = array( ), 'tag' => array( 'name' => 'Тег', - 'options' => 'v2tags_get_tags', + 'options' => function($olap) + { + return $olap->mysql()->select('tags', 'id, name', array('type' => 0)); + } ), ), ), @@ -76,15 +74,41 @@ OLAP::$sources = array( 'bugzilla' => array( 'id' => 'bugzilla', 'name' => 'Время Bugzilla', - 'tables' => array('t' => 'bugs3.longdescs', 'p' => 'bugs3.profiles'), + 'tables' => array( + 't' => 'bugs3.longdescs', + 'p' => [ 'INNER', 'bugs3.profiles', [ 'p.userid=t.who' ] ], + 'b' => [ 'INNER', 'bugs3.bugs', [ 'b.bug_id=t.bug_id' ] ], + 'pr' => [ 'INNER', 'bugs3.products', [ 'pr.id=b.product_id' ] ], + 'c' => [ 'INNER', 'bugs3.components', [ 'c.id=b.component_id' ] ], + 'bt' => [ 'LEFT', 'bugs3.cf_bug_type', [ 'bt.id=b.cf_bug_type' ] ], + ), 'fields' => 'p.login_name, t.bug_when, t.work_time', - 'where' => array('t.who=p.userid'), + 'where' => array( + 'p.login_name like "%@custis.ru"', + ), 'fielddescs' => array( - 'login_name' => array( - 'name' => 'Сотрудник', + 'group' => array( + 'name' => 'Группа', + 'join' => [ + 'ug' => [ 'INNER', 'bugs3.user_group_map', [ 'ug.user_id=t.who', 'ug.isbless=0' ] ], + 'g' => [ 'INNER', 'bugs3.groups', [ 'g.id=ug.group_id' ] ], + ], + 'sql' => 'g.id', + 'options' => function($olap) + { + return $olap->mysql()->select('bugs3.groups', 'id, name', array('isbuggroup=1'), array('ORDER BY' => 'name')); + } + ), + 'who' => array( + 'name' => 'Логин', + 'sql' => 'p.login_name', +/* 'options' => function($olap) + { + return $olap->mysql()->select('bugs3.profiles', 'userid id, login_name name', array('login_name like "%@custis.ru" and realname not like \'Группа%\'')); + }*/ ), 'bug_when' => array( - 'name' => 'Момент', + 'name' => 'Момент времени', 'le_ge' => true, 'is_time' => true, 'format' => TS_DB, @@ -93,6 +117,40 @@ OLAP::$sources = array( 'name' => 'Часы', 'le_ge' => true, ), + 'bug_id' => array( + 'name' => 'ID бага', + 'sql' => 't.bug_id', + 'le_ge' => true, + ), + 'product' => array( + 'name' => 'Продукт', + 'sql' => 'pr.name', + ), + 'component' => array( + 'name' => 'Компонент', + 'sql' => 'c.name', + ), + 'cf_bug_type' => array( + 'name' => 'Тип бага', + 'sql' => 'bt.value', + ), + 'da_type' => array( + 'name' => 'Время ДА', + 'sql' => function($olap) + { + $arch_product = $olap->mysql()->select('bugs3.products', 'id', [ 'name' => '-Arch_Other' ], NULL, MS_VALUE); + $arch_components = $olap->mysql()->select('bugs3.components', 'id', [ 'name LIKE ?' => 'arch%' ], NULL, MS_COL); + $arch_bug_types = $olap->mysql()->select('bugs3.cf_bug_type', 'id', [ 'value LIKE ?' => 'arch%' ], NULL, MS_COL); + return '(CASE'. + ($arch_product ? ' WHEN b.product_id='.$arch_product.' THEN \'ДА\'' : ''). + ($arch_components || $arch_bug_types ? ' WHEN '. + ($arch_components ? 'b.component_id IN ('.implode(',', $arch_components).')' : ''). + ($arch_components && $arch_bug_types ? ' OR ' : ''). + ($arch_bug_types ? 'b.cf_bug_type IN ('.implode(',', $arch_bug_types).')' : ''). + ' THEN \'Арх\'' : ''). + ' ELSE \'Другое\' END)'; + } + ), ), ), ); diff --git a/templates/default/admin_header.tpl b/templates/default/admin_header.tpl index 65b2abc..e453010 100644 --- a/templates/default/admin_header.tpl +++ b/templates/default/admin_header.tpl @@ -19,7 +19,7 @@ p { margin: 4px 0; } .themes li { padding: 0; display: inline; margin-right: 8px; } .simpletable, .simpletable td { border: 1px solid black; } .simpletable { border-collapse: collapse; } -.simpletable.center td { text-align: center; } +.simpletable.center td { text-align: right; } .simpletable td ul { padding: 0 6px 0 20px; } .simpletable td li { text-align: left; } .simpletable th { padding: 3px 8px; background-color: #a0a0a0; vertical-align: top; }