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.

161 lines
5.1 KiB

  1. # -*- coding: utf-8 -*-
  2. # Copyright 2012 - Now Savoir-faire Linux <https://www.savoirfairelinux.com/>
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
  4. from openerp import fields, models, api
  5. from openerp.tools.safe_eval import safe_eval
  6. import re
  7. def is_one_value(result):
  8. # check if sql query returns only one value
  9. if type(result) is dict and 'value' in result.dictfetchone():
  10. return True
  11. elif type(result) is list and 'value' in result[0]:
  12. return True
  13. else:
  14. return False
  15. RE_SELECT_QUERY = re.compile('.*(' + '|'.join((
  16. 'INSERT',
  17. 'UPDATE',
  18. 'DELETE',
  19. 'CREATE',
  20. 'ALTER',
  21. 'DROP',
  22. 'GRANT',
  23. 'REVOKE',
  24. 'INDEX',
  25. )) + ')')
  26. def is_sql_or_ddl_statement(query):
  27. """Check if sql query is a SELECT statement"""
  28. return not RE_SELECT_QUERY.match(query.upper())
  29. class KPIThresholdRange(models.Model):
  30. """
  31. KPI Threshold Range
  32. """
  33. _name = "kpi.threshold.range"
  34. _description = "KPI Threshold Range"
  35. name = fields.Char('Name', size=50, required=True)
  36. valid = fields.Boolean(string='Valid', required=True,
  37. compute="_compute_is_valid_range", default=True)
  38. invalid_message = fields.Char(string='Message', size=100,
  39. compute="_compute_generate_invalid_message")
  40. min_type = fields.Selection((
  41. ('static', 'Fixed value'),
  42. ('python', 'Python Code'),
  43. ('local', 'SQL - Local DB'),
  44. ('external', 'SQL - Externa DB'),
  45. ), 'Min Type', required=True)
  46. min_value = fields.Float(string='Minimum', compute="_compute_min_value")
  47. min_fixed_value = fields.Float('Minimum')
  48. min_code = fields.Text('Minimum Computation Code')
  49. min_dbsource_id = fields.Many2one(
  50. 'base.external.dbsource',
  51. 'External DB Source',
  52. )
  53. max_type = fields.Selection((
  54. ('static', 'Fixed value'),
  55. ('python', 'Python Code'),
  56. ('local', 'SQL - Local DB'),
  57. ('external', 'SQL - External DB'),
  58. ), 'Max Type', required=True)
  59. max_value = fields.Float(string='Maximum', compute="_compute_max_value")
  60. max_fixed_value = fields.Float('Maximum')
  61. max_code = fields.Text('Maximum Computation Code')
  62. max_dbsource_id = fields.Many2one(
  63. 'base.external.dbsource',
  64. 'External DB Source',
  65. )
  66. color = fields.Char(
  67. string="Color",
  68. help="Choose your color"
  69. )
  70. threshold_ids = fields.Many2many(
  71. 'kpi.threshold',
  72. 'kpi_threshold_range_rel',
  73. 'range_id',
  74. 'threshold_id',
  75. 'Thresholds',
  76. )
  77. company_id = fields.Many2one(
  78. 'res.company', 'Company',
  79. default=lambda self: self.env.user.company_id.id)
  80. @api.multi
  81. def _compute_min_value(self):
  82. result = {}
  83. for obj in self:
  84. value = None
  85. if obj.min_type == 'local' and is_sql_or_ddl_statement(
  86. obj.min_code):
  87. self.env.cr.execute(obj.min_code)
  88. dic = self.env.cr.dictfetchall()
  89. if is_one_value(dic):
  90. value = dic[0]['value']
  91. elif (obj.min_type == 'external' and obj.min_dbsource_id.id and
  92. is_sql_or_ddl_statement(obj.min_code)):
  93. dbsrc_obj = obj.min_dbsource_id
  94. res = dbsrc_obj.execute(obj.min_code)
  95. if is_one_value(res):
  96. value = res[0]['value']
  97. elif obj.min_type == 'python':
  98. value = safe_eval(obj.min_code)
  99. else:
  100. value = obj.min_fixed_value
  101. obj.min_value = value
  102. return result
  103. @api.multi
  104. def _compute_max_value(self):
  105. result = {}
  106. for obj in self:
  107. value = None
  108. if obj.max_type == 'local' and is_sql_or_ddl_statement(
  109. obj.max_code):
  110. self.env.cr.execute(obj.max_code)
  111. dic = self.env.cr.dictfetchall()
  112. if is_one_value(dic):
  113. value = dic[0]['value']
  114. elif obj.max_type == 'python':
  115. value = safe_eval(obj.max_code)
  116. elif (obj.max_type == 'external' and obj.max_dbsource_id.id and
  117. is_sql_or_ddl_statement(obj.max_code)):
  118. dbsrc_obj = obj.max_dbsource_id
  119. res = dbsrc_obj.execute(obj.max_code)
  120. if is_one_value(res):
  121. value = res[0]['value']
  122. else:
  123. value = obj.max_fixed_value
  124. obj.max_value = value
  125. return result
  126. @api.multi
  127. def _compute_is_valid_range(self):
  128. result = {}
  129. for obj in self:
  130. if obj.max_value < obj.min_value:
  131. obj.valid = False
  132. else:
  133. obj.valid = True
  134. return result
  135. @api.multi
  136. def _compute_generate_invalid_message(self):
  137. result = {}
  138. for obj in self:
  139. if obj.valid:
  140. obj.invalid_message = ""
  141. else:
  142. obj.invalid_message = (
  143. "Minimum value is greater than the maximum "
  144. "value! Please adjust them.")
  145. return result