3
0
Fork 0

Merge PR #3005 into 18.0

Signed-off-by pedrobaeza
18.0
OCA-git-bot 2024-11-29 14:31:25 +00:00
commit 8e1f37dc73
30 changed files with 2392 additions and 0 deletions

View File

@ -0,0 +1 @@
odoo-test-helper

Binary file not shown.

View File

@ -0,0 +1,135 @@
==========================
Web Pivot Computed Measure
==========================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:4cef60dd775467b756ccbacb8c215bba0bc74fd32e1917c8b15c3be9de6302a1
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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%2Fweb-lightgray.png?logo=github
:target: https://github.com/OCA/web/tree/18.0/web_pivot_computed_measure
:alt: OCA/web
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/web-18-0/web-18-0-web_pivot_computed_measure
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/web&target_branch=18.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
Adds support for computed measures on the pivot view.
**Table of contents**
.. contents::
:local:
Usage
=====
Go to pivot view and click on the "Measures" menu, you will see a new
option called 'Computed Measure'.
You have the follow options to create a 'computed measure':
- Measure 1: Used in 'operation formula' as 'm1'
- Measure 2: Used in 'operation formula' as 'm2'
- Operation: The formula
- Sum: m1 + m2
- Sub: m1 - m2
- Mult: m1 \* m2
- Div: m1 / m2 (Format: Float)
- Perc m1 / m2 (Format: Percentage)
- Custom: Special option only visible in debug mode to write a
custom formula.
- Name: The name of the new measure (emtpy = auto-generated)
- Format: How will the value be printed
- Integer
- Float
- Percentage (value \* 100)
- | Formula\*: Custom operation formula
| These formula is evaluated using 'PY.eval'
These computed measures can be mixed (You can reuse it to make new
computed measures) and saved as favorites.
Notice that "measures/computed measures" involved in an active 'computed
measure' can't be deactivated until you have deactivate the 'computed
measure'.
Known issues / Roadmap
======================
1. Add support to define a style for a computed measure (ex. colored)
2. Use t-model to data-binding instead of jquery selectors
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/web/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/web/issues/new?body=module:%20web_pivot_computed_measure%0Aversion:%2018.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
-------
* Tecnativa
Contributors
------------
- `Tecnativa <https://www.tecnativa.com/>`__:
- Alexandre D. Díaz
- Pedro M. Baeza
- Ernesto Tejeda
- Carlos Roca
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.
.. |maintainer-CarlosRoca13| image:: https://github.com/CarlosRoca13.png?size=40px
:target: https://github.com/CarlosRoca13
:alt: CarlosRoca13
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-CarlosRoca13|
This module is part of the `OCA/web <https://github.com/OCA/web/tree/18.0/web_pivot_computed_measure>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

@ -0,0 +1,29 @@
# Copyright 2020 Tecnativa - Alexandre Díaz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
{
"name": "Web Pivot Computed Measure",
"category": "web",
"version": "18.0.1.0.0",
"author": "Tecnativa, Odoo Community Association (OCA)",
"license": "AGPL-3",
"website": "https://github.com/OCA/web",
"depends": ["web"],
"auto_install": False,
"installable": True,
"maintainers": ["CarlosRoca13"],
"assets": {
"web.assets_backend": [
"web_pivot_computed_measure/static/src/**/*.esm.js",
"web_pivot_computed_measure/static/src/**/*.scss",
"web_pivot_computed_measure/static/src/**/*.xml",
("remove", "web_pivot_computed_measure/static/src/test/*.esm.js"),
("remove", "web_pivot_computed_measure/static/src/pivot/*"),
],
"web.assets_backend_lazy": [
"web_pivot_computed_measure/static/src/pivot/*",
],
"web.assets_tests": [
"web_pivot_computed_measure/static/src/test/test.esm.js",
],
},
}

View File

@ -0,0 +1,210 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_pivot_computed_measure
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 13.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2021-07-05 12:48+0000\n"
"Last-Translator: jabelchi <jabelchi@gmail.com>\n"
"Language-Team: none\n"
"Language: ca\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.3.2\n"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Add"
msgstr "Afegir"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Can be empty"
msgstr "Pot estar buit"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Computed Measure"
msgstr "Mesura calculada"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Custom"
msgstr "Personalitat"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Div (m1 / m2)"
msgstr "Div (m1 / m2)"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Float"
msgstr "Comma flotant"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Format"
msgstr "Format"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Formula"
msgstr "Fórmula"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Integer"
msgstr "Enter"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Measure 1"
msgstr "Mesura 1"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Measure 2"
msgstr "Mesura 2"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Mult (m1 * m2)"
msgstr "Mult (m1 * m2)"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Name"
msgstr "Nom"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Operation"
msgstr "Operació"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Perc (m1 * 100 / m2)"
msgstr "Perc (m1 * 100 / m2)"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Percentage"
msgstr "Percentatge"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Sub (m1 - m2)"
msgstr "Resta (m1 - m2)"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Sum (m1 + m2)"
msgstr "Suma (m1 + m2)"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/pivot/pivot_model.esm.js:0
#, python-format
msgid ""
"This measure is currently used by a 'computed measure'. Please, disable the "
"computed measure first."
msgstr ""
"Aquesta mesura s'usa actualment per una \"mesura calculada\". Si us plau, "
"inhabiliteu primer la mesura calculada."
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "custom"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "float"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "integer"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "m1*m2"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "m1+m2"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "m1-m2"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "m1/m2"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "percentage"
msgstr ""

View File

@ -0,0 +1,215 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_pivot_computed_measure
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-11-22 12:42+0000\n"
"PO-Revision-Date: 2023-11-19 19:33+0000\n"
"Last-Translator: Ivorra78 <informatica@totmaterial.es>\n"
"Language-Team: none\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.17\n"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Add"
msgstr "Añadir"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Can be empty"
msgstr "Puede estar vacío"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Computed Measure"
msgstr "Medida computada"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Custom"
msgstr "Customizado"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Div (m1 / m2)"
msgstr "Div (m1 / m2)"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Float"
msgstr "Flotador"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Format"
msgstr "Formato"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Formula"
msgstr "Fórmula"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Integer"
msgstr "Entero"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Measure 1"
msgstr "Medida 1"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Measure 2"
msgstr "Medida 2"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Mult (m1 * m2)"
msgstr "Mult (m1 * m2)"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Name"
msgstr "Nombre"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Operation"
msgstr "Operación"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Perc (m1 * 100 / m2)"
msgstr "Perc (m1 * 100 / m2)"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Percentage"
msgstr "Porcentaje"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Sub (m1 - m2)"
msgstr "Sub (m1 - m2)"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Sum (m1 + m2)"
msgstr "Sum (m1 + m2)"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/pivot/pivot_model.esm.js:0
#, python-format
msgid ""
"This measure is currently used by a 'computed measure'. Please, disable the "
"computed measure first."
msgstr ""
"Esta medida está utilizada por una 'medida computada'. Por favor, desabilita "
"la medida computada primero."
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "custom"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "float"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "integer"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "m1*m2"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "m1+m2"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "m1-m2"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "m1/m2"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "percentage"
msgstr ""
#, python-format
#~ msgid "!measure.startsWith('__computed_')"
#~ msgstr "!measure.startsWith('__computed_')"

View File

@ -0,0 +1,210 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_pivot_computed_measure
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-04-19 14:37+0000\n"
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
"Language-Team: none\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.17\n"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Add"
msgstr "Aggiungi"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Can be empty"
msgstr "Può essere sufficiente"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Computed Measure"
msgstr "Misura calcolata"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Custom"
msgstr "Personalizzato"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Div (m1 / m2)"
msgstr "Div. (m1 / m2)"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Float"
msgstr "Float"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Format"
msgstr "Formato"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Formula"
msgstr "Formula"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Integer"
msgstr "Intero"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Measure 1"
msgstr "Misura 1"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Measure 2"
msgstr "Misura 2"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Mult (m1 * m2)"
msgstr "Molt. (m1 * m2)"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Name"
msgstr "Nome"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Operation"
msgstr "Operazione"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Perc (m1 * 100 / m2)"
msgstr "Perc. (m1 * 100 / m2)"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Percentage"
msgstr "Percentuale"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Sub (m1 - m2)"
msgstr "Sott. (m1 - m2)"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Sum (m1 + m2)"
msgstr "Som. (m1 + m2)"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/pivot/pivot_model.esm.js:0
#, python-format
msgid ""
"This measure is currently used by a 'computed measure'. Please, disable the "
"computed measure first."
msgstr ""
"Questa misura è utilizzata in una 'misura calcolata'. Disabilitare prima la "
"misura calcolata."
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "custom"
msgstr "personalizzato"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "float"
msgstr "float"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "integer"
msgstr "integer"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "m1*m2"
msgstr "m1*m2"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "m1+m2"
msgstr "m1+m2"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "m1-m2"
msgstr "m1-m2"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "m1/m2"
msgstr "m1/m2"
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "percentage"
msgstr "percentuale"

View File

@ -0,0 +1,206 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_pivot_computed_measure
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.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: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Add"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Can be empty"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Computed Measure"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Custom"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Div (m1 / m2)"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Float"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Format"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Formula"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Integer"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Measure 1"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Measure 2"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Mult (m1 * m2)"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Name"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Operation"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Perc (m1 * 100 / m2)"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Percentage"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Sub (m1 - m2)"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "Sum (m1 + m2)"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/pivot/pivot_model.esm.js:0
#, python-format
msgid ""
"This measure is currently used by a 'computed measure'. Please, disable the "
"computed measure first."
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "custom"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "float"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "integer"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "m1*m2"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "m1+m2"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "m1-m2"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "m1/m2"
msgstr ""
#. module: web_pivot_computed_measure
#. odoo-javascript
#: code:addons/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.xml:0
#, python-format
msgid "percentage"
msgstr ""

View File

@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"

View File

@ -0,0 +1,5 @@
- [Tecnativa](https://www.tecnativa.com/):
- Alexandre D. Díaz
- Pedro M. Baeza
- Ernesto Tejeda
- Carlos Roca

View File

@ -0,0 +1 @@
Adds support for computed measures on the pivot view.

View File

@ -0,0 +1,2 @@
1. Add support to define a style for a computed measure (ex. colored)
2. Use t-model to data-binding instead of jquery selectors

View File

@ -0,0 +1,33 @@
Go to pivot view and click on the "Measures" menu, you will see a new
option called 'Computed Measure'.
You have the follow options to create a 'computed measure':
- Measure 1: Used in 'operation formula' as 'm1'
- Measure 2: Used in 'operation formula' as 'm2'
- Operation: The formula
- Sum: m1 + m2
- Sub: m1 - m2
- Mult: m1 \* m2
- Div: m1 / m2 (Format: Float)
- Perc m1 / m2 (Format: Percentage)
- Custom: Special option only visible in debug mode to write a custom
formula.
- Name: The name of the new measure (emtpy = auto-generated)
- Format: How will the value be printed
- Integer
- Float
- Percentage (value \* 100)
- Formula\*: Custom operation formula
These formula is evaluated using 'PY.eval'
These computed measures can be mixed (You can reuse it to make new
computed measures) and saved as favorites.
Notice that "measures/computed measures" involved in an active 'computed
measure' can't be deactivated until you have deactivate the 'computed
measure'.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@ -0,0 +1,482 @@
<!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: https://docutils.sourceforge.io/" />
<title>Web Pivot Computed Measure</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/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: gray; } /* 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, pre.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="web-pivot-computed-measure">
<h1 class="title">Web Pivot Computed Measure</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:4cef60dd775467b756ccbacb8c215bba0bc74fd32e1917c8b15c3be9de6302a1
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" 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 image-reference" 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 image-reference" href="https://github.com/OCA/web/tree/18.0/web_pivot_computed_measure"><img alt="OCA/web" src="https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/web-18-0/web-18-0-web_pivot_computed_measure"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/web&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>Adds support for computed measures on the pivot view.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#usage" id="toc-entry-1">Usage</a></li>
<li><a class="reference internal" href="#known-issues-roadmap" id="toc-entry-2">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-3">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-4">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-5">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-6">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-7">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#toc-entry-1">Usage</a></h1>
<p>Go to pivot view and click on the “Measures” menu, you will see a new
option called Computed Measure.</p>
<p>You have the follow options to create a computed measure:</p>
<ul>
<li><p class="first">Measure 1: Used in operation formula as m1</p>
</li>
<li><p class="first">Measure 2: Used in operation formula as m2</p>
</li>
<li><p class="first">Operation: The formula</p>
<ul class="simple">
<li>Sum: m1 + m2</li>
<li>Sub: m1 - m2</li>
<li>Mult: m1 * m2</li>
<li>Div: m1 / m2 (Format: Float)</li>
<li>Perc m1 / m2 (Format: Percentage)</li>
<li>Custom: Special option only visible in debug mode to write a
custom formula.</li>
</ul>
</li>
<li><p class="first">Name: The name of the new measure (emtpy = auto-generated)</p>
</li>
<li><p class="first">Format: How will the value be printed</p>
<ul class="simple">
<li>Integer</li>
<li>Float</li>
<li>Percentage (value * 100)</li>
</ul>
</li>
<li><div class="first line-block">
<div class="line">Formula*: Custom operation formula</div>
<div class="line">These formula is evaluated using PY.eval</div>
</div>
</li>
</ul>
<p>These computed measures can be mixed (You can reuse it to make new
computed measures) and saved as favorites.</p>
<p>Notice that “measures/computed measures” involved in an active computed
measure cant be deactivated until you have deactivate the computed
measure.</p>
</div>
<div class="section" id="known-issues-roadmap">
<h1><a class="toc-backref" href="#toc-entry-2">Known issues / Roadmap</a></h1>
<ol class="arabic simple">
<li>Add support to define a style for a computed measure (ex. colored)</li>
<li>Use t-model to data-binding instead of jquery selectors</li>
</ol>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/web/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 to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/web/issues/new?body=module:%20web_pivot_computed_measure%0Aversion:%2018.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="#toc-entry-4">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-5">Authors</a></h2>
<ul class="simple">
<li>Tecnativa</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
<ul class="simple">
<li><a class="reference external" href="https://www.tecnativa.com/">Tecnativa</a>:<ul>
<li>Alexandre D. Díaz</li>
<li>Pedro M. Baeza</li>
<li>Ernesto Tejeda</li>
<li>Carlos Roca</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-7">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>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
<p><a class="reference external image-reference" href="https://github.com/CarlosRoca13"><img alt="CarlosRoca13" src="https://github.com/CarlosRoca13.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/web/tree/18.0/web_pivot_computed_measure">OCA/web</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>

View File

@ -0,0 +1,49 @@
/** @odoo-module **/
/* Copyright 2022 Tecnativa - Carlos Roca
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) */
import {Component, useState} from "@odoo/owl";
/**
* @extends Component
*/
export class DropdownItemCustomMeasure extends Component {
setup() {
this.isOpen = useState({value: false});
}
onClickComputedMeasure() {
this.isOpen.value = !this.isOpen.value;
}
addMeasure(ev) {
const target = ev.target.closest("#add_computed_measure_wrapper");
const id = new Date().getTime();
const field1 = target.querySelector("#computed_measure_field_1").value;
const field2 = target.querySelector("#computed_measure_field_2").value;
let operation = target.querySelector("#computed_measure_operation").value;
if (operation === "custom") {
operation = target.querySelector(
"#computed_measure_operation_custom"
).value;
}
const name = target.querySelector("#computed_measure_name").value;
const format = target.querySelector("#computed_measure_format").value;
this.props.model.addComputedMeasure(
id,
field1,
field2,
operation,
name,
format
);
}
}
DropdownItemCustomMeasure.template =
"web_pivot_computed_measure.DropdownItemCustomMeasure";
DropdownItemCustomMeasure.props = {
measures: Object,
// Set as model because this module can be extended to be used on views that
// uses Measures like the graph view.
model: Object,
};

View File

@ -0,0 +1,9 @@
#add_computed_measure_wrapper {
padding: 0 20px;
min-width: 300px;
white-space: nowrap;
.d-table-cell {
vertical-align: middle;
padding: 3px 0;
}
}

View File

@ -0,0 +1,160 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-name="web_pivot_computed_measure.ComputedMeasureOperations" owl="1">
<option name="sum" value="m1+m2">
Sum (m1 + m2)
</option>
<option name="sub" value="m1-m2">
Sub (m1 - m2)
</option>
<option name="mult" value="m1*m2">
Mult (m1 * m2)
</option>
<option name="div" data-format="float" value="m1/m2">
Div (m1 / m2)
</option>
<option name="perc" data-format="percentage" value="m1/m2">
Perc (m1 * 100 / m2)
</option>
<option t-if="debug" name="custom" value="custom">
Custom
</option>
</t>
<t t-name="web_pivot_computed_measure.ComputedMeasureFormats" owl="1">
<option name="int" value="integer">
Integer
</option>
<option name="float" value="float" selected="selected">
Float
</option>
<option name="percentage" value="percentage">
Percentage
</option>
</t>
<t t-name="web_pivot_computed_measure.DropdownItemCustomMeasure" owl="1">
<div class="o_menu_item dropdown-item" data-id="__computed__">
<a href="#" role="menuitem" t-on-click="onClickComputedMeasure">
Computed Measure
<span class="o_submenu_switcher" data-id="__computed__">
<span
t-att-class="isOpen.value ? 'fa fa-caret-down' : 'fa fa-caret-right'"
/>
</span>
</a>
<t t-if="isOpen.value">
<div id="add_computed_measure_wrapper" class="d-table">
<div class="d-table-row">
<div class="d-table-cell">
<label for="computed_measure_field_1">Measure 1</label>
</div>
<div class="d-table-cell">
<select class="o_input" id="computed_measure_field_1">
<t
t-foreach="props.measures"
t-as="measure"
t-key="measure"
>
<option
t-att-value="measure"
t-if="measure != '__count'"
>
<t t-esc="props.measures[measure].string" />
</option>
</t>
</select>
</div>
</div>
<div class="d-table-row">
<div class="d-table-cell">
<label for="computed_measure_field_2">Measure 2</label>
</div>
<div class="d-table-cell">
<select class="o_input" id="computed_measure_field_2">
<t
t-foreach="props.measures"
t-as="measure"
t-key="measure"
>
<option
t-att-value="measure"
t-if="measure != '__count'"
>
<t t-esc="props.measures[measure].string" />
</option>
</t>
</select>
</div>
</div>
<div class="d-table-row">
<div class="d-table-cell">
<label for="computed_measure_operation">Operation</label>
</div>
<div class="d-table-cell">
<select class="o_input" id="computed_measure_operation">
<t
t-call="web_pivot_computed_measure.ComputedMeasureOperations"
/>
</select>
</div>
</div>
<div
t-if="debug"
class="d-none"
id="container_computed_measure_operation_custom"
>
<div class="d-table-cell">
<label
for="computed_measure_operation_custom"
>Formula</label>
</div>
<div class="d-table-cell">
<input
type="text"
class="o_input"
id="computed_measure_operation_custom"
/>
</div>
</div>
<div class="d-table-row">
<div class="d-table-cell">
<label for="computed_measure_name">Name</label>
</div>
<div class="d-table-cell">
<input
placeholder="Can be empty"
type="text"
class="o_input"
id="computed_measure_name"
/>
</div>
</div>
<div class="d-table-row">
<div class="d-table-cell">
<label for="computed_measure_format">Format</label>
</div>
<div class="d-table-cell">
<select class="o_input" id="computed_measure_format">
<t
t-call="web_pivot_computed_measure.ComputedMeasureFormats"
/>
</select>
</div>
</div>
<div class="d-table-row">
<div class="d-table-cell">
<button
class="btn btn-primary o_add_computed_measure"
type="button"
t-on-click="addMeasure"
>Add</button>
</div>
</div>
</div>
</t>
</div>
</t>
</templates>

View File

@ -0,0 +1,124 @@
/** @odoo-module **/
/* Copyright 2023 Tecnativa - Carlos Roca
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) */
/**
* Function that traverse the text given character by character
*
* @param {String} text
* @returns {Array}
*/
function getTokensFromText(text) {
const symbols = ["+", "-", "*", "/", "(", ")"];
const tokens = [];
let token = "";
for (let i = 0; i < text.length; i++) {
const c = text[i];
if (c === " ") continue;
if (symbols.includes(c)) {
if (token !== "") {
tokens.push(token);
token = "";
}
tokens.push(c);
} else {
token += c;
}
}
if (token !== "") {
tokens.push(token);
}
return tokens;
}
/**
* Function that executes an operation between the last two operands in the operands stack
* and the last operator in the operators stack, and saves the result in the operands stack.
*
* @param {Array} operands
* @param {Array} operators
*/
function executeOperation(operands, operators) {
const b = operands.pop();
const a = operands.pop();
const op = operators.pop();
switch (op) {
case "+":
operands.push(a + b);
break;
case "-":
operands.push(a - b);
break;
case "*":
operands.push(a * b);
break;
case "/":
operands.push(a / b);
break;
}
}
/**
* Function that returns the precedence of an operator
*
* @param {String} op
* @returns {Number}
*/
function precedence(op) {
if (op === "+" || op === "-") {
return 1;
}
if (op === "*" || op === "/") {
return 2;
}
if (op === "(" || op === ")") {
return 0;
}
}
/**
* Helper function that takes a mathematical expression in text form and an object
* of variable values, evaluates the expression, and returns the result.
*
* @param {String} text
* @param {Object} values
* @returns {any}
*/
export function evalOperation(text, values) {
const tokens = getTokensFromText(text);
const operands = [];
const operators = [];
for (const token of tokens) {
if (!isNaN(token)) {
// If the token is a number, convert it to a number and add it to the operands stack
operands.push(Number(token));
} else if (token in values) {
// If the token is a variable, get its value from the object and add it to the operands stack
operands.push(values[token]);
} else if (token === "(") {
// If the token is an open parenthesis, add it to the operators stack
operators.push(token);
} else if (token === ")") {
// If the token is a closing parenthesis, pop and execute operators from the stack until an open parenthesis is found
while (operators.length > 0 && operators[operators.length - 1] !== "(") {
executeOperation(operands, operators);
}
// Pop the open parenthesis from the operators stack
operators.pop();
} else {
// If the token is an operator, pop and execute operators from the stack while they have equal or higher precedence than the token
while (
operators.length > 0 &&
precedence(operators[operators.length - 1]) >= precedence(token)
) {
executeOperation(operands, operators);
}
// Add the token to the operators stack
operators.push(token);
}
}
while (operators.length > 0) {
executeOperation(operands, operators);
}
return operands.pop();
}

View File

@ -0,0 +1,20 @@
/** @odoo-module **/
/* Copyright 2024 Tecnativa - Carlos Roca
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) */
import {PivotController} from "@web/views/pivot/pivot_controller";
import {patch} from "@web/core/utils/patch";
patch(PivotController.prototype, {
/**
* Add computed_measures to context key to avoid loosing info when saving the
* filter to favorites.
*
* @override
*/
getContext() {
var res = super.getContext(...arguments);
res.pivot_computed_measures = this.model._computed_measures;
return res;
},
});

View File

@ -0,0 +1,294 @@
/** @odoo-module **/
/* Copyright 2020 Tecnativa - Alexandre Díaz
* Copyright 2022 Tecnativa - Carlos Roca
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) */
import {PivotModel} from "@web/views/pivot/pivot_model";
import {patch} from "@web/core/utils/patch";
import {computeReportMeasures} from "@web/views/utils";
import {evalOperation} from "../helpers/utils.esm";
patch(PivotModel.prototype, {
/**
* Add _computed_measures to avoid recompute them until page is recharged
*
* @override
*/
setup() {
super.setup(...arguments);
this._computed_measures = [];
},
/**
* Create a new computed measure
*
* @param {String} id
* @param {String} field1
* @param {String} field2
* @param {String} operation
* @param {String} name
* @param {String} format
* @returns a promise
*/
addComputedMeasure(id, field1, field2, operation, name, format) {
const measure = this._computed_measures.find((item) => {
return (
item.field1 === field1 &&
item.field2 === field2 &&
item.operation === operation
);
});
if (measure) {
return Promise.resolve();
}
const fieldM1 = this.metaData.fields[field1];
const fieldM2 = this.metaData.fields[field2];
const cmId = "__computed_" + id;
const oper = operation.replace(/m1/g, field1).replace(/m2/g, field2);
const oper_human = operation
.replace(
/m1/g,
fieldM1.__computed_id ? "(" + fieldM1.string + ")" : fieldM1.string
)
.replace(
/m2/g,
fieldM2.__computed_id ? "(" + fieldM2.string + ")" : fieldM2.string
);
const cmTotal = this._computed_measures.push({
field1: field1,
field2: field2,
operation: oper,
name: name || oper_human,
id: cmId,
format: format,
});
return this._createVirtualMeasure(this._computed_measures[cmTotal - 1]);
},
/**
* Create and enable a measure based on a 'fake' field
*
* @private
* @param {Object} cmDef
* @param {List} fields *Optional*
* @returns a promise
*/
_createVirtualMeasure(cmDef, fields) {
this._createVirtualField(cmDef, fields);
// Activate computed field
return this.toggleMeasure(cmDef.id);
},
_createVirtualField(cmDef, fields, config) {
const arrFields = fields || this.metaData.fields;
// This is a minimal 'fake' field info
arrFields[cmDef.id] = {
// Used to format the value
type: cmDef.format,
// Used to print the header name
string: cmDef.name,
// Referenced on payload prop at DropdownItem, used to interact with
// created measures
name: cmDef.id,
// Used to know if is a computed measure field
__computed_id: cmDef.id,
// Operator used for group the measure added.
aggregator: "sum",
};
const metaData = (config && config.metaData) || this.metaData;
metaData.measures[cmDef.id] = arrFields[cmDef.id];
},
/**
* Active the measures related to the 'fake' field
*
* @private
* @param {List of Strings} fields
*/
async _activeMeasures(fields) {
let needLoad = false;
for (const field of fields) {
if (await !this._isMeasureEnabled(field)) {
this.metaData.activeMeasures.push(field);
needLoad = true;
}
}
if (needLoad) {
const config = {metaData: this.metaData, data: this.data};
return this._loadData(config).then(() => {
// Notify changes to renderer for show it on the pivot view
this.notify();
});
}
return Promise.resolve();
},
/**
* Check if the measure is enabled
*
* @private
* @param {String} field
*/
_isMeasureEnabled(field, config) {
const activeMeasures =
(config && config.metaData.activeMeasures) ||
this.metaData.activeMeasures ||
[];
return activeMeasures.includes(field);
},
/**
* Helper function to add computed measure fields data into a 'subGroupData'
*
* @private
* @param {Object} subGroupData
*/
_fillComputedMeasuresData(subGroupData, config) {
for (const cm of this._computed_measures) {
if (!this._isMeasureEnabled(cm.id, config)) continue;
if (subGroupData.__count === 0) {
subGroupData[cm.id] = false;
} else {
subGroupData[cm.id] = evalOperation(cm.operation, subGroupData);
}
}
},
/**
* Fill the groupSubdivisions with the computed measures and their values
*
* @override
*/
_prepareData(group, groupSubdivisions, config) {
for (const groupSubdivision of groupSubdivisions) {
for (const subGroup of groupSubdivision.subGroups) {
this._fillComputedMeasuresData(subGroup, config);
}
}
super._prepareData(...arguments);
},
/**
* _getGroupSubdivision method invokes the read_group method of the
* model via rpc and the passed 'fields' argument is the list of
* measure names that is in this.metaData.activeMeasures, so we remove the
* computed measures form this.metaData.activeMeasures before calling _super
* to prevent any possible exception.
*
* @override
*/
async _getGroupSubdivision(group, rowGroupBy, colGroupBy, config) {
const computed_measures = [];
for (let i = 0; i < config.measureSpecs.length; i++)
if (config.measureSpecs[i].startsWith("__computed_")) {
computed_measures.push(config.measureSpecs[i]);
config.measureSpecs.splice(i, 1);
i--;
}
const res = await super._getGroupSubdivision(...arguments);
Object.assign(config.measureSpecs, computed_measures);
return res;
},
/**
* Adds a rule to deny that measures can be disabled if are being used by a computed measure.
* In the other hand, when enables a measure analyzes it to active all involved measures.
*
* @override
*/
toggleMeasure(fieldName) {
if (this._isMeasureEnabled(fieldName)) {
// Mesaure is enabled
const umeasures = this._computed_measures.filter((item) => {
return item.field1 === fieldName || item.field2 === fieldName;
});
if (umeasures.length && this._isMeasureEnabled(umeasures[0].id)) {
return Promise.reject(
this.env._t(
"This measure is currently used by a 'computed measure'. Please, disable the computed measure first."
)
);
}
} else {
// Measure is disabled
const toEnable = [];
const toAnalyze = [fieldName];
while (toAnalyze.length) {
// Analyze all items involved on computed measures to enable them
const afield = toAnalyze.shift();
const fieldDef = this.metaData.fields[afield];
// Need to check if fieldDef exists to avoid problems with __count
if (fieldDef && fieldDef.__computed_id) {
const cm = this._computed_measures.find((item) => {
return item.id === fieldDef.__computed_id;
});
toAnalyze.push(cm.field1, cm.field2);
const toEnableFields = [];
if (!this.metaData.fields[cm.field1].__computed_id) {
toEnableFields.push(cm.field1);
}
if (!this.metaData.fields[cm.field2].__computed_id) {
toEnableFields.push(cm.field2);
}
toEnableFields.push(afield);
toEnable.push(toEnableFields);
}
}
if (toEnable.length) {
this._activeMeasures(
// Transform the array of arrays to a simple array.
// [1, [2, 3]] => [1, 2, 3]
toEnable.reverse().flat(Infinity)
);
}
}
return super.toggleMeasure(...arguments);
},
/**
* Load the measures added to selected favorite filters
*
* @override
*/
async load(searchParams) {
var _super = super.load.bind(this);
var config = {metaData: this.metaData, data: this.data};
if (!this.metaData.measures) {
const metaData = this._buildMetaData();
metaData.measures = computeReportMeasures(
metaData.fields,
metaData.fieldAttrs,
metaData.activeMeasures,
metaData.additionalMeasures
);
config = {metaData, data: this.data};
}
if ("context" in searchParams) {
this._computed_measures =
searchParams.context.pivot_computed_measures ||
searchParams.computed_measures ||
[];
}
for (const cmDef of this._computed_measures) {
if (this._isMeasureEnabled(cmDef.id, config)) {
continue;
}
await this._createVirtualField(cmDef, undefined, config);
}
const fieldNames = Object.keys(this.metaData.fields);
for (const fieldName of fieldNames) {
const field = this.metaData.fields[fieldName];
if (field.__computed_id) {
const cm = this._computed_measures.find((item) => {
return item.id === field.__computed_id;
});
if (!cm) {
delete this.metaData.fields[fieldName];
delete this.metaData.measures[fieldName];
this.metaData.activeMeasures = this.metaData.activeMeasures.filter(
(item) => item !== fieldName
);
}
}
}
return _super(...arguments);
},
});

View File

@ -0,0 +1,15 @@
/** @odoo-module **/
/* Copyright 2022 Tecnativa - Carlos Roca
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) */
import {PivotRenderer} from "@web/views/pivot/pivot_renderer";
import {patch} from "@web/core/utils/patch";
patch(PivotRenderer.prototype, {
getFormattedValue(cell) {
if (cell.value === Infinity) {
return "-";
}
return super.getFormattedValue(...arguments);
},
});

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-inherit="web.PivotView.Buttons" t-inherit-mode="extension">
<xpath expr="//ReportViewMeasures" position="attributes">
<attribute name="add_computed_measures">true</attribute>
<attribute name="model">model</attribute>
</xpath>
</t>
</templates>

View File

@ -0,0 +1,16 @@
/** @odoo-module **/
/* Copyright 2024 Tecnativa - Carlos Roca
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) */
import {ReportViewMeasures} from "@web/views/view_components/report_view_measures";
import {DropdownItemCustomMeasure} from "../dropdown_item_custom_measure/dropdown_item_custom_measure.esm";
ReportViewMeasures.components = {
...ReportViewMeasures.components,
DropdownItemCustomMeasure,
};
ReportViewMeasures.props = {
...ReportViewMeasures.props,
add_computed_measures: {type: Boolean, optional: true},
model: {type: Object, optional: true},
};

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-inherit="web.ReportViewMeasures" t-inherit-mode="extension">
<xpath expr="//DropdownItem" position="attributes">
<attribute name="t-if">!measure.startsWith('__computed_')</attribute>
</xpath>
<xpath expr="//t[@t-foreach='props.measures']" position="after">
<div
role="separator"
class="dropdown-divider"
t-if="props.add_computed_measures"
/>
<t t-foreach="props.measures" t-as="measure" t-key="measure_value.name">
<DropdownItem
class="{ o_menu_item: true, selected: props.activeMeasures.includes(measure) }"
t-if="props.add_computed_measures and measure.startsWith('__computed_')"
t-esc="props.measures[measure].string"
closingMode="'none'"
onSelected="() => this.props.onMeasureSelected({ measure: measure_value.name })"
/>
</t>
<DropdownItemCustomMeasure
measures="props.measures"
model="props.model"
t-if="props.add_computed_measures"
/>
</xpath>
</t>
</templates>

View File

@ -0,0 +1,85 @@
/** @odoo-module **/
/* Copyright 2022 Tecnativa - Carlos Roca
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) */
import {registry} from "@web/core/registry";
registry.category("web_tour.tours").add("web_pivot_computed_measure_tour", {
url: "/odoo",
steps: () => [
{
trigger: ".o_navbar_apps_menu button",
run: "click",
},
{
trigger: '.o_app[data-menu-xmlid="base.menu_administration"]',
run: "click",
},
{
trigger: 'button[data-menu-xmlid="base.menu_users"]',
run: "click",
},
{
trigger: 'a[data-menu-xmlid="base.menu_action_res_users"]',
run: "click",
},
{
trigger: "button.o_pivot",
run: "click",
},
{
trigger: '.o_pivot_buttons div[aria-label="Main actions"] button',
run: "click",
},
{
trigger: 'div[data-id="__computed__"] a',
run: "click",
},
{
trigger: "select#computed_measure_field_1",
run() {
this.anchor.value = "user_year_now";
},
},
{
trigger: "select#computed_measure_field_2",
run() {
this.anchor.value = "user_year_born";
},
},
{
trigger: "select#computed_measure_operation",
run() {
this.anchor.value = "m1-m2";
},
},
{
trigger: "select#computed_measure_format",
run() {
this.anchor.value = "integer";
},
},
{
trigger: "button.o_add_computed_measure",
run: "click",
},
{
trigger: 'th.o_pivot_measure_row:contains("User Year Now")',
},
{
trigger: 'div.o_value:contains("2,022")',
},
{
trigger: 'th.o_pivot_measure_row:contains("User Year Born")',
},
{
trigger: 'div.o_value:contains("1,998")',
},
{
trigger: 'th.o_pivot_measure_row:contains("User Year Now-User Year Born")',
},
{
trigger: 'div.o_value:contains("24")',
},
],
});

View File

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

View File

@ -0,0 +1,12 @@
# Copyright 2022 Tecnativa - Carlos Roca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
from odoo import fields, models
class ResUsersFake(models.Model):
_inherit = "res.users"
user_year_born = fields.Integer()
user_year_now = fields.Integer()

View File

@ -0,0 +1,37 @@
# Copyright 2022 Tecnativa - Carlos Roca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
from odoo_test_helper import FakeModelLoader
from odoo.tests import common, tagged
@tagged("post_install", "-at_install")
class TestUIPivot(common.HttpCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.loader = FakeModelLoader(cls.env, cls.__module__)
cls.loader.backup_registry()
from .res_users_fake import ResUsersFake
cls.loader.update_registry((ResUsersFake,))
cls.env["res.users"].create(
{
"name": "User 1",
"login": "us_1",
# Fake fields
"user_year_born": 1998,
"user_year_now": 2022,
}
)
# Set pivot view to company action
action = cls.env.ref("base.action_res_users")
action.view_mode += ",pivot"
def test_ui(self):
self.start_tour(
"/odoo",
"web_pivot_computed_measure_tour",
login="admin",
step_delay=100,
)