forked from Techsystech/web
[IMP] web_pivot_computed_measure: Function that eval operations
parent
c5f5c7274d
commit
1529a7bf93
|
@ -7,7 +7,7 @@ Web Pivot Computed Measure
|
||||||
!! This file is generated by oca-gen-addon-readme !!
|
!! This file is generated by oca-gen-addon-readme !!
|
||||||
!! changes will be overwritten. !!
|
!! changes will be overwritten. !!
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
!! source digest: sha256:ece4336d91177883eff784573de23cd6a67b1044e080eb758f7de5e6374d57f0
|
!! source digest: sha256:34691d378ce32fade67311831059070fab3df66f5cb2ec7fa88287018b85de7b
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
|
||||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
{
|
{
|
||||||
"name": "Web Pivot Computed Measure",
|
"name": "Web Pivot Computed Measure",
|
||||||
"category": "web",
|
"category": "web",
|
||||||
"version": "15.0.1.0.2",
|
"version": "15.0.1.0.3",
|
||||||
"author": "Tecnativa, Odoo Community Association (OCA)",
|
"author": "Tecnativa, Odoo Community Association (OCA)",
|
||||||
"license": "AGPL-3",
|
"license": "AGPL-3",
|
||||||
"website": "https://github.com/OCA/web",
|
"website": "https://github.com/OCA/web",
|
||||||
|
|
|
@ -367,7 +367,7 @@ ul.auto-toc {
|
||||||
!! This file is generated by oca-gen-addon-readme !!
|
!! This file is generated by oca-gen-addon-readme !!
|
||||||
!! changes will be overwritten. !!
|
!! changes will be overwritten. !!
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
!! source digest: sha256:ece4336d91177883eff784573de23cd6a67b1044e080eb758f7de5e6374d57f0
|
!! source digest: sha256:34691d378ce32fade67311831059070fab3df66f5cb2ec7fa88287018b85de7b
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||||
<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/15.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-15-0/web-15-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&target_branch=15.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
|
<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/15.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-15-0/web-15-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&target_branch=15.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>Adds support for computed measures on the pivot view.</p>
|
||||||
|
|
|
@ -1,27 +1,124 @@
|
||||||
/** @odoo-module **/
|
/** @odoo-module **/
|
||||||
/* Copyright 2022 Tecnativa - Carlos Roca
|
/* Copyright 2023 Tecnativa - Carlos Roca
|
||||||
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) */
|
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to eval text for a given object
|
* Function that traverse the text given character by character
|
||||||
*
|
*
|
||||||
* @param {String} text
|
* @param {String} text
|
||||||
* @param {Object} vals
|
* @returns {Array}
|
||||||
* @returns {any}
|
|
||||||
*/
|
*/
|
||||||
export const evalOperation = (text, vals) => {
|
function getTokensFromText(text) {
|
||||||
for (const variable in vals) {
|
const symbols = ["+", "-", "*", "/", "(", ")"];
|
||||||
if (vals.hasOwnProperty(variable)) {
|
const tokens = [];
|
||||||
const regex = new RegExp(variable, "g");
|
let token = "";
|
||||||
text = text.replace(regex, vals[variable]);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
if (token !== "") {
|
||||||
// eslint-disable-next-line no-eval
|
tokens.push(token);
|
||||||
const res = eval(text);
|
|
||||||
return res;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error trying to eval operation:", error);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
};
|
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();
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue