Browse Source

Merge PR #393 into 12.0

Signed-off-by LoisRForgeFlow
12.0
OCA-git-bot 5 years ago
parent
commit
977d9328d7
  1. 12
      kpi_dashboard/README.rst
  2. 2
      kpi_dashboard/__manifest__.py
  3. 52
      kpi_dashboard/demo/demo_dashboard.xml
  4. 35
      kpi_dashboard/models/kpi_kpi.py
  5. 14
      kpi_dashboard/readme/CONFIGURE.rst
  6. 38
      kpi_dashboard/static/description/index.html
  7. 1
      kpi_dashboard/tests/__init__.py
  8. 59
      kpi_dashboard/tests/test_formula.py
  9. 38
      kpi_dashboard/tests/test_kpi_dashboard.py
  10. 5
      kpi_dashboard/views/kpi_kpi.xml
  11. 73
      kpi_dashboard_test/README.rst
  12. 1
      kpi_dashboard_test/__init__.py
  13. 14
      kpi_dashboard_test/__manifest__.py
  14. 20
      kpi_dashboard_test/i18n/kpi_dashboard_test.pot
  15. 1
      kpi_dashboard_test/models/__init__.py
  16. 48
      kpi_dashboard_test/models/kpi_kpi.py
  17. 1
      kpi_dashboard_test/readme/CONTRIBUTORS.rst
  18. 1
      kpi_dashboard_test/readme/DESCRIPTION.rst
  19. BIN
      kpi_dashboard_test/static/description/icon.png
  20. 419
      kpi_dashboard_test/static/description/index.html

12
kpi_dashboard/README.rst

@ -45,6 +45,18 @@ Configure KPIs
#. Meter: result must contain `value`, `min` and `max` #. Meter: result must contain `value`, `min` and `max`
#. Graph: result must contain a list on `graphs` containing `values`, `title` and `key` #. Graph: result must contain a list on `graphs` containing `values`, `title` and `key`
#. In order to compute the KPI you can use a predefined function from a model or
use the code to directly compute it.
Using KPI with code
~~~~~~~~~~~~~~~~~~~
Define the code directly on the code field. You can use:
* `self` and `model` as the kpi element
* The script should create a variable called `result` as a dictionary that
will be stored as the value
Configure dashboards Configure dashboards
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~

2
kpi_dashboard/__manifest__.py

@ -20,4 +20,6 @@
"views/kpi_kpi.xml", "views/kpi_kpi.xml",
"views/kpi_dashboard.xml", "views/kpi_dashboard.xml",
], ],
"demo": ["demo/demo_dashboard.xml"],
"maintainers": ["etobella"],
} }

52
kpi_dashboard_test/demo/demo_dashboard.xml → kpi_dashboard/demo/demo_dashboard.xml

@ -11,17 +11,21 @@
<record id="widget_number_01" model="kpi.kpi"> <record id="widget_number_01" model="kpi.kpi">
<field name="name">Number 01</field> <field name="name">Number 01</field>
<field name="prefix">$</field> <field name="prefix">$</field>
<field name="computation_method">function</field>
<field name="computation_method">code</field>
<field name="widget">number</field> <field name="widget">number</field>
<field name="function">test_demo_number</field>
<field name="code">
result = {"value": 10000,"previous": 12000}
</field>
</record> </record>
<record id="widget_number_02" model="kpi.kpi"> <record id="widget_number_02" model="kpi.kpi">
<field name="name">Number 02</field> <field name="name">Number 02</field>
<field name="suffix"></field> <field name="suffix"></field>
<field name="computation_method">function</field>
<field name="computation_method">code</field>
<field name="widget">number</field> <field name="widget">number</field>
<field name="function">test_demo_number</field>
<field name="code">
result = {"value": 12000,"previous": 10000}
</field>
</record> </record>
<function model="kpi.kpi" name="compute" <function model="kpi.kpi" name="compute"
@ -30,17 +34,21 @@
<record id="widget_meter_01" model="kpi.kpi"> <record id="widget_meter_01" model="kpi.kpi">
<field name="name">Meter 01</field> <field name="name">Meter 01</field>
<field name="suffix"></field> <field name="suffix"></field>
<field name="computation_method">function</field>
<field name="computation_method">code</field>
<field name="widget">meter</field> <field name="widget">meter</field>
<field name="function">test_demo_meter</field>
<field name="code">
result = {"min": 0, "max": 100, "value": 90}
</field>
</record> </record>
<record id="widget_meter_02" model="kpi.kpi"> <record id="widget_meter_02" model="kpi.kpi">
<field name="name">Meter 02</field> <field name="name">Meter 02</field>
<field name="prefix">$</field> <field name="prefix">$</field>
<field name="computation_method">function</field>
<field name="computation_method">code</field>
<field name="widget">meter</field> <field name="widget">meter</field>
<field name="function">test_demo_meter</field>
<field name="code">
result = {"min": 0, "max": 100, "value": 40}
</field>
</record> </record>
<function model="kpi.kpi" name="compute" <function model="kpi.kpi" name="compute"
@ -48,15 +56,37 @@
<record id="widget_graph" model="kpi.kpi"> <record id="widget_graph" model="kpi.kpi">
<field name="name">Graph</field> <field name="name">Graph</field>
<field name="computation_method">function</field>
<field name="computation_method">code</field>
<field name="widget">graph</field> <field name="widget">graph</field>
<field name="function">test_demo_graph</field>
<field name="code">
result = {"graphs": [
{
"values": [
{"x": i, "y": i * 1000}
for i in range(1, 12)
],
"title": "Current Year",
"key": "current",
"area": True,
"color": "ffffff",
},
{
"values": [
{"x": i, "y": 1000 * (12-i)}
for i in range(1, 12)
],
"title": "Previous Year",
"key": "previous",
"area": True,
"color": "000000",
},
]}
</field>
</record> </record>
<function model="kpi.kpi" name="compute" <function model="kpi.kpi" name="compute"
eval="[[ref('widget_graph')]]"/> eval="[[ref('widget_graph')]]"/>
<record id="dashboard_widget_text" model="kpi.dashboard.item"> <record id="dashboard_widget_text" model="kpi.dashboard.item">
<field name="name">Dashboard title</field> <field name="name">Dashboard title</field>
<field name="dashboard_id" ref="demo_dashboard"/> <field name="dashboard_id" ref="demo_dashboard"/>

35
kpi_dashboard/models/kpi_kpi.py

@ -1,8 +1,11 @@
# Copyright 2020 Creu Blanca # Copyright 2020 Creu Blanca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
import ast import ast
from odoo.tools.safe_eval import safe_eval
import re
class KpiKpi(models.Model): class KpiKpi(models.Model):
@ -13,7 +16,7 @@ class KpiKpi(models.Model):
active = fields.Boolean(default=True) active = fields.Boolean(default=True)
cron_id = fields.Many2one("ir.cron", readonly=True, copy=False) cron_id = fields.Many2one("ir.cron", readonly=True, copy=False)
computation_method = fields.Selection( computation_method = fields.Selection(
[("function", "Function")], required=True
[("function", "Function"), ("code", "Code")], required=True
) )
value = fields.Serialized() value = fields.Serialized()
dashboard_item_ids = fields.One2many("kpi.dashboard.item", inverse_name="kpi_id") dashboard_item_ids = fields.One2many("kpi.dashboard.item", inverse_name="kpi_id")
@ -34,6 +37,7 @@ class KpiKpi(models.Model):
inverse_name='kpi_id', inverse_name='kpi_id',
help="Actions that can be opened from the KPI" help="Actions that can be opened from the KPI"
) )
code = fields.Text("Code")
def _cron_vals(self): def _cron_vals(self):
return { return {
@ -84,6 +88,33 @@ class KpiKpi(models.Model):
vals["value_last_update"] = fields.Datetime.now() vals["value_last_update"] = fields.Datetime.now()
return super().write(vals) return super().write(vals)
def _get_code_input_dict(self):
return {
"self": self,
"model": self.browse(),
}
def _forbidden_code(self):
return ["commit", "rollback", "getattr", "execute"]
def _compute_value_code(self):
forbidden = self._forbidden_code()
search_terms = "(" + ("|".join(forbidden)) + ")"
if re.search(search_terms, (self.code or "").lower()):
message = ", ".join(forbidden[:-1]) or ""
if len(message) > 0:
message += _(" or ")
message += forbidden[-1]
raise ValidationError(_(
"The code cannot contain the following terms: %s."
) % message)
results = self._get_code_input_dict()
savepoint = "kpi_formula_%s" % self.id
self.env.cr.execute("savepoint %s" % savepoint)
safe_eval(self.code or "", results, mode="exec", nocopy=True)
self.env.cr.execute("rollback to %s" % savepoint)
return results.get("result", {})
class KpiKpiAction(models.Model): class KpiKpiAction(models.Model):
_name = 'kpi.kpi.action' _name = 'kpi.kpi.action'

14
kpi_dashboard/readme/CONFIGURE.rst

@ -8,6 +8,20 @@ Configure KPIs
#. Meter: result must contain `value`, `min` and `max` #. Meter: result must contain `value`, `min` and `max`
#. Graph: result must contain a list on `graphs` containing `values`, `title` and `key` #. Graph: result must contain a list on `graphs` containing `values`, `title` and `key`
#. In order to compute the KPI you can use a predefined function from a model or
use the code to directly compute it.
Using KPI with code
~~~~~~~~~~~~~~~~~~~
Define the code directly on the code field. You can use `self` and `model` as the kpi element
The script should create a variable called `result` as a dictionary that
will be stored as the value.
For example, we can use::
result = {}
result['value'] = len(model.search([('id', '=', %s)]))
result['previous'] = len(model.search([('id', '!=', %s)]))
Configure dashboards Configure dashboards
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~

38
kpi_dashboard/static/description/index.html

@ -3,7 +3,7 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
<meta name="generator" content="Docutils 0.14: http://docutils.sourceforge.net/" />
<title>Kpi Dashboard</title> <title>Kpi Dashboard</title>
<style type="text/css"> <style type="text/css">
@ -374,14 +374,15 @@ ul.auto-toc {
<ul class="simple"> <ul class="simple">
<li><a class="reference internal" href="#configuration" id="id1">Configuration</a><ul> <li><a class="reference internal" href="#configuration" id="id1">Configuration</a><ul>
<li><a class="reference internal" href="#configure-kpis" id="id2">Configure KPIs</a></li> <li><a class="reference internal" href="#configure-kpis" id="id2">Configure KPIs</a></li>
<li><a class="reference internal" href="#configure-dashboards" id="id3">Configure dashboards</a></li>
<li><a class="reference internal" href="#using-kpi-with-code" id="id3">Using KPI with code</a></li>
<li><a class="reference internal" href="#configure-dashboards" id="id4">Configure dashboards</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#bug-tracker" id="id4">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id5">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id6">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id7">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id8">Maintainers</a></li>
<li><a class="reference internal" href="#bug-tracker" id="id5">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id6">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id7">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id8">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id9">Maintainers</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
@ -398,10 +399,21 @@ ul.auto-toc {
<li>Graph: result must contain a list on <cite>graphs</cite> containing <cite>values</cite>, <cite>title</cite> and <cite>key</cite></li> <li>Graph: result must contain a list on <cite>graphs</cite> containing <cite>values</cite>, <cite>title</cite> and <cite>key</cite></li>
</ol> </ol>
</li> </li>
<li>In order to compute the KPI you can use a predefined function from a model or
use the code to directly compute it.</li>
</ol> </ol>
</div> </div>
<div class="section" id="using-kpi-with-code">
<h2><a class="toc-backref" href="#id3">Using KPI with code</a></h2>
<p>Define the code directly on the code field. You can use:</p>
<ul class="simple">
<li><cite>self</cite> and <cite>model</cite> as the kpi element</li>
<li>The script should create a variable called <cite>result</cite> as a dictionary that
will be stored as the value</li>
</ul>
</div>
<div class="section" id="configure-dashboards"> <div class="section" id="configure-dashboards">
<h2><a class="toc-backref" href="#id3">Configure dashboards</a></h2>
<h2><a class="toc-backref" href="#id4">Configure dashboards</a></h2>
<ol class="arabic simple"> <ol class="arabic simple">
<li>Access <cite>Dashboards &gt; Configuration &gt; KPI Dashboards &gt; Configure Dashboards</cite></li> <li>Access <cite>Dashboards &gt; Configuration &gt; KPI Dashboards &gt; Configure Dashboards</cite></li>
<li>Create a new dashboard and specify all the standard parameters on <cite>Widget configuration</cite></li> <li>Create a new dashboard and specify all the standard parameters on <cite>Widget configuration</cite></li>
@ -412,7 +424,7 @@ ul.auto-toc {
</div> </div>
</div> </div>
<div class="section" id="bug-tracker"> <div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#id4">Bug Tracker</a></h1>
<h1><a class="toc-backref" href="#id5">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/reporting-engine/issues">GitHub Issues</a>. <p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/reporting-engine/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported. In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed If you spotted it first, help us smashing it by providing a detailed and welcomed
@ -420,21 +432,21 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
<p>Do not contact contributors directly about support or help with technical issues.</p> <p>Do not contact contributors directly about support or help with technical issues.</p>
</div> </div>
<div class="section" id="credits"> <div class="section" id="credits">
<h1><a class="toc-backref" href="#id5">Credits</a></h1>
<h1><a class="toc-backref" href="#id6">Credits</a></h1>
<div class="section" id="authors"> <div class="section" id="authors">
<h2><a class="toc-backref" href="#id6">Authors</a></h2>
<h2><a class="toc-backref" href="#id7">Authors</a></h2>
<ul class="simple"> <ul class="simple">
<li>Creu Blanca</li> <li>Creu Blanca</li>
</ul> </ul>
</div> </div>
<div class="section" id="contributors"> <div class="section" id="contributors">
<h2><a class="toc-backref" href="#id7">Contributors</a></h2>
<h2><a class="toc-backref" href="#id8">Contributors</a></h2>
<ul class="simple"> <ul class="simple">
<li>Enric Tobella &lt;<a class="reference external" href="mailto:etobella&#64;creublanca.es">etobella&#64;creublanca.es</a>&gt;</li> <li>Enric Tobella &lt;<a class="reference external" href="mailto:etobella&#64;creublanca.es">etobella&#64;creublanca.es</a>&gt;</li>
</ul> </ul>
</div> </div>
<div class="section" id="maintainers"> <div class="section" id="maintainers">
<h2><a class="toc-backref" href="#id8">Maintainers</a></h2>
<h2><a class="toc-backref" href="#id9">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p> <p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a> <a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose <p>OCA, or the Odoo Community Association, is a nonprofit organization whose

1
kpi_dashboard_test/tests/__init__.py → kpi_dashboard/tests/__init__.py

@ -1 +1,2 @@
from . import test_formula
from . import test_kpi_dashboard from . import test_kpi_dashboard

59
kpi_dashboard/tests/test_formula.py

@ -0,0 +1,59 @@
# Copyright 2020 Creu Blanca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.tests.common import TransactionCase
from odoo.exceptions import ValidationError
class TestFormula(TransactionCase):
def setUp(self):
super().setUp()
self.kpi = self.env["kpi.kpi"].create(
{
"name": "DEMO KPI",
"widget": "number",
"computation_method": "code",
}
)
def test_forbidden_words_01(self):
self.kpi.code = """
result = {"value": 0}
self.env.cr.commit()
"""
with self.assertRaises(ValidationError):
self.kpi.compute()
def test_forbidden_words_02(self):
self.kpi.code = """
result = {"value": 0}
self.env.cr.rollback()
"""
with self.assertRaises(ValidationError):
self.kpi.compute()
def test_forbidden_words_03(self):
self.kpi.code = """
result = {"value": 0}
self.env.cr.execute("CoMMiT")
"""
with self.assertRaises(ValidationError):
self.kpi.compute()
def test_computation(self):
self.assertFalse(self.kpi.value)
self.kpi.compute()
self.assertEqual(self.kpi.value, {})
self.kpi.code = """
result = {}
result['value'] = len(model.search([('id', '=', %s)]))
result['previous'] = len(model.search([('id', '!=', %s)]))
""" % (
self.kpi.id,
self.kpi.id,
)
self.kpi.compute()
value = self.kpi.value
self.assertTrue(value.get("value"))
self.assertEqual(value.get("value"), 1)
self.assertEqual(value.get("previous"), self.kpi.search_count([]) - 1)

38
kpi_dashboard_test/tests/test_kpi_dashboard.py → kpi_dashboard/tests/test_kpi_dashboard.py

@ -4,6 +4,7 @@
from odoo.tests.common import TransactionCase from odoo.tests.common import TransactionCase
from odoo.exceptions import ValidationError from odoo.exceptions import ValidationError
from odoo.tests.common import Form from odoo.tests.common import Form
from mock import patch
class TestKpiDashboard(TransactionCase): class TestKpiDashboard(TransactionCase):
@ -116,8 +117,45 @@ class TestKpiDashboard(TransactionCase):
actions += len(item['actions']) actions += len(item['actions'])
self.assertTrue(title_found) self.assertTrue(title_found)
self.assertEqual(2, actions) self.assertEqual(2, actions)
self.assertFalse(data.get("action_id", False))
wzd = self.env['kpi.dashboard.menu'].create({
'dashboard_id': self.dashboard.id,
'menu_id': self.env['ir.ui.menu'].search([], limit=1).id,
})
wzd.generate_menu()
data = self.dashboard.read_dashboard()
self.assertTrue(data.get("action_id", False))
def test_compute(self): def test_compute(self):
self.assertFalse(self.kpi_01.value_last_update) self.assertFalse(self.kpi_01.value_last_update)
with patch(
"odoo.addons.kpi_dashboard.models.kpi_kpi."
"KpiKpi.test_demo_number", create=True
) as f:
f.return_value = {"value": 0}
self.kpi_01.compute() self.kpi_01.compute()
self.assertTrue(self.kpi_01.value_last_update) self.assertTrue(self.kpi_01.value_last_update)
def test_compute_model(self):
self.assertFalse(self.kpi_01.value_last_update)
self.kpi_01.model_id = self.env.ref('base.model_res_partner')
with patch(
"odoo.addons.base.models.res_partner.Partner.test_demo_number",
create=True
) as f:
f.return_value = {"value": 0}
self.kpi_01.compute()
self.assertTrue(self.kpi_01.value_last_update)
def test_generate_cron(self):
self.assertFalse(self.kpi_01.cron_id)
self.kpi_01.generate_cron()
self.assertTrue(self.kpi_01.cron_id)
self.assertFalse(self.kpi_01.value_last_update)
with patch(
"odoo.addons.kpi_dashboard.models.kpi_kpi."
"KpiKpi.test_demo_number", create=True
) as f:
f.return_value = {"value": 0}
self.kpi_01.cron_id.method_direct_trigger()
self.assertTrue(self.kpi_01.value_last_update)

5
kpi_dashboard/views/kpi_kpi.xml

@ -45,6 +45,11 @@
</tree> </tree>
</field> </field>
</page> </page>
<page name="code" string="Code" attrs="{'invisible': [('computation_method', '!=', 'code')]}">
<field name="code" widget="ace"
options="{'mode': 'python'}"
placeholder="Enter Python code here."/>
</page>
</notebook> </notebook>
</sheet> </sheet>
</form> </form>

73
kpi_dashboard_test/README.rst

@ -1,73 +0,0 @@
===================
Kpi Dashboard: Test
===================
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github
:target: https://github.com/OCA/reporting-engine/tree/12.0/kpi_dashboard_test
:alt: OCA/reporting-engine
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/reporting-engine-12-0/reporting-engine-12-0-kpi_dashboard_test
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/143/12.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
This module is used in order to test KPI Dashboard
**Table of contents**
.. contents::
:local:
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/reporting-engine/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
`feedback <https://github.com/OCA/reporting-engine/issues/new?body=module:%20kpi_dashboard_test%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* Creu Blanca
Contributors
~~~~~~~~~~~~
* Enric Tobella <etobella@creublanca.es>
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
This module is part of the `OCA/reporting-engine <https://github.com/OCA/reporting-engine/tree/12.0/kpi_dashboard_test>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

1
kpi_dashboard_test/__init__.py

@ -1 +0,0 @@
from . import models

14
kpi_dashboard_test/__manifest__.py

@ -1,14 +0,0 @@
# Copyright 2020 Creu Blanca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "Kpi Dashboard: Test",
"summary": """
Testing KPI dashboard""",
"version": "12.0.1.0.1",
"license": "AGPL-3",
"author": "Creu Blanca,Odoo Community Association (OCA)",
"website": "https://github.com/reporting-engine",
"depends": ["kpi_dashboard"],
"demo": ["demo/demo_dashboard.xml"],
}

20
kpi_dashboard_test/i18n/kpi_dashboard_test.pot

@ -1,20 +0,0 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * kpi_dashboard_test
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: kpi_dashboard_test
#: model:ir.model,name:kpi_dashboard_test.model_kpi_kpi
msgid "Kpi Kpi"
msgstr ""

1
kpi_dashboard_test/models/__init__.py

@ -1 +0,0 @@
from . import kpi_kpi

48
kpi_dashboard_test/models/kpi_kpi.py

@ -1,48 +0,0 @@
# Copyright 2020 Creu Blanca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models
import random
class KpiKpi(models.Model):
_inherit = "kpi.kpi"
def test_demo_number(self):
return {
"value": random.random() * 10000,
"previous": random.random() * 10000,
}
def test_demo_meter(self):
return {
"min": 0,
"max": 100,
"value": random.random() * 100,
}
def test_demo_graph(self):
return {
"graphs": [
{
"values": [
{"x": i, "y": random.random() * 1000}
for i in range(1, 12)
],
"title": "Current Year",
"key": "current",
"area": True,
"color": "ffffff",
},
{
"values": [
{"x": i, "y": random.random() * 1000}
for i in range(1, 12)
],
"title": "Previous Year",
"key": "previous",
"area": True,
"color": "000000",
},
]
}

1
kpi_dashboard_test/readme/CONTRIBUTORS.rst

@ -1 +0,0 @@
* Enric Tobella <etobella@creublanca.es>

1
kpi_dashboard_test/readme/DESCRIPTION.rst

@ -1 +0,0 @@
This module is used in order to test KPI Dashboard

BIN
kpi_dashboard_test/static/description/icon.png

Before

Width: 128  |  Height: 128  |  Size: 9.2 KiB

419
kpi_dashboard_test/static/description/index.html

@ -1,419 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
<title>Kpi Dashboard: Test</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="kpi-dashboard-test">
<h1 class="title">Kpi Dashboard: Test</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/reporting-engine/tree/12.0/kpi_dashboard_test"><img alt="OCA/reporting-engine" src="https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/reporting-engine-12-0/reporting-engine-12-0-kpi_dashboard_test"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/143/12.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>This module is used in order to test KPI Dashboard</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#bug-tracker" id="id1">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id2">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id3">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id4">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id5">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#id1">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/reporting-engine/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/reporting-engine/issues/new?body=module:%20kpi_dashboard_test%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#id2">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#id3">Authors</a></h2>
<ul class="simple">
<li>Creu Blanca</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#id4">Contributors</a></h2>
<ul class="simple">
<li>Enric Tobella &lt;<a class="reference external" href="mailto:etobella&#64;creublanca.es">etobella&#64;creublanca.es</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#id5">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/reporting-engine/tree/12.0/kpi_dashboard_test">OCA/reporting-engine</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>
Loading…
Cancel
Save