From ef11a898997c921efbac277c1cbcb6bcf349eaaa Mon Sep 17 00:00:00 2001 From: "Hubert Van de Walle (huvw)" Date: Mon, 31 Jul 2023 15:08:17 +0000 Subject: [PATCH] [FIX] point_of_sale: hide cash move button for users without permission Steps to reproduce ================== - Remove the Accounting/Billing permission from Marc Demo - Login as Marc Demo - Start a POS session - Click on "Cash In/Out" An error occurs because the user doesn't have the appropriate permission Solution ======== Add a key `has_cash_move_permission` in the pos config. Set it to the presence/absence of the group `account.group_account_invoice`. If the permission is missing, hide the "Cash In/Out" button. opw-3333622 closes odoo/odoo#133444 X-original-commit: 62ea247953e5d8e81b3af7d4bbde3ec2ffb49f19 Signed-off-by: Robin Heinz (rhe) Signed-off-by: Hubert Van De Walle --- addons/point_of_sale/models/pos_session.py | 1 + .../static/src/app/navbar/navbar.js | 2 +- .../static/tests/tours/Chrome.tour.js | 8 +++++-- .../ChromeWithoutCashMovePermission.tour.js | 20 ++++++++++++++++ .../tests/tours/helpers/ChromeTourMethods.js | 24 ++++++++++++++++++- addons/point_of_sale/tests/test_frontend.py | 14 ++++++++++- 6 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 addons/point_of_sale/static/tests/tours/ChromeWithoutCashMovePermission.tour.js diff --git a/addons/point_of_sale/models/pos_session.py b/addons/point_of_sale/models/pos_session.py index d739ea45545..637f51c5bf3 100644 --- a/addons/point_of_sale/models/pos_session.py +++ b/addons/point_of_sale/models/pos_session.py @@ -1829,6 +1829,7 @@ class PosSession(models.Model): config = self.env['pos.config'].search_read(**params['search_params'])[0] config['use_proxy'] = config['is_posbox'] and (config['iface_electronic_scale'] or config['iface_print_via_proxy'] or config['iface_scan_via_proxy'] or config['iface_customer_facing_display_via_proxy']) + config['has_cash_move_permission'] = self.user_has_groups('account.group_account_invoice') return config def _loader_params_pos_bill(self): diff --git a/addons/point_of_sale/static/src/app/navbar/navbar.js b/addons/point_of_sale/static/src/app/navbar/navbar.js index 36378c6c1d2..6507f853275 100644 --- a/addons/point_of_sale/static/src/app/navbar/navbar.js +++ b/addons/point_of_sale/static/src/app/navbar/navbar.js @@ -49,7 +49,7 @@ export class Navbar extends Component { return this.pos.config.iface_customer_facing_display; } get showCashMoveButton() { - return Boolean(this.pos?.config?.cash_control); + return Boolean(this.pos?.config?.cash_control && this.pos?.config?.has_cash_move_permission); } onCashMoveButtonClick() { this.hardwareProxy.openCashbox(_t("Cash in / out")); diff --git a/addons/point_of_sale/static/tests/tours/Chrome.tour.js b/addons/point_of_sale/static/tests/tours/Chrome.tour.js index 9d1cad8dbd7..5818eaf6175 100644 --- a/addons/point_of_sale/static/tests/tours/Chrome.tour.js +++ b/addons/point_of_sale/static/tests/tours/Chrome.tour.js @@ -15,9 +15,13 @@ registry url: "/pos/ui", steps: () => { startSteps(); - - // Order 1 is at Product Screen + ProductScreen.do.confirmOpeningPopup(); + Chrome.do.clickMenuButton(); + Chrome.check.isCashMoveButtonShown(); + Chrome.do.clickMenuButton(); + + // Order 1 is at Product Screen ProductScreen.do.clickHomeCategory(); ProductScreen.exec.addOrderline("Desk Pad", "1", "2", "2.0"); Chrome.do.clickMenuButton(); diff --git a/addons/point_of_sale/static/tests/tours/ChromeWithoutCashMovePermission.tour.js b/addons/point_of_sale/static/tests/tours/ChromeWithoutCashMovePermission.tour.js new file mode 100644 index 00000000000..46087c55c7a --- /dev/null +++ b/addons/point_of_sale/static/tests/tours/ChromeWithoutCashMovePermission.tour.js @@ -0,0 +1,20 @@ +/** @odoo-module **/ + +import { Chrome } from "@point_of_sale/../tests/tours/helpers/ChromeTourMethods"; +import { ProductScreen } from "@point_of_sale/../tests/tours/helpers/ProductScreenTourMethods"; +import { getSteps, startSteps } from "@point_of_sale/../tests/tours/helpers/utils"; +import { registry } from "@web/core/registry"; + +registry.category("web_tour.tours").add("chrome_without_cash_move_permission", { + test: true, + url: "/pos/ui", + steps: () => { + startSteps(); + + ProductScreen.do.confirmOpeningPopup(); + Chrome.do.clickMenuButton(); + Chrome.check.isCashMoveButtonHidden(); + + return getSteps(); + }, +}); diff --git a/addons/point_of_sale/static/tests/tours/helpers/ChromeTourMethods.js b/addons/point_of_sale/static/tests/tours/helpers/ChromeTourMethods.js index c0bf6b1ac01..7bf140e7fa8 100644 --- a/addons/point_of_sale/static/tests/tours/helpers/ChromeTourMethods.js +++ b/addons/point_of_sale/static/tests/tours/helpers/ChromeTourMethods.js @@ -49,6 +49,28 @@ class Do { ]; } } + +class Check { + isCashMoveButtonHidden() { + return [ + { + extraTrigger: ".pos-topheader", + trigger: ".pos-topheader:not(:contains(Cash In/Out))", + run: () => {}, + }, + ]; + } + + isCashMoveButtonShown() { + return [ + { + trigger: ".pos-topheader:contains(Cash In/Out)", + run: () => {}, + }, + ]; + } +} + // FIXME: this is a horrible hack to export an object as named exports. // eslint-disable-next-line no-undef -Object.assign(__exports, createTourMethods("Chrome", Do)); +Object.assign(__exports, createTourMethods("Chrome", Do, Check)); diff --git a/addons/point_of_sale/tests/test_frontend.py b/addons/point_of_sale/tests/test_frontend.py index 002b2148dfb..80aa156a74b 100644 --- a/addons/point_of_sale/tests/test_frontend.py +++ b/addons/point_of_sale/tests/test_frontend.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo import tools +from odoo import Command from odoo.api import Environment from odoo.tools import DEFAULT_SERVER_DATE_FORMAT from odoo.addons.account.tests.common import AccountTestInvoicingHttpCommon @@ -894,6 +894,18 @@ class TestUi(TestPointOfSaleHttpCommon): self.main_pos_config.with_user(self.pos_user).open_ui() self.start_tour("/pos/ui?config_id=%d" % self.main_pos_config.id, 'ShowTaxExcludedTour', login="pos_user") + def test_chrome_without_cash_move_permission(self): + self.env.user.write({'groups_id': [ + Command.set( + [ + self.env.ref('base.group_user').id, + self.env.ref('point_of_sale.group_pos_user').id, + ] + ) + ]}) + self.main_pos_config.open_ui() + self.start_tour("/pos/ui?config_id=%d" % self.main_pos_config.id, 'chrome_without_cash_move_permission', login="accountman") + # This class just runs the same tests as above but with mobile emulation class MobileTestUi(TestUi): browser_size = '375x667'