You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

245 lines
8.8 KiB

13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
  1. # -*- encoding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # OpenERP, Open Source Management Solution
  5. # Copyright (C) 2012 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
  6. #
  7. # This program is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as
  9. # published by the Free Software Foundation, either version 3 of the
  10. # License, or (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. #
  20. ##############################################################################
  21. from dateutil.relativedelta import relativedelta
  22. from datetime import datetime
  23. from osv import fields, osv
  24. import time
  25. class mgmtsystem_kpi_category(osv.osv):
  26. """
  27. KPI Category
  28. """
  29. _name = "mgmtsystem.kpi.category"
  30. _description = "KPI Category"
  31. _columns = {
  32. 'name': fields.char('Name', size=50, required=True),
  33. 'description': fields.text('Description')
  34. }
  35. mgmtsystem_kpi_category()
  36. class mgmtsystem_kpi_threshold_range(osv.osv):
  37. """
  38. KPI Threshold Range
  39. """
  40. _name = "mgmtsystem.kpi.threshold.range"
  41. _description = "KPI Threshold Range"
  42. def _compute_min_value(self, cr, uid, ids, field_name, arg, context=None):
  43. if context is None:
  44. context = {}
  45. result = {}
  46. for obj in self.browse(cr, uid, ids):
  47. value = 0
  48. if obj.min_type == 'sql':
  49. cr.execute(obj.min_code)
  50. value = cr.dictfetchone()['value']
  51. elif obj.min_type == 'python':
  52. value = eval(obj.min_code)
  53. else:
  54. value = obj.min_fixed_value
  55. result[obj.id] = value
  56. return result
  57. def _compute_max_value(self, cr, uid, ids, field_name, arg, context=None):
  58. if context is None:
  59. context = {}
  60. result = {}
  61. for obj in self.browse(cr, uid, ids):
  62. value = 0
  63. if obj.max_type == 'sql':
  64. cr.execute(obj.max_code)
  65. value = cr.dictfetchone()['value']
  66. elif obj.max_type == 'python':
  67. value = eval(obj.max_code)
  68. else:
  69. value = obj.max_fixed_value
  70. result[obj.id] = value
  71. return result
  72. _columns = {
  73. 'name': fields.char('Name', size=50, required=True),
  74. 'min_type': fields.selection((('static','Fixed value'), ('python','Python Code'), ('sql', 'SQL Query')), 'Min Type', required=True),
  75. 'min_value': fields.function(_compute_min_value, string='Minimum', type='float'),
  76. 'min_fixed_value': fields.float('Minimum'),
  77. 'min_code': fields.text('Minimum Computation Code'),
  78. 'max_type': fields.selection((('static','Fixed value'), ('python','Python Code'), ('sql', 'SQL Query')), 'Max Type', required=True),
  79. 'max_value': fields.function(_compute_max_value, string='Maximum', type='float'),
  80. 'max_fixed_value': fields.float('Maximum'),
  81. 'max_code': fields.text('Maximum Computation Code'),
  82. 'color': fields.char('Color', help='RGB code with #', size=7, required=True),
  83. }
  84. mgmtsystem_kpi_threshold_range()
  85. class mgmtsystem_kpi_threshold(osv.osv):
  86. """
  87. KPI Threshold
  88. """
  89. _name = "mgmtsystem.kpi.threshold"
  90. _description = "KPI Threshold"
  91. _columns = {
  92. 'name': fields.char('Name', size=50, required=True),
  93. 'range_ids': fields.many2many('mgmtsystem.kpi.threshold.range','mgmtsystem_kpi_threshold_range_rel', 'threshold_id', 'range_id', 'Range', required=True),
  94. }
  95. mgmtsystem_kpi_threshold()
  96. class mgmtsystem_kpi_history(osv.osv):
  97. """
  98. History of the KPI
  99. """
  100. _name = "mgmtsystem.kpi.history"
  101. _description = "History of the KPI"
  102. _columns = {
  103. 'name': fields.char('Name', size=150, required=True),
  104. 'kpi_id': fields.many2one('mgmtsystem.kpi', 'KPI', required=True),
  105. 'date': fields.datetime('Execution Date', required=True, readonly=True),
  106. 'value': fields.float('Value', required=True, readonly=True),
  107. }
  108. _defaults = {
  109. 'name': lambda *a: time.strftime('%d %B %Y'),
  110. 'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
  111. }
  112. _order = "date desc"
  113. mgmtsystem_kpi_threshold()
  114. class mgmtsystem_kpi(osv.osv):
  115. """
  116. Key Performance Indicators
  117. """
  118. _name = "mgmtsystem.kpi"
  119. _description = "Key Performance Indicator"
  120. def _display_last_kpi_value(self, cr, uid, ids, field_name, arg, context=None):
  121. if context is None:
  122. context = {}
  123. result = {}
  124. for obj in self.browse(cr, uid, ids):
  125. if obj.history_ids:
  126. result[obj.id] = obj.history_ids[0].value
  127. else:
  128. result[obj.id] = 0
  129. return result
  130. def compute_kpi_value(self, cr, uid, ids, context=None):
  131. if context is None:
  132. context = {}
  133. kpi_value = 0
  134. for obj in self.browse(cr, uid, ids):
  135. kpi_value = 0
  136. if obj.kpi_type == 'sql':
  137. cr.execute(obj.kpi_code)
  138. kpi_value = cr.dictfetchone()['value']
  139. elif obj.kpi_type == 'python':
  140. kpi_value = eval(obj.kpi_code)
  141. values = {
  142. 'kpi_id': obj.id,
  143. 'value': kpi_value,
  144. }
  145. history_obj = self.pool.get('mgmtsystem.kpi.history')
  146. history_id = history_obj.create(cr, uid, values, context=context)
  147. obj.history_ids.append(history_id)
  148. return True
  149. def update_next_execution_date(self, cr, uid, ids, context=None):
  150. if context is None:
  151. context = {}
  152. for obj in self.browse(cr, uid, ids):
  153. if obj.periodicity_uom == 'hour':
  154. new_date = datetime.now() + relativedelta( hours = +obj.periodicity )
  155. elif obj.periodicity_uom == 'day':
  156. new_date = datetime.now() + relativedelta( days = +obj.periodicity )
  157. elif obj.periodicity_uom == 'week':
  158. new_date = datetime.now() + relativedelta( weeks = +obj.periodicity )
  159. elif obj.periodicity_uom == 'month':
  160. new_date = datetime.now() + relativedelta( months = +obj.periodicity )
  161. values = {
  162. 'next_execution_date': new_date.strftime('%Y-%m-%d %H:%M:%S'),
  163. }
  164. obj.write(values)
  165. return True
  166. # Method called by the scheduler
  167. def update_kpi_value(self, cr, uid, ids=None, context=None):
  168. if context is None:
  169. context = {}
  170. if not ids:
  171. filters = ['&', '|', ('active', '=', True), ('next_execution_date', '<=', datetime.now().strftime('%Y-%m-%d %H:%M:%S')), ('next_execution_date', '=', False)]
  172. if 'filters' in context:
  173. filters.extend(context['filters'])
  174. ids = self.search(cr, uid, filters, context=context)
  175. res = None
  176. try:
  177. res = self.compute_kpi_value(cr, uid, ids, context=context)
  178. self.update_next_execution_date(cr, uid, ids, context=context)
  179. except Exception:
  180. _logger.exception("Failed updating KPI values")
  181. return res
  182. _columns = {
  183. 'name': fields.char('Name', size=50, required=True),
  184. 'description': fields.text('Description'),
  185. 'category_id': fields.many2one('mgmtsystem.kpi.category','Category', required=True),
  186. 'threshold_id': fields.many2one('mgmtsystem.kpi.threshold','Threshold', required=True),
  187. 'periodicity': fields.integer('Periodicity'),
  188. 'periodicity_uom': fields.selection((('hour','Hour'), ('day','Day'), ('week','Week'), ('month','Month')), 'Periodicity UoM', required=True),
  189. 'next_execution_date': fields.datetime('Next execution date', readonly=True),
  190. 'value': fields.function(_display_last_kpi_value, string='Value', type='float'),
  191. 'kpi_type': fields.selection((('sql','SQL'), ('python','Python')),'KPI Computation Type'),
  192. 'kpi_code': fields.text('KPI Code', help='SQL code must return the result as \'value\' (i.e. \'SELECT 5 AS value\').'),
  193. 'history_ids': fields.one2many('mgmtsystem.kpi.history', 'kpi_id', 'History'),
  194. 'active': fields.boolean('Active', help="Only active KPIs will be updated by the scheduler based on the periodicity configuration."),
  195. }
  196. _defaults = {
  197. 'active': True,
  198. 'periodicity': 1,
  199. 'periodicity_uom': 'day',
  200. }
  201. mgmtsystem_kpi()
  202. # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: