diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 000000000..4ad8e0ece --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1 @@ +odoo-test-helper diff --git a/web_pivot_computed_measure.zip b/web_pivot_computed_measure.zip new file mode 100644 index 000000000..0244e21ca Binary files /dev/null and b/web_pivot_computed_measure.zip differ diff --git a/web_pivot_computed_measure/__manifest__.py b/web_pivot_computed_measure/__manifest__.py index 02260c9c7..6ff8fb5ea 100644 --- a/web_pivot_computed_measure/__manifest__.py +++ b/web_pivot_computed_measure/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Web Pivot Computed Measure", "category": "web", - "version": "16.0.1.0.0", + "version": "18.0.1.0.0", "author": "Tecnativa, Odoo Community Association (OCA)", "license": "AGPL-3", "website": "https://github.com/OCA/web", @@ -13,13 +13,17 @@ "maintainers": ["CarlosRoca13"], "assets": { "web.assets_backend": [ - "/web_pivot_computed_measure/static/src/**/*.esm.js", - "/web_pivot_computed_measure/static/src/**/*.scss", - ("remove", "/web_pivot_computed_measure/static/src/test/*.esm.js"), - "/web_pivot_computed_measure/static/src/**/*.xml", + "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", + "web_pivot_computed_measure/static/src/test/test.esm.js", ], }, } diff --git a/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.esm.js b/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.esm.js index e6a9259cd..b19e3ab87 100644 --- a/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.esm.js +++ b/web_pivot_computed_measure/static/src/dropdown_item_custom_measure/dropdown_item_custom_measure.esm.js @@ -17,16 +17,18 @@ export class DropdownItemCustomMeasure extends Component { } addMeasure(ev) { - const $target = $(ev.target).closest("#add_computed_measure_wrapper"); + const target = ev.target.closest("#add_computed_measure_wrapper"); const id = new Date().getTime(); - const field1 = $target.find("#computed_measure_field_1").val(); - const field2 = $target.find("#computed_measure_field_2").val(); - let operation = $target.find("#computed_measure_operation").val(); + 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.find("#computed_measure_operation_custom").val(); + operation = target.querySelector( + "#computed_measure_operation_custom" + ).value; } - const name = $target.find("#computed_measure_name").val(); - const format = $target.find("#computed_measure_format").val(); + const name = target.querySelector("#computed_measure_name").value; + const format = target.querySelector("#computed_measure_format").value; this.props.model.addComputedMeasure( id, field1, @@ -35,8 +37,6 @@ export class DropdownItemCustomMeasure extends Component { name, format ); - // Click on measures button to close the modal and recompute the measures added - $(ev.target).closest(".dropdown").find(".dropdown-toggle").trigger("click"); } } DropdownItemCustomMeasure.template = diff --git a/web_pivot_computed_measure/static/src/pivot/pivot_controller.esm.js b/web_pivot_computed_measure/static/src/pivot/pivot_controller.esm.js index 8fd29a265..6ac0e8e6d 100644 --- a/web_pivot_computed_measure/static/src/pivot/pivot_controller.esm.js +++ b/web_pivot_computed_measure/static/src/pivot/pivot_controller.esm.js @@ -4,9 +4,8 @@ import {PivotController} from "@web/views/pivot/pivot_controller"; import {patch} from "@web/core/utils/patch"; -import {DropdownItemCustomMeasure} from "../dropdown_item_custom_measure/dropdown_item_custom_measure.esm"; -patch(PivotController.prototype, "web_pivot_computed_measure.PivotController", { +patch(PivotController.prototype, { /** * Add computed_measures to context key to avoid loosing info when saving the * filter to favorites. @@ -14,13 +13,8 @@ patch(PivotController.prototype, "web_pivot_computed_measure.PivotController", { * @override */ getContext() { - var res = this._super(...arguments); + var res = super.getContext(...arguments); res.pivot_computed_measures = this.model._computed_measures; return res; }, }); - -PivotController.components = { - ...PivotController.components, - DropdownItemCustomMeasure, -}; diff --git a/web_pivot_computed_measure/static/src/pivot/pivot_model.esm.js b/web_pivot_computed_measure/static/src/pivot/pivot_model.esm.js index 6a2f454c0..c7a2d0e5f 100644 --- a/web_pivot_computed_measure/static/src/pivot/pivot_model.esm.js +++ b/web_pivot_computed_measure/static/src/pivot/pivot_model.esm.js @@ -8,14 +8,14 @@ import {patch} from "@web/core/utils/patch"; import {computeReportMeasures} from "@web/views/utils"; import {evalOperation} from "../helpers/utils.esm"; -patch(PivotModel.prototype, "web_pivot_computed_measure.PivotModel", { +patch(PivotModel.prototype, { /** * Add _computed_measures to avoid recompute them until page is recharged * * @override */ setup() { - this._super(...arguments); + super.setup(...arguments); this._computed_measures = []; }, @@ -31,7 +31,7 @@ patch(PivotModel.prototype, "web_pivot_computed_measure.PivotModel", { * @returns a promise */ addComputedMeasure(id, field1, field2, operation, name, format) { - const measure = _.find(this._computed_measures, (item) => { + const measure = this._computed_measures.find((item) => { return ( item.field1 === field1 && item.field2 === field2 && @@ -92,7 +92,7 @@ patch(PivotModel.prototype, "web_pivot_computed_measure.PivotModel", { // Used to know if is a computed measure field __computed_id: cmDef.id, // Operator used for group the measure added. - group_operator: "sum", + aggregator: "sum", }; const metaData = (config && config.metaData) || this.metaData; metaData.measures[cmDef.id] = arrFields[cmDef.id]; @@ -133,7 +133,7 @@ patch(PivotModel.prototype, "web_pivot_computed_measure.PivotModel", { (config && config.metaData.activeMeasures) || this.metaData.activeMeasures || []; - return _.contains(activeMeasures, field); + return activeMeasures.includes(field); }, /** @@ -148,7 +148,6 @@ patch(PivotModel.prototype, "web_pivot_computed_measure.PivotModel", { if (subGroupData.__count === 0) { subGroupData[cm.id] = false; } else { - subGroupData[cm.id] = evalOperation(cm.operation, subGroupData); } } @@ -165,7 +164,7 @@ patch(PivotModel.prototype, "web_pivot_computed_measure.PivotModel", { this._fillComputedMeasuresData(subGroup, config); } } - this._super(...arguments); + super._prepareData(...arguments); }, /** @@ -177,16 +176,16 @@ patch(PivotModel.prototype, "web_pivot_computed_measure.PivotModel", { * * @override */ - _getGroupSubdivision(group, rowGroupBy, colGroupBy, config) { + async _getGroupSubdivision(group, rowGroupBy, colGroupBy, config) { const computed_measures = []; - for (let i = 0; i < config.metaData.activeMeasures.length; i++) - if (config.metaData.activeMeasures[i].startsWith("__computed_")) { - computed_measures.push(config.metaData.activeMeasures[i]); - config.metaData.activeMeasures.splice(i, 1); + 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 = this._super(...arguments); - $.merge(config.metaData.activeMeasures, computed_measures); + const res = await super._getGroupSubdivision(...arguments); + Object.assign(config.measureSpecs, computed_measures); return res; }, @@ -199,7 +198,7 @@ patch(PivotModel.prototype, "web_pivot_computed_measure.PivotModel", { toggleMeasure(fieldName) { if (this._isMeasureEnabled(fieldName)) { // Mesaure is enabled - const umeasures = _.filter(this._computed_measures, (item) => { + const umeasures = this._computed_measures.filter((item) => { return item.field1 === fieldName || item.field2 === fieldName; }); if (umeasures.length && this._isMeasureEnabled(umeasures[0].id)) { @@ -219,8 +218,8 @@ patch(PivotModel.prototype, "web_pivot_computed_measure.PivotModel", { const fieldDef = this.metaData.fields[afield]; // Need to check if fieldDef exists to avoid problems with __count if (fieldDef && fieldDef.__computed_id) { - const cm = _.find(this._computed_measures, { - id: fieldDef.__computed_id, + const cm = this._computed_measures.find((item) => { + return item.id === fieldDef.__computed_id; }); toAnalyze.push(cm.field1, cm.field2); const toEnableFields = []; @@ -238,11 +237,11 @@ patch(PivotModel.prototype, "web_pivot_computed_measure.PivotModel", { this._activeMeasures( // Transform the array of arrays to a simple array. // [1, [2, 3]] => [1, 2, 3] - _.flatten(toEnable.reverse()) + toEnable.reverse().flat(Infinity) ); } } - return this._super(...arguments); + return super.toggleMeasure(...arguments); }, /** * Load the measures added to selected favorite filters @@ -250,7 +249,7 @@ patch(PivotModel.prototype, "web_pivot_computed_measure.PivotModel", { * @override */ async load(searchParams) { - var _super = this._super.bind(this); + var _super = super.load.bind(this); var config = {metaData: this.metaData, data: this.data}; if (!this.metaData.measures) { const metaData = this._buildMetaData(); @@ -278,15 +277,14 @@ patch(PivotModel.prototype, "web_pivot_computed_measure.PivotModel", { for (const fieldName of fieldNames) { const field = this.metaData.fields[fieldName]; if (field.__computed_id) { - const cm = _.find(this._computed_measures, { - id: 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 = _.without( - this.metaData.activeMeasures, - fieldName + this.metaData.activeMeasures = this.metaData.activeMeasures.filter( + (item) => item !== fieldName ); } } diff --git a/web_pivot_computed_measure/static/src/pivot/pivot_renderer.esm.js b/web_pivot_computed_measure/static/src/pivot/pivot_renderer.esm.js index 3987dc852..3598cb548 100644 --- a/web_pivot_computed_measure/static/src/pivot/pivot_renderer.esm.js +++ b/web_pivot_computed_measure/static/src/pivot/pivot_renderer.esm.js @@ -5,11 +5,11 @@ import {PivotRenderer} from "@web/views/pivot/pivot_renderer"; import {patch} from "@web/core/utils/patch"; -patch(PivotRenderer.prototype, "web_pivot_computed_measure.PivotRenderer", { +patch(PivotRenderer.prototype, { getFormattedValue(cell) { if (cell.value === Infinity) { return "-"; } - return this._super(...arguments); + return super.getFormattedValue(...arguments); }, }); diff --git a/web_pivot_computed_measure/static/src/pivot/pivot_view.xml b/web_pivot_computed_measure/static/src/pivot/pivot_view.xml index 4027ce8c5..4e46243f3 100644 --- a/web_pivot_computed_measure/static/src/pivot/pivot_view.xml +++ b/web_pivot_computed_measure/static/src/pivot/pivot_view.xml @@ -1,9 +1,9 @@ - - - - + + + true + model diff --git a/web_pivot_computed_measure/static/src/report_view_measures/report_view_measures.esm.js b/web_pivot_computed_measure/static/src/report_view_measures/report_view_measures.esm.js new file mode 100644 index 000000000..e519e89d7 --- /dev/null +++ b/web_pivot_computed_measure/static/src/report_view_measures/report_view_measures.esm.js @@ -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}, +}; diff --git a/web_pivot_computed_measure/static/src/report_view_measures/report_view_measures.xml b/web_pivot_computed_measure/static/src/report_view_measures/report_view_measures.xml new file mode 100644 index 000000000..6e6358221 --- /dev/null +++ b/web_pivot_computed_measure/static/src/report_view_measures/report_view_measures.xml @@ -0,0 +1,29 @@ + + + + + !measure.startsWith('__computed_') + + +