Ir al contenido
Menú
Se marcó esta pregunta
2 Respuestas
380 Vistas

Problem:

I'm trying to disable the POS discount button for users without the proper group permissions, but my implementation either:

  1. The cashier object is undefined when checking permissions
  2. The button either shows for all users or is disabled for everyone

Current Implementation:

1. JavaScript Patch (PosAccessRight.js):

patch(ProductScreen.prototype, {
    getNumpadButtons() {
        const originalButtons = super.getNumpadButtons();
        try {
            const pos = this.env.services.pos;
            const cashier = pos.globalState?.get_cashier() || pos.globalState?.cashier;
            const hasDiscountGroup = cashier?.hasGroupDiscount || false;
            
            return originalButtons.map(button => ({
                ...button,
                ...((button.value === "discount" || button.value === "price") && {
                    disabled: !hasDiscountGroup
                })
            }));
        } catch (error) {
            console.error("Button modification failed:", error);
            return originalButtons;
        }
    }
});

2. Python Extension (res_users.py):

class ResUsers(models.Model):
    _inherit = 'res.users'
    
    def _load_pos_data(self, data):
        res = super()._load_pos_data(data)
        user = self.env["res.users"].browse(res["data"][0]["id"])
        res["data"][0]["hasGroupDiscount"] = user.has_group('pos_access_right.group_discount')
        return res

Key Questions:

  1. Why is pos.globalState.cashier undefined during button rendering?
  2. What's the correct way to access the logged-in cashier's permissions in Odoo 18 POS?
  3. Where should I properly check group permissions if not in getNumpadButtons?

Environment:

  • Odoo 18.0 Community
  • Custom POS module (depends on point_of_sale)
  • PostgreSQL 13 / Ubuntu 20.04
  • Chrome 


Avatar
Descartar
Autor Mejor respuesta

Avatar
Descartar
Mejor respuesta

Issues

  1. pos.globalState.get_cashier() is undefined:
    • The cashier object is populated only after the POS session is fully loaded and a user is logged in.
    • If you're patching getNumpadButtons() too early (before the cashier is set), the cashier object will be undefined.
  2. Why the button shows for all or none:
    • Because you're relying on cashier.hasGroupDiscount, and if cashier is undefined, your fallback disables the logic or treats all users the same.

You should defer the permission check to runtime and not during the initial button setup, or ensure the cashier object is guaranteed to be available before patching.

Fix: Check cashier in setup() or use reactive model

Instead of patching getNumpadButtons(), consider overriding the setup() method and dynamically updating the button state once the cashier is available. Like this:

import { patch } from "@web/core/utils/patch"; import { ProductScreen } from "@point_of_sale/app/screens/product_screen/product_screen"; patch(ProductScreen.prototype, { setup() { super.setup(); this.env.services.pos.bus.on('cashier-changed', null, () => { this.render(); // re-render when cashier changes }); }, get numpadButtons() { const buttons = super.numpadButtons; const cashier = this.env.services.pos.get_cashier?.() || null; const hasGroupDiscount = cashier?.hasGroupDiscount || false; return buttons.map(button => { if (["discount", "price"].includes(button.value)) { return { ...button, disabled: !hasGroupDiscount, }; } return button; }); }, });

Python Fix: Ensure field is loaded to POS user data

Your Python code seems mostly correct, but verify the custom group external ID is correct and ensure it's added to the loaded user data:

python

CopiarEditar

class ResUsers(models.Model): _inherit = 'res.users' def _load_pos_data(self, data): res = super()._load_pos_data(data) for record in res["data"]: user = self.browse(record["id"]) record["hasGroupDiscount"] = user.has_group('pos_access_right.group_discount') return res

Also, confirm that hasGroupDiscount is being passed to the JS frontend via the POS session config and is accessible in the cashier object.

Group Access Configuration

Make sure:

  • Your custom group group_discount exists and has the correct external ID (pos_access_right.group_discount).
  • POS users are correctly added to the group via Settings > Users > Access Rights.

Avatar
Descartar
Autor

Thank you for your suggested solution! I implemented your approach, but encountered an error : TypeError: this.env.services.pos.bus.on is not a function

Publicaciones relacionadas Respuestas Vistas Actividad
0
jun 25
312
0
abr 25
841
2
ene 25
1156
2
feb 24
12459
2
dic 24
1278