Browse Source

[IMP] Add color to kpi history item. Add dependency with base_external_dbsource to support external databases.

pull/510/head^2
Maxime Chambreuil 12 years ago
parent
commit
8084bf218b
  1. 10
      mgmtsystem_kpi/__openerp__.py
  2. 56
      mgmtsystem_kpi/mgmtsystem_kpi.py
  3. 10
      mgmtsystem_kpi/mgmtsystem_kpi_view.xml

10
mgmtsystem_kpi/__openerp__.py

@ -28,7 +28,8 @@
"complexity" : "normal", "complexity" : "normal",
"description": """ "description": """
This module provides the basis for creating key performance indicators, This module provides the basis for creating key performance indicators,
including static and dynamic thresholds (SQL query or Python code).
including static and dynamic thresholds (SQL query or Python code),
on local and remote data sources.
The module also provides the mecanism to update KPIs automatically. The module also provides the mecanism to update KPIs automatically.
A scheduler is executed every hour and updates the KPI values, based A scheduler is executed every hour and updates the KPI values, based
@ -42,9 +43,12 @@
* color (RGB code like #00FF00 for green, #FFA500 for orange, * color (RGB code like #00FF00 for green, #FFA500 for orange,
#FF0000 for red) #FF0000 for red)
""", """,
"depends" : ['mgmtsystem'],
"depends" : [
'mgmtsystem',
'base_external_dbsource',
],
"data" : [ "data" : [
'mgmtsystem_kpi.xml',
'mgmtsystem_kpi_view.xml',
], ],
"images" : [ "images" : [
"images/kpi_definition.png", "images/kpi_definition.png",

56
mgmtsystem_kpi/mgmtsystem_kpi.py

@ -1,4 +1,4 @@
# -*- encoding: utf-8 -*-
# -*- encoding: utf-8 -*-
############################################################################## ##############################################################################
# #
# OpenERP, Open Source Management Solution # OpenERP, Open Source Management Solution
@ -51,9 +51,14 @@ class mgmtsystem_kpi_threshold_range(osv.osv):
for obj in self.browse(cr, uid, ids): for obj in self.browse(cr, uid, ids):
value = 0 value = 0
if obj.min_type == 'sql':
if obj.min_type == 'local':
cr.execute(obj.min_code) cr.execute(obj.min_code)
value = cr.dictfetchone()['value'] value = cr.dictfetchone()['value']
elif obj.max_type == 'external':
if not dbsource_id:
dbsrc_obj = self.pool.get('base.external.dbsource').browse(cr, uid, min_dbsource_id, context)
res = dbsrc_obj.execute(obj.min_code)
value = res[0]['value']
elif obj.min_type == 'python': elif obj.min_type == 'python':
value = eval(obj.min_code) value = eval(obj.min_code)
else: else:
@ -70,11 +75,16 @@ class mgmtsystem_kpi_threshold_range(osv.osv):
for obj in self.browse(cr, uid, ids): for obj in self.browse(cr, uid, ids):
value = 0 value = 0
if obj.max_type == 'sql':
if obj.max_type == 'local':
cr.execute(obj.max_code) cr.execute(obj.max_code)
value = cr.dictfetchone()['value'] value = cr.dictfetchone()['value']
elif obj.max_type == 'python': elif obj.max_type == 'python':
value = eval(obj.max_code) value = eval(obj.max_code)
elif obj.max_type == 'external':
if not dbsource_id:
dbsrc_obj = self.pool.get('base.external.dbsource').browse(cr, uid, max_dbsource_id, context)
res = dbsrc_obj.execute(obj.max_code)
value = res[0]['value']
else: else:
value = obj.max_fixed_value value = obj.max_fixed_value
@ -84,14 +94,16 @@ class mgmtsystem_kpi_threshold_range(osv.osv):
_columns = { _columns = {
'name': fields.char('Name', size=50, required=True), 'name': fields.char('Name', size=50, required=True),
'min_type': fields.selection((('static','Fixed value'), ('python','Python Code'), ('sql', 'SQL Query')), 'Min Type', required=True),
'min_type': fields.selection((('static','Fixed value'), ('python','Python Code'), ('local', 'SQL - Local DB'), ('external', 'SQL - Externa DB')), 'Min Type', required=True),
'min_value': fields.function(_compute_min_value, string='Minimum', type='float'), 'min_value': fields.function(_compute_min_value, string='Minimum', type='float'),
'min_fixed_value': fields.float('Minimum'), 'min_fixed_value': fields.float('Minimum'),
'min_code': fields.text('Minimum Computation Code'), 'min_code': fields.text('Minimum Computation Code'),
'max_type': fields.selection((('static','Fixed value'), ('python','Python Code'), ('sql', 'SQL Query')), 'Max Type', required=True),
'min_dbsource_id': fields.many2one('base.external.dbsource','External DB Source'),
'max_type': fields.selection((('static','Fixed value'), ('python','Python Code'), ('local', 'SQL - Local DB'), ('external', 'SQL - External DB')), 'Max Type', required=True),
'max_value': fields.function(_compute_max_value, string='Maximum', type='float'), 'max_value': fields.function(_compute_max_value, string='Maximum', type='float'),
'max_fixed_value': fields.float('Maximum'), 'max_fixed_value': fields.float('Maximum'),
'max_code': fields.text('Maximum Computation Code'), 'max_code': fields.text('Maximum Computation Code'),
'max_dbsource_id': fields.many2one('base.external.dbsource','External DB Source'),
'color': fields.char('Color', help='RGB code with #', size=7, required=True), 'color': fields.char('Color', help='RGB code with #', size=7, required=True),
} }
@ -109,6 +121,26 @@ class mgmtsystem_kpi_threshold(osv.osv):
'range_ids': fields.many2many('mgmtsystem.kpi.threshold.range','mgmtsystem_kpi_threshold_range_rel', 'threshold_id', 'range_id', 'Range', required=True), 'range_ids': fields.many2many('mgmtsystem.kpi.threshold.range','mgmtsystem_kpi_threshold_range_rel', 'threshold_id', 'range_id', 'Range', required=True),
} }
def write(self, cr, uid, ids, vals, context=None):
if context is None:
context = {}
# TODO: check if ranges overlap
return super(mgmtsystem_kpi_threshold, self).write(cr, uid, ids, vals, context=context)
def get_color(self, cr, uid, ids, kpi_value, context=None):
if context is None:
context = {}
color = '#FFFFFF'
for obj in self.browse(cr, uid, ids, context):
for range_id in obj.range_ids:
range_obj = self.pool.get('mgmtsystem.kpi.threshold.range').browse(cr, uid, range_id.id, context)
if range_obj.min_value <= kpi_value <= range_obj.max_value:
color = range_obj.color
return color
mgmtsystem_kpi_threshold() mgmtsystem_kpi_threshold()
class mgmtsystem_kpi_history(osv.osv): class mgmtsystem_kpi_history(osv.osv):
@ -123,11 +155,13 @@ class mgmtsystem_kpi_history(osv.osv):
'kpi_id': fields.many2one('mgmtsystem.kpi', 'KPI', required=True), 'kpi_id': fields.many2one('mgmtsystem.kpi', 'KPI', required=True),
'date': fields.datetime('Execution Date', required=True, readonly=True), 'date': fields.datetime('Execution Date', required=True, readonly=True),
'value': fields.float('Value', required=True, readonly=True), 'value': fields.float('Value', required=True, readonly=True),
'color': fields.text('Color', required=True, readonly=True),
} }
_defaults = { _defaults = {
'name': lambda *a: time.strftime('%d %B %Y'), 'name': lambda *a: time.strftime('%d %B %Y'),
'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'), 'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
'color': '#FFFFFF',
} }
_order = "date desc" _order = "date desc"
@ -161,15 +195,22 @@ class mgmtsystem_kpi(osv.osv):
for obj in self.browse(cr, uid, ids): for obj in self.browse(cr, uid, ids):
kpi_value = 0 kpi_value = 0
if obj.kpi_type == 'sql':
if obj.kpi_type == 'local':
cr.execute(obj.kpi_code) cr.execute(obj.kpi_code)
kpi_value = cr.dictfetchone()['value'] kpi_value = cr.dictfetchone()['value']
elif obj.kpi_type == 'external':
if obj.dbsource_id.id:
dbsrc_obj = self.pool.get('base.external.dbsource').browse(cr, uid, obj.dbsource_id.id, context)
res = dbsrc_obj.execute(obj.kpi_code)
kpi_value = res[0]['value']
elif obj.kpi_type == 'python': elif obj.kpi_type == 'python':
kpi_value = eval(obj.kpi_code) kpi_value = eval(obj.kpi_code)
threshold_obj = self.pool.get('mgmtsystem.kpi.threshold').browse(cr, uid, obj.threshold_id.id, context)
values = { values = {
'kpi_id': obj.id, 'kpi_id': obj.id,
'value': kpi_value, 'value': kpi_value,
'color': threshold_obj.get_color(kpi_value),
} }
history_obj = self.pool.get('mgmtsystem.kpi.history') history_obj = self.pool.get('mgmtsystem.kpi.history')
@ -228,7 +269,8 @@ class mgmtsystem_kpi(osv.osv):
'periodicity_uom': fields.selection((('hour','Hour'), ('day','Day'), ('week','Week'), ('month','Month')), 'Periodicity UoM', required=True), 'periodicity_uom': fields.selection((('hour','Hour'), ('day','Day'), ('week','Week'), ('month','Month')), 'Periodicity UoM', required=True),
'next_execution_date': fields.datetime('Next execution date', readonly=True), 'next_execution_date': fields.datetime('Next execution date', readonly=True),
'value': fields.function(_display_last_kpi_value, string='Value', type='float'), 'value': fields.function(_display_last_kpi_value, string='Value', type='float'),
'kpi_type': fields.selection((('sql','SQL'), ('python','Python')),'KPI Computation Type'),
'kpi_type': fields.selection((('python','Python'), ('local','SQL - Local DB'), ('external','SQL - External DB')),'KPI Computation Type'),
'dbsource_id': fields.many2one('base.external.dbsource','External DB Source'),
'kpi_code': fields.text('KPI Code', help='SQL code must return the result as \'value\' (i.e. \'SELECT 5 AS value\').'), 'kpi_code': fields.text('KPI Code', help='SQL code must return the result as \'value\' (i.e. \'SELECT 5 AS value\').'),
'history_ids': fields.one2many('mgmtsystem.kpi.history', 'kpi_id', 'History'), 'history_ids': fields.one2many('mgmtsystem.kpi.history', 'kpi_id', 'History'),
'active': fields.boolean('Active', help="Only active KPIs will be updated by the scheduler based on the periodicity configuration."), 'active': fields.boolean('Active', help="Only active KPIs will be updated by the scheduler based on the periodicity configuration."),

10
mgmtsystem_kpi/mgmtsystem_kpi.xml → mgmtsystem_kpi/mgmtsystem_kpi_view.xml

@ -13,6 +13,7 @@
<field name="name"/> <field name="name"/>
<field name="value" widget="progressbar"/> <field name="value" widget="progressbar"/>
<field name="category_id"/> <field name="category_id"/>
<field name="kpi_type"/>
</tree> </tree>
</field> </field>
</record> </record>
@ -32,6 +33,7 @@
<newline /> <newline />
<group expand="0" string="Group By..."> <group expand="0" string="Group By...">
<filter string="Category" context="{'group_by':'category_id'}"/> <filter string="Category" context="{'group_by':'category_id'}"/>
<filter string="Type" context="{'group_by':'kpi_type'}"/>
</group> </group>
</search> </search>
</field> </field>
@ -64,6 +66,7 @@
<separator string="KPI Computation" colspan="6"/> <separator string="KPI Computation" colspan="6"/>
<newline/> <newline/>
<field name="kpi_type" colspan="2"/> <field name="kpi_type" colspan="2"/>
<field name="dbsource_id" colspan="2" attrs="{'invisible' : [('kpi_type', '!=', 'external')]}"/>
<newline/> <newline/>
<field name="kpi_code" colspan="6"/> <field name="kpi_code" colspan="6"/>
</group> </group>
@ -103,6 +106,7 @@
<field name="name"/> <field name="name"/>
<field name="date"/> <field name="date"/>
<field name="value"/> <field name="value"/>
<field name="color"/>
</tree> </tree>
</field> </field>
</record> </record>
@ -233,15 +237,17 @@
<newline/> <newline/>
<field name="min_type"/> <field name="min_type"/>
<field name="min_fixed_value" attrs="{'invisible' : [('min_type', '!=', 'static')]}"/> <field name="min_fixed_value" attrs="{'invisible' : [('min_type', '!=', 'static')]}"/>
<field name="min_dbsource_id" attrs="{'invisible' : [('min_type', '!=', 'external')]}"/>
<newline/> <newline/>
<field name="min_code" colspan="4" attrs="{'invisible' : [('min_type', 'NOT IN', ('sql','python'))]}"/>
<field name="min_code" colspan="4" attrs="{'invisible' : [('min_type', 'NOT IN', ('local','external','python'))]}"/>
<newline/> <newline/>
<separator string="Maximum" colspan="4"/> <separator string="Maximum" colspan="4"/>
<newline/> <newline/>
<field name="max_type"/> <field name="max_type"/>
<field name="max_fixed_value" attrs="{'invisible' : [('max_type', '!=', 'static')]}"/> <field name="max_fixed_value" attrs="{'invisible' : [('max_type', '!=', 'static')]}"/>
<field name="max_dbsource_id" attrs="{'invisible' : [('max_type', '!=', 'external')]}"/>
<newline/> <newline/>
<field name="max_code" colspan="4" attrs="{'invisible' : [('max_type', 'NOT IN', ('sql','python'))]}"/>
<field name="max_code" colspan="4" attrs="{'invisible' : [('max_type', 'NOT IN', ('local','external','python'))]}"/>
</form> </form>
</field> </field>
</record> </record>
Loading…
Cancel
Save