commit 11eb0b8debcecaaa6007ec815b180f32651ee3e8 Author: Suherdy Yacob Date: Wed May 13 14:47:50 2026 +0700 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..296f591 --- /dev/null +++ b/.gitignore @@ -0,0 +1,117 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +# Odoo specific +*.log +*.conf +/data/ + +# OS specific +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# IDEs +.idea/ +.vscode/ +*.swp +*.swo diff --git a/README.md b/README.md new file mode 100644 index 0000000..c06e6d6 --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +# POS Receipt Print Default Settings + +This module allows you to set the default number of copies and paper size for POS receipts. + +## Features +1. **Default Number of Copies**: Configure how many times the receipt should be printed. +2. **Default Paper Size**: Suggest the paper size to the browser print dialog using `@page` CSS rules. + - Supported sizes: 57mm (ISO 57), 58mm, 80mm, 80x210mm, 80x297mm, 112mm, A4. + +## How it works +- The module adds configuration fields in **Point of Sale > Configuration > Settings**. +- It patches the `PosStore.printReceipt` method in Javascript to: + - Inject dynamic CSS that overrides the `@page` size. + - Execute a loop to trigger the print function multiple times if more than 1 copy is requested. + +## Requirements +- Odoo 19 +- Standard browser printing (works best in Chrome/Edge for `@page` support). +- For silent printing (no dialog), the browser must be started in kiosk mode (e.g., `--kiosk-printing` for Chrome). diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/__manifest__.py b/__manifest__.py new file mode 100644 index 0000000..0e21eb9 --- /dev/null +++ b/__manifest__.py @@ -0,0 +1,23 @@ +{ + 'name': 'POS Receipt Print Default Settings', + 'version': '1.0', + 'category': 'Sales/Point of Sale', + 'summary': 'Set default number of copies and paper size for POS receipts', + 'description': """ + This module allows you to configure the default number of copies and paper size + for receipt printing in the Point of Sale. + It auto-fills the paper size selection via CSS @page and handles multiple copies. + """, + 'author': 'Suherdy Yacob', + 'depends': ['point_of_sale'], + 'data': [ + 'views/pos_config_views.xml', + ], + 'assets': { + 'point_of_sale._assets_pos': [ + 'pos_receipt_print_default/static/src/app/**/*', + ], + }, + 'installable': True, + 'license': 'LGPL-3', +} diff --git a/models/__init__.py b/models/__init__.py new file mode 100644 index 0000000..2b92809 --- /dev/null +++ b/models/__init__.py @@ -0,0 +1,2 @@ +from . import pos_config +from . import res_config_settings diff --git a/models/pos_config.py b/models/pos_config.py new file mode 100644 index 0000000..3a99d1c --- /dev/null +++ b/models/pos_config.py @@ -0,0 +1,21 @@ +from odoo import fields, models, api + +class PosConfig(models.Model): + _inherit = 'pos.config' + + receipt_print_copies = fields.Integer(string='Default Number of Copies', default=1, help="Default number of copies to print for receipts.") + receipt_paper_size = fields.Selection([ + ('57mm', '57mm (ISO 57)'), + ('58mm', '58mm'), + ('80mm', '80mm'), + ('80x210mm', '80 x 210 mm'), + ('80x297mm', '80 x 297 mm'), + ('112mm', '112mm'), + ('A4', 'A4'), + ], string='Default Paper Size', default='57mm', help="Default paper size for browser print dialog.") + + @api.model + def _load_pos_data_fields(self, config): + fields = super()._load_pos_data_fields(config) + fields += ['receipt_print_copies', 'receipt_paper_size'] + return fields diff --git a/models/res_config_settings.py b/models/res_config_settings.py new file mode 100644 index 0000000..f90a0bc --- /dev/null +++ b/models/res_config_settings.py @@ -0,0 +1,7 @@ +from odoo import fields, models + +class ResConfigSettings(models.TransientModel): + _inherit = 'res.config.settings' + + pos_receipt_print_copies = fields.Integer(related='pos_config_id.receipt_print_copies', readonly=False) + pos_receipt_paper_size = fields.Selection(related='pos_config_id.receipt_paper_size', readonly=False) diff --git a/static/src/app/services/pos_store_patch.js b/static/src/app/services/pos_store_patch.js new file mode 100644 index 0000000..83265a6 --- /dev/null +++ b/static/src/app/services/pos_store_patch.js @@ -0,0 +1,77 @@ +/** @odoo-module **/ + +import { PosStore } from "@point_of_sale/app/services/pos_store"; +import { patch } from "@web/core/utils/patch"; + +patch(PosStore.prototype, { + async printReceipt(params = {}) { + const copies = this.config.receipt_print_copies || 1; + const paperSize = this.config.receipt_paper_size || '57mm'; + + // Inject CSS for paper size to guide browser print dialog + this._injectReceiptPaperSizeCSS(paperSize); + + let result; + // Print multiple copies + for (let i = 0; i < copies; i++) { + result = await super.printReceipt(params); + } + return result; + }, + + /** + * Injects dynamic CSS with @page rules to suggest paper size to the browser. + * Most modern browsers (Chrome/Edge) use @page { size: ... } to auto-select + * the paper size in the print dialog. + */ + _injectReceiptPaperSizeCSS(size) { + let style = document.getElementById('pos_receipt_print_style'); + if (!style) { + style = document.createElement('style'); + style.id = 'pos_receipt_print_style'; + document.head.appendChild(style); + } + + let width = '57mm'; + let pageSize = '57mm auto'; + + if (size === '58mm') { + width = '58mm'; + pageSize = '58mm auto'; + } else if (size === '80mm') { + width = '80mm'; + pageSize = '80mm auto'; + } else if (size === '80x210mm') { + width = '80mm'; + pageSize = '80mm 210mm'; + } else if (size === '80x297mm') { + width = '80mm'; + pageSize = '80mm 297mm'; + } else if (size === '112mm') { + width = '112mm'; + pageSize = '112mm auto'; + } else if (size === 'A4') { + width = '210mm'; + pageSize = 'A4'; + } + + style.innerHTML = ` + @media print { + @page { + size: ${pageSize}; + margin: 0; + } + .pos-receipt { + width: ${width} !important; + margin: 0 auto !important; + padding: 5px !important; + box-sizing: border-box !important; + } + /* Hide other elements if any */ + body { + margin: 0 !important; + } + } + `; + } +}); diff --git a/views/pos_config_views.xml b/views/pos_config_views.xml new file mode 100644 index 0000000..daf1da6 --- /dev/null +++ b/views/pos_config_views.xml @@ -0,0 +1,24 @@ + + + + res.config.settings.view.form.inherit.pos_receipt_print_default + res.config.settings + + + + +
+
+
+
+
+
+
+
+
+
+