diff --git a/pos_barcode_block_on_error/README.rst b/pos_barcode_block_on_error/README.rst new file mode 100644 index 0000000..c493187 --- /dev/null +++ b/pos_barcode_block_on_error/README.rst @@ -0,0 +1,35 @@ +POS: Block barcode scanning on error popup +========================================= + +Summary +------- +This Point of Sale extension prevents the POS from processing further barcode +scans while the "barcode not found" error popup is visible. It also avoids the +scanner's Enter/Escape keystrokes from closing the popup, so the cashier must +explicitly dismiss it (click/tap) before continuing. + +Features +-------- +- Takes exclusive control of the barcode reader while the error popup is shown. +- Prevents scanner-triggered keyboard "clicks" from closing the popup. +- Keeps the initial error message visible; subsequent scans are ignored. +- Includes CSS to highlight the error popup for better visibility. + +Usage +----- +- Scan a non-existent barcode in the POS. + - The error popup will show. + - Further scans will be ignored while the popup is visible. + - Close the popup via mouse/touch to resume scanning. + +Limitations +----------- +- While the popup is open, all barcode actions are blocked (product, client, + weight, price, discount, GS1, etc.). Customize the hook if you need + exceptions. + + +Credits +------- +- Author: Criptomart +- License: AGPL-3 diff --git a/pos_barcode_block_on_error/__manifest__.py b/pos_barcode_block_on_error/__manifest__.py new file mode 100644 index 0000000..1af2032 --- /dev/null +++ b/pos_barcode_block_on_error/__manifest__.py @@ -0,0 +1,16 @@ +{ + "name": "POS: Block barcode scanning on error popup", + "version": "16.0.1.0.0", + "summary": "Stops processing new barcodes while ErrorBarcodePopup is shown.", + "category": "Point of Sale", + "license": "AGPL-3", + "author": "Criptomart", + "depends": ["point_of_sale"], + "assets": { + "point_of_sale.assets": [ + "pos_barcode_block_on_error/static/src/js/error_barcode_popup_block.js", + "pos_barcode_block_on_error/static/src/css/error_popup.css", + ], + }, + "installable": True, +} diff --git a/pos_barcode_block_on_error/static/src/css/error_popup.css b/pos_barcode_block_on_error/static/src/css/error_popup.css new file mode 100644 index 0000000..817a99b --- /dev/null +++ b/pos_barcode_block_on_error/static/src/css/error_popup.css @@ -0,0 +1,16 @@ +/* Emphasize the error popup for unknown barcode */ +/* Make the whole popup background red and invert text for visibility */ +.popup.popup-barcode { + background-color: #c62828 !important; /* strong red background */ + color: #fff !important; /* default text to white */ +} +.popup.popup-barcode .title, +.popup.popup-barcode .body { + color: #fff !important; + font-weight: 600; +} +.popup.popup-barcode .footer .button.cancel { + background: #fff !important; /* white button on red bg */ + color: #c62828 !important; /* red text */ + border-color: #fff !important; +} diff --git a/pos_barcode_block_on_error/static/src/js/error_barcode_popup_block.js b/pos_barcode_block_on_error/static/src/js/error_barcode_popup_block.js new file mode 100644 index 0000000..9024895 --- /dev/null +++ b/pos_barcode_block_on_error/static/src/js/error_barcode_popup_block.js @@ -0,0 +1,67 @@ +/** @odoo-module */ +/** + * Block barcode processing while ErrorBarcodePopup is visible by taking + * exclusive control of the barcode reader, and release it when closing. + */ + +import Registries from "point_of_sale.Registries"; +import ErrorBarcodePopup from "point_of_sale.ErrorBarcodePopup"; +import { useBarcodeReader } from "point_of_sale.custom_hooks"; + +const ErrorBarcodePopupBlock = (ErrorPopup) => + class extends ErrorPopup { + setup() { + super.setup(...arguments); + // Prevent keyboard-triggered clicks (Enter on focused button) + owl.onMounted(() => { + this.__clickHandler = (ev) => { + // Keyboard-triggered clicks usually have detail === 0 + if (ev && ev.detail === 0) { + ev.preventDefault(); + ev.stopPropagation(); + } + }; + if (this.el) { + this.el.addEventListener('click', this.__clickHandler, true); + } + }); + + + // Take exclusive control using POS hook so subsequent scans are ignored + useBarcodeReader({ + product: () => {}, + quantity: () => {}, + weight: () => {}, + price: () => {}, + client: () => {}, + discount: () => {}, + cashier: () => {}, + error: () => {}, + gs1: () => {}, + }, true); + } + + willUnmount() { + // useBarcodeReader cleans up automatically on unmount + if (this.el && this.__clickHandler) { + this.el.removeEventListener('click', this.__clickHandler, true); + } + super.willUnmount(...arguments); + } + + // Only accept real pointer clicks to close the popup; ignore keyboard/programmatic events + async confirm(ev) { + if (ev && ev.type === 'click' && ev.isTrusted && ev.detail > 0) { + return super.confirm(); + } + } + cancel(ev) { + if (ev && ev.type === 'click' && ev.isTrusted && ev.detail > 0) { + return super.cancel(); + } + } + }; + +Registries.Component.extend(ErrorBarcodePopup, ErrorBarcodePopupBlock); + +export default ErrorBarcodePopup;