diff --git a/pos_sale_order_print/__manifest__.py b/pos_sale_order_print/__manifest__.py index 6a22c48ad7..ebf5adf2a4 100644 --- a/pos_sale_order_print/__manifest__.py +++ b/pos_sale_order_print/__manifest__.py @@ -17,6 +17,9 @@ "pos_sale_order_print/static/src/js/pos_sale_order_print.esm.js", "pos_sale_order_print/static/src/js/SaleOrderManagementScreen.esm.js", ], + "web.assets_tests": [ + "pos_sale_order_print/static/tests/tours/**/*", + ], }, "license": "AGPL-3", } diff --git a/pos_sale_order_print/static/src/js/SaleOrderManagementScreen.esm.js b/pos_sale_order_print/static/src/js/SaleOrderManagementScreen.esm.js index 69147db78d..c715458294 100644 --- a/pos_sale_order_print/static/src/js/SaleOrderManagementScreen.esm.js +++ b/pos_sale_order_print/static/src/js/SaleOrderManagementScreen.esm.js @@ -34,7 +34,40 @@ const PrintSaleOrderManagementScreen = (OriginalSaleOrderManagementScreen) => } ); - // Show a selection popup for the user to choose what to print + if (printActions.length === 0) { + this.showPopup("ErrorPopup", { + title: this.env._t("Print Error"), + body: this.env._t( + "Please choose which sale orders to print in the POS sales configuration." + ), + }); + return {confirmed, payload}; + } + + if (printActions.length === 1) { + try { + await this.env.legacyActionManager.do_action( + printActions[0], + { + additional_context: { + active_ids: [this.clickedOrder.id], + }, + } + ); + } catch (error) { + if (error instanceof Error) { + throw error; + } else { + this.showPopup("ErrorPopup", { + title: this.env._t("Network Error"), + body: this.env._t("Unable to download the report."), + }); + } + } + return {confirmed, payload}; + } + + // Two or more reports configured: keep the selection popup. const {confirmed: popupConfirmed, payload: popupSelectedOption} = await this.showPopup("SelectionPopup", { title: this.env._t("What do you want to print?"), diff --git a/pos_sale_order_print/static/tests/tours/print_single_skip_tour.js b/pos_sale_order_print/static/tests/tours/print_single_skip_tour.js new file mode 100644 index 0000000000..5a8514e29d --- /dev/null +++ b/pos_sale_order_print/static/tests/tours/print_single_skip_tour.js @@ -0,0 +1,131 @@ +/** @odoo-module **/ + +import {ErrorPopup} from "point_of_sale.tour.ErrorPopupTourMethods"; +import {getSteps, startSteps} from "point_of_sale.tour.utils"; +import {ProductScreen} from "pos_sale.tour.ProductScreenTourMethods"; +import {SelectionPopup} from "point_of_sale.tour.SelectionPopupTourMethods"; +import tour from "web_tour.tour"; + +// Tour 1 — 1 inform configured, direct action +startSteps(); + +ProductScreen.do.confirmOpeningPopup(); +getSteps().push({ + content: "Click Quotation/Order button to open SaleOrderManagementScreen", + trigger: ".control-button.o_sale_order_button", + timeout: 2000, + run: "click", +}); + +getSteps().push({ + content: "Select first sale order from SaleOrderManagementScreen", + trigger: ".order-management-screen .order-list .order-row:first", + run: "click", +}); +getSteps().push({ + content: "Wait until popup selection is loaded", + trigger: ".modal-dialog .popup-selection", + timeout: 5000, + // eslint-disable-next-line no-empty-function + run: () => {}, +}); +getSteps().push({ + content: "Click Print option", + trigger: + ".modal-dialog .popup-selection .selection-item:contains('Print')", + run: "click", +}); +getSteps().push({ + content: "Assert SelectionPopup is NOT shown (do_action invoked directly)", + trigger: ".order-management-screen", + run: function () { + const popup = document.querySelector(".modal-dialog .popup-selection"); + if (popup) { + throw new Error( + "SelectionPopup MUST NOT render when only one report is configured" + ); + } + }, +}); + +tour.register( + "print_single_report_direct_action_tour_oca", + {test: true, url: "/pos/ui"}, + getSteps() +); + +// Tour 2 — 2 informs configured, SelectionPopup +startSteps(); +ProductScreen.do.confirmOpeningPopup(); +getSteps().push({ + content: "Click Quotation/Order button to open SaleOrderManagementScreen", + trigger: ".control-button.o_sale_order_button", + run: "click", +}); + +getSteps().push({ + content: "Select first sale order from SaleOrderManagementScreen", + trigger: ".order-management-screen .order-list .order-row:first", + run: "click", +}); +getSteps().push({ + content: "Wait until popup selection is loaded", + trigger: ".modal-dialog .popup-selection", + timeout: 5000, + // eslint-disable-next-line no-empty-function + run: () => {}, +}); +getSteps().push({ + content: "Click Print option", + trigger: + ".modal-dialog .popup-selection .selection-item:contains('Print')", + run: "click", +}); + +SelectionPopup.check.isShown(); +SelectionPopup.check.hasSelectionItem("Test Report A"); +SelectionPopup.check.hasSelectionItem("Test Report B"); +SelectionPopup.do.clickItem("Test Report B"); + +tour.register( + "print_multi_report_selection_tour_oca", + {test: true, url: "/pos/ui"}, + getSteps() +); + +// Tour 3 — 0 informs configured, ErrorPopup +startSteps(); + +ProductScreen.do.confirmOpeningPopup(); +getSteps().push({ + content: "Click Quotation/Order button to open SaleOrderManagementScreen", + trigger: ".control-button.o_sale_order_button", + timeout: 2000, + run: "click", +}); + +getSteps().push({ + content: "Select first sale order from SaleOrderManagementScreen", + trigger: ".order-management-screen .order-list .order-row:first", + run: "click", +}); +getSteps().push({ + content: "Wait until popup selection is loaded", + trigger: ".modal-dialog .popup-selection", + timeout: 5000, + // eslint-disable-next-line no-empty-function + run: () => {}, +}); +getSteps().push({ + content: "Click Print option", + trigger: + ".modal-dialog .popup-selection .selection-item:contains('Print')", + run: "click", +}); +ErrorPopup.check.isShown(); + +tour.register( + "print_no_reports_error_popup_tour_oca", + {test: true, url: "/pos/ui"}, + getSteps() +); diff --git a/pos_sale_order_print/tests/__init__.py b/pos_sale_order_print/tests/__init__.py new file mode 100644 index 0000000000..be8118a027 --- /dev/null +++ b/pos_sale_order_print/tests/__init__.py @@ -0,0 +1 @@ +from . import test_print_single_skip diff --git a/pos_sale_order_print/tests/test_print_single_skip.py b/pos_sale_order_print/tests/test_print_single_skip.py new file mode 100644 index 0000000000..09a8a7670c --- /dev/null +++ b/pos_sale_order_print/tests/test_print_single_skip.py @@ -0,0 +1,73 @@ +from odoo.tests import tagged + +from odoo.addons.point_of_sale.tests.test_frontend import TestPointOfSaleHttpCommon + + +@tagged("post_install", "-at_install") +class TestPrintSingleSkipOCA(TestPointOfSaleHttpCommon): + def setUp(self): + super().setUp() + partner = self.env["res.partner"].search([], limit=1) + self.order = self.env["sale.order"].create({"partner_id": partner.id}) + self.order.action_confirm() + + def test01_print_single_skip_popup(self): + report = self.env["ir.actions.report"].create( + { + "name": "Test Report A", + "model": "sale.order", + "report_name": "report", + } + ) + self.main_pos_config.write( + { + "print_sales_order_ids": [(6, 0, [report.id])], + } + ) + self.main_pos_config.open_ui() + self.start_tour( + "/pos/ui?config_id=%d" % self.main_pos_config.id, + "print_single_report_direct_action_tour_oca", + login="accountman", + ) + + def test02_print_multiple_shows_popup(self): + report_a = self.env["ir.actions.report"].create( + { + "name": "Test Report A", + "model": "sale.order", + "report_name": "report A", + } + ) + report_b = self.env["ir.actions.report"].create( + { + "name": "Test Report B", + "model": "sale.order", + "report_name": "report B", + } + ) + self.main_pos_config.write( + { + "print_sales_order_ids": [(6, 0, [report_a.id, report_b.id])], + } + ) + self.main_pos_config.open_ui() + self.start_tour( + "/pos/ui?config_id=%d" % self.main_pos_config.id, + "print_multi_report_selection_tour_oca", + login="accountman", + ) + + def test03_no_print_config_shows_error(self): + partner = self.env["res.partner"].search([], limit=1) + self.env["sale.order"].create( + { + "partner_id": partner.id, + } + ) + self.main_pos_config.open_ui() + self.start_tour( + "/pos/ui?config_id=%d" % self.main_pos_config.id, + "print_no_reports_error_popup_tour_oca", + login="accountman", + )