From b6612fca6914f497e7fe1b15c0bc42e79dede434 Mon Sep 17 00:00:00 2001 From: luvi Date: Sun, 8 Jan 2023 22:38:50 +0000 Subject: [PATCH] [FIX] web: fix ids to export with selected domain This commit fixes the export when all records are selected (full domain). Since many records ids might be present when an entire domain is selected, the request should contains 'false' instead of a list of ids. As a limit is set in session.active_ids_limit, not all the records were considered. This means that only the limit was actually exported instead of the full list that is present. As the legacy implementation of the ExportDialog allowed to export all records, the behavior has been fixed. A test has been added to verify the correct parameter during the download call. closes odoo/odoo#110126 X-original-commit: 7200e1c5875bc148fb64187fd67d58a7d6c13c7c Signed-off-by: Aaron Bohy (aab) --- .../static/src/views/list/list_controller.js | 10 +- .../view_dialogs/export_data_dialog_tests.js | 148 +++++++++++++++--- 2 files changed, 128 insertions(+), 30 deletions(-) diff --git a/addons/web/static/src/views/list/list_controller.js b/addons/web/static/src/views/list/list_controller.js index 3cf91d143fb..4f81794fcb9 100644 --- a/addons/web/static/src/views/list/list_controller.js +++ b/addons/web/static/src/views/list/list_controller.js @@ -356,7 +356,11 @@ export class ListController extends Component { } async downloadExport(fields, import_compat, format) { - const resIds = await this.getSelectedResIds(); + let ids = false; + if (!this.isDomainSelected) { + const resIds = await this.getSelectedResIds(); + ids = resIds.length > 0 && resIds; + } const exportedFields = fields.map((field) => ({ name: field.name || field.id, label: field.label || field.string, @@ -374,7 +378,7 @@ export class ListController extends Component { domain: this.model.root.domain, fields: exportedFields, groupby: this.model.root.groupBy, - ids: resIds.length > 0 && resIds, + ids, model: this.model.root.resModel, }), }, @@ -396,9 +400,7 @@ export class ListController extends Component { * @private */ async onExportData() { - const resIds = await this.getSelectedResIds(); const dialogProps = { - resIds, context: this.props.context, defaultExportList: this.defaultExportList, download: this.downloadExport.bind(this), diff --git a/addons/web/static/tests/views/view_dialogs/export_data_dialog_tests.js b/addons/web/static/tests/views/view_dialogs/export_data_dialog_tests.js index fabe116c782..b9486cda760 100644 --- a/addons/web/static/tests/views/view_dialogs/export_data_dialog_tests.js +++ b/addons/web/static/tests/views/view_dialogs/export_data_dialog_tests.js @@ -612,37 +612,38 @@ QUnit.module("ViewDialogs", (hooks) => { }); QUnit.test("Export dialog: export list with 'exportable: false'", async function (assert) { - (serverData.models.partner.fields.not_exportable = { + serverData.models.partner.fields.not_exportable = { string: "Not exportable", type: "char", exportable: false, - }), - (serverData.models.partner.fields.exportable = { string: "Exportable", type: "char" }), - await makeView({ - serverData, - type: "list", - resModel: "partner", - arch: ` - - - - `, - actionMenus: {}, - mockRPC(route, args) { - if (route === "/web/export/formats") { - return Promise.resolve([{ tag: "csv", label: "CSV" }]); + }; + serverData.models.partner.fields.exportable = { string: "Exportable", type: "char" }; + + await makeView({ + serverData, + type: "list", + resModel: "partner", + arch: ` + + + + `, + actionMenus: {}, + mockRPC(route, args) { + if (route === "/web/export/formats") { + return Promise.resolve([{ tag: "csv", label: "CSV" }]); + } + if (route === "/web/export/get_fields") { + if (!args.parent_field) { + return Promise.resolve(fetchedFields.root); } - if (route === "/web/export/get_fields") { - if (!args.parent_field) { - return Promise.resolve(fetchedFields.root); - } - if (args.prefix === "partner_ids") { - assert.step("fetch fields for 'partner_ids'"); - } - return Promise.resolve(fetchedFields[args.prefix]); + if (args.prefix === "partner_ids") { + assert.step("fetch fields for 'partner_ids'"); } - }, - }); + return Promise.resolve(fetchedFields[args.prefix]); + } + }, + }); await openExportDataDialog(); assert.containsN(target, ".o_export_field", 2, "only two fields are selected in the list"); @@ -728,6 +729,101 @@ QUnit.module("ViewDialogs", (hooks) => { ); }); + QUnit.test("ExportDialog: export all records of the domain", async function (assert) { + assert.expect(2); + let isDomainSelected = false; + + mockDownload(({ data }) => { + if (isDomainSelected) { + assert.deepEqual( + JSON.parse(data.data), + { + context: { lang: "en", uid: 7, tz: "taht" }, + model: "partner", + domain: [["bar", "!=", "glou"]], + groupby: [], + ids: false, + import_compat: false, + fields: [ + { + name: "foo", + label: "Foo", + type: "char", + }, + { + name: "bar", + label: "Bar", + type: "boolean", + }, + ], + }, + "should be called with correct params when all records are selected" + ); + } else { + assert.deepEqual( + JSON.parse(data.data), + { + context: { lang: "en", uid: 7, tz: "taht" }, + model: "partner", + domain: [["bar", "!=", "glou"]], + groupby: [], + ids: [1], + import_compat: false, + fields: [ + { + name: "foo", + label: "Foo", + type: "char", + }, + { + name: "bar", + label: "Bar", + type: "boolean", + }, + ], + }, + "should be called with correct params when only one record is selected" + ); + } + return Promise.resolve(); + }); + + await makeView({ + serverData, + type: "list", + resModel: "partner", + arch: ` + + + + `, + actionMenus: {}, + domain: [["bar", "!=", "glou"]], + mockRPC(route) { + if (route === "/web/export/formats") { + return Promise.resolve([{ tag: "xls", label: "Excel" }]); + } + if (route === "/web/export/get_fields") { + return Promise.resolve(fetchedFields.root); + } + }, + }); + + await openExportDataDialog(); + await click(target.querySelector(".o_select_button")); + await click(target.querySelector(".btn-close")); + + isDomainSelected = true; + await click(target.querySelector(".o_list_select_domain")); + await click(target.querySelector(".o_control_panel .o_cp_action_menus .dropdown-toggle")); + await click( + target.querySelector( + ".o_control_panel .o_cp_action_menus .dropdown-menu span:first-child" + ) + ); + await click(target.querySelector(".o_select_button")); + }); + QUnit.test("Direct export list", async function (assert) { assert.expect(2);