From 335e1c39ac898191dbdbfb78b3a28878974c1766 Mon Sep 17 00:00:00 2001 From: niyp-odoo Date: Wed, 30 Jul 2025 18:32:42 +0530 Subject: [PATCH] [ADD] pos_receipt: enable flexible and user-friendly receipt customization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change introduces a user-centric framework for customizing POS receipt layouts, addressing the need for more flexible and visually appealing print formats. By allowing businesses to configure receipt appearance and content—such as layout styles, headers, footers, and logos—directly from POS settings or via a dedicated wizard, we significantly improve the adaptability of the POS module to various branding requirements. The enhancements also make receipt previews more intuitive, helping users visualize changes in real time and promoting better alignment between digital and physical touchpoints. These changes aim to improve usability, maintain consistency in receipt formatting across sessions, and offer a more intuitive configuration workflow aligned with real-world operational needs. --- pos_receipt/__init__.py | 2 + pos_receipt/__manifest__.py | 20 ++ pos_receipt/models/__init__.py | 2 + pos_receipt/models/pos_config.py | 13 + pos_receipt/models/res_config_settings.py | 17 + pos_receipt/security/ir.model.access.csv | 2 + .../static/src/order_receipt_inherit.js | 22 ++ .../static/src/order_receipt_inherit.xml | 329 ++++++++++++++++++ pos_receipt/views/boxes_receipt.xml | 76 ++++ pos_receipt/views/light_receipt.xml | 37 ++ pos_receipt/views/lined_receipt.xml | 105 ++++++ .../views/res_config_settings_view.xml | 18 + pos_receipt/wizard/__init__.py | 1 + pos_receipt/wizard/pos_receipt_wizard.py | 55 +++ .../wizard/pos_receipt_wizard_views.xml | 29 ++ 15 files changed, 728 insertions(+) create mode 100644 pos_receipt/__init__.py create mode 100644 pos_receipt/__manifest__.py create mode 100644 pos_receipt/models/__init__.py create mode 100644 pos_receipt/models/pos_config.py create mode 100644 pos_receipt/models/res_config_settings.py create mode 100644 pos_receipt/security/ir.model.access.csv create mode 100644 pos_receipt/static/src/order_receipt_inherit.js create mode 100644 pos_receipt/static/src/order_receipt_inherit.xml create mode 100644 pos_receipt/views/boxes_receipt.xml create mode 100644 pos_receipt/views/light_receipt.xml create mode 100644 pos_receipt/views/lined_receipt.xml create mode 100644 pos_receipt/views/res_config_settings_view.xml create mode 100644 pos_receipt/wizard/__init__.py create mode 100644 pos_receipt/wizard/pos_receipt_wizard.py create mode 100644 pos_receipt/wizard/pos_receipt_wizard_views.xml diff --git a/pos_receipt/__init__.py b/pos_receipt/__init__.py new file mode 100644 index 00000000000..9b4296142f4 --- /dev/null +++ b/pos_receipt/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizard diff --git a/pos_receipt/__manifest__.py b/pos_receipt/__manifest__.py new file mode 100644 index 00000000000..e57897c8436 --- /dev/null +++ b/pos_receipt/__manifest__.py @@ -0,0 +1,20 @@ +{ + 'name': 'POS receipt', + 'version': '1.0', + 'depends': ['point_of_sale'], + 'data': [ + 'security/ir.model.access.csv', + 'wizard/pos_receipt_wizard_views.xml', + 'views/res_config_settings_view.xml', + 'views/boxes_receipt.xml', + 'views/lined_receipt.xml', + 'views/light_receipt.xml', + ], + 'assets': { + 'point_of_sale._assets_pos': [ + 'pos_receipt/static/src/**/*', + ], + }, + 'installable': True, + 'license': 'LGPL-3', +} diff --git a/pos_receipt/models/__init__.py b/pos_receipt/models/__init__.py new file mode 100644 index 00000000000..2b92809a3b4 --- /dev/null +++ b/pos_receipt/models/__init__.py @@ -0,0 +1,2 @@ +from . import pos_config +from . import res_config_settings diff --git a/pos_receipt/models/pos_config.py b/pos_receipt/models/pos_config.py new file mode 100644 index 00000000000..0bec588eaac --- /dev/null +++ b/pos_receipt/models/pos_config.py @@ -0,0 +1,13 @@ +from odoo import fields, models + + +class POSConfig(models.Model): + _inherit = 'pos.config' + + receipt_layout = fields.Selection([ + ('light', 'Light'), + ('lined', 'Lined'), + ('boxes', 'Boxes'), + ], string="Receipt Layout", default='light') + + receipt_logo = fields.Binary(string='Receipt Logo', related='company_id.logo', readonly=False) diff --git a/pos_receipt/models/res_config_settings.py b/pos_receipt/models/res_config_settings.py new file mode 100644 index 00000000000..795b527362c --- /dev/null +++ b/pos_receipt/models/res_config_settings.py @@ -0,0 +1,17 @@ +from odoo import _, fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = 'res.config.settings' + + receipt_layout = fields.Selection(related='pos_config_id.receipt_layout', readonly=False) + + def action_pos_receipt_layout(self): + return { + 'type': 'ir.actions.act_window', + 'name': _('Configure your pos receipt'), + 'res_model': 'pos.receipt.wizard', + 'view_mode': 'form', + 'target': 'new', + 'context': {'active_pos_config_id': self.pos_config_id.id, 'dialog_size': 'extra-large'}, + } diff --git a/pos_receipt/security/ir.model.access.csv b/pos_receipt/security/ir.model.access.csv new file mode 100644 index 00000000000..009e231981a --- /dev/null +++ b/pos_receipt/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +pos_receipt.access_receipt_layout,access_receipt_layout,pos_receipt.model_pos_receipt_wizard,base.group_user,1,1,1,1 diff --git a/pos_receipt/static/src/order_receipt_inherit.js b/pos_receipt/static/src/order_receipt_inherit.js new file mode 100644 index 00000000000..e16bdaad9ab --- /dev/null +++ b/pos_receipt/static/src/order_receipt_inherit.js @@ -0,0 +1,22 @@ +import { OrderReceipt } from "@point_of_sale/app/screens/receipt_screen/receipt/order_receipt"; +import { patch } from "@web/core/utils/patch"; +import { usePos } from "@point_of_sale/app/store/pos_hook"; + +patch(OrderReceipt, { + template: "pos_receipt.order_receipt_inherited" +}); + +patch(OrderReceipt.prototype, { + setup(){ + super.setup(); + this.pos = usePos(); + }, + + get orderQuantity() { + return this.props.data.orderlines.reduce((acc, line) => acc + parseFloat(line.qty), 0); + }, + + get order() { + return this.pos.get_order() + } +}); diff --git a/pos_receipt/static/src/order_receipt_inherit.xml b/pos_receipt/static/src/order_receipt_inherit.xml new file mode 100644 index 00000000000..ae8e73c6200 --- /dev/null +++ b/pos_receipt/static/src/order_receipt_inherit.xml @@ -0,0 +1,329 @@ + + + +
+ + + + + + +
  • + + +
  • +
    +
    + +
    +
    --------------------------------
    +
    + + Untaxed Amount + +
    +
    + + + + + + + on + + + +
    +
    +
    --------------------------------
    +
    + TOTAL + +
    + +
    + Rounding + +
    +
    + To Pay + +
    +
    +
    + + +
    +
    + CHANGE + +
    + +
    + Discounts + +
    +
    +