OCA reporting engine fork for dev and update.
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.

110 lines
3.4 KiB

  1. # Copyright 2020 Creu Blanca
  2. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
  3. from odoo import api, fields, models
  4. import ast
  5. class KpiKpi(models.Model):
  6. _name = "kpi.kpi"
  7. _description = "Kpi Kpi"
  8. name = fields.Char(required=True)
  9. active = fields.Boolean(default=True)
  10. cron_id = fields.Many2one("ir.cron", readonly=True, copy=False)
  11. computation_method = fields.Selection(
  12. [("function", "Function")], required=True
  13. )
  14. value = fields.Serialized()
  15. dashboard_item_ids = fields.One2many("kpi.dashboard.item", inverse_name="kpi_id")
  16. model_id = fields.Many2one("ir.model",)
  17. function = fields.Char()
  18. args = fields.Char()
  19. kwargs = fields.Char()
  20. widget = fields.Selection(
  21. [("number", "Number"), ("meter", "Meter"), ("graph", "Graph")],
  22. required=True,
  23. default="number",
  24. )
  25. value_last_update = fields.Datetime(readonly=True)
  26. prefix = fields.Char()
  27. suffix = fields.Char()
  28. action_ids = fields.One2many(
  29. "kpi.kpi.action",
  30. inverse_name='kpi_id',
  31. help="Actions that can be opened from the KPI"
  32. )
  33. def _cron_vals(self):
  34. return {
  35. "name": self.name,
  36. "model_id": self.env.ref("kpi_dashboard.model_kpi_kpi").id,
  37. "interval_number": 1,
  38. "interval_type": "hours",
  39. "state": "code",
  40. "code": "model.browse(%s).compute()" % self.id,
  41. "active": True,
  42. }
  43. def compute(self):
  44. for record in self:
  45. record._compute()
  46. return True
  47. def _compute(self):
  48. self.write(
  49. {
  50. "value": getattr(
  51. self, "_compute_value_%s" % self.computation_method
  52. )()
  53. }
  54. )
  55. notifications = []
  56. for dashboard_item in self.dashboard_item_ids:
  57. channel = "kpi_dashboard_%s" % dashboard_item.dashboard_id.id
  58. notifications.append([channel, dashboard_item._read_dashboard()])
  59. if notifications:
  60. self.env["bus.bus"].sendmany(notifications)
  61. def _compute_value_function(self):
  62. obj = self
  63. if self.model_id:
  64. obj = self.env[self.model_id.model]
  65. args = ast.literal_eval(self.args or "[]")
  66. kwargs = ast.literal_eval(self.kwargs or "{}")
  67. return getattr(obj, self.function)(*args, **kwargs)
  68. def generate_cron(self):
  69. self.ensure_one()
  70. self.cron_id = self.env["ir.cron"].create(self._cron_vals())
  71. @api.multi
  72. def write(self, vals):
  73. if "value" in vals:
  74. vals["value_last_update"] = fields.Datetime.now()
  75. return super().write(vals)
  76. class KpiKpiAction(models.Model):
  77. _name = 'kpi.kpi.action'
  78. _description = 'KPI action'
  79. kpi_id = fields.Many2one('kpi.kpi', required=True, ondelete='cascade')
  80. action = fields.Reference(
  81. selection=[('ir.actions.report', 'ir.actions.report'),
  82. ('ir.actions.act_window', 'ir.actions.act_window'),
  83. ('ir.actions.act_url', 'ir.actions.act_url'),
  84. ('ir.actions.server', 'ir.actions.server'),
  85. ('ir.actions.client', 'ir.actions.client')],
  86. required=True,
  87. )
  88. def read_dashboard(self):
  89. result = []
  90. for r in self:
  91. result.append({
  92. 'id': r.action.id,
  93. 'type': r.action._name,
  94. 'name': r.action.name
  95. })
  96. return result