From 0f225a7bfb42d98c7ea9375cd8016ff2c9d8b6ee Mon Sep 17 00:00:00 2001 From: Suherdy Yacob Date: Wed, 20 May 2026 06:59:57 +0700 Subject: [PATCH] feat: implement dynamic POS configuration ID resolution and UI updates for printer bypass functionality --- static/src/css/bluetooth_printer.css | 6 ++++++ static/src/js/bluetooth_printer_config.js | 9 +++++---- static/src/js/connection_status_widget.js | 12 ++++++++++++ static/src/js/pos_receipt_printer.js | 21 ++++++++++++++------- static/src/js/pos_session_integration.js | 6 ++++++ 5 files changed, 43 insertions(+), 11 deletions(-) diff --git a/static/src/css/bluetooth_printer.css b/static/src/css/bluetooth_printer.css index adf381d..9065a73 100755 --- a/static/src/css/bluetooth_printer.css +++ b/static/src/css/bluetooth_printer.css @@ -68,6 +68,12 @@ box-shadow: 0 0 8px rgba(220, 53, 69, 0.6); } +/* Bypassed Status - Grey */ +.bluetooth-status-indicator-bypassed { + background-color: #6c757d; + box-shadow: 0 0 8px rgba(108, 117, 125, 0.4); +} + /* Pulse Animation for Connecting State */ @keyframes bluetooth-pulse { 0% { diff --git a/static/src/js/bluetooth_printer_config.js b/static/src/js/bluetooth_printer_config.js index dd50720..d5fec25 100755 --- a/static/src/js/bluetooth_printer_config.js +++ b/static/src/js/bluetooth_printer_config.js @@ -265,14 +265,15 @@ export class BluetoothPrinterConfig extends Component { this._saveConfiguration(); } - /** - * Handle bypass toggle - * @param {Event} event - Change event - */ onBypassChange(event) { this.state.bypassBluetooth = event.target.checked; this.storageManager.setBypassStatus(this.posConfigId, this.state.bypassBluetooth); + // Notify connection status widget about the change immediately + if (this.bluetoothManager && typeof this.bluetoothManager._emit === 'function') { + this.bluetoothManager._emit('connection-status-changed', this.bluetoothManager.getConnectionInfo()); + } + if (this.state.bypassBluetooth) { this._showNotification('Bluetooth printer bypassed on this device', 'info'); } else { diff --git a/static/src/js/connection_status_widget.js b/static/src/js/connection_status_widget.js index 28986fc..50b9f2a 100755 --- a/static/src/js/connection_status_widget.js +++ b/static/src/js/connection_status_widget.js @@ -4,6 +4,7 @@ import { Component, useState, onWillStart, onWillUnmount } from "@odoo/owl"; import { useService } from "@web/core/utils/hooks"; import { BluetoothPrinterConfig } from "./bluetooth_printer_config"; import { ConfirmationDialog } from "@web/core/confirmation_dialog/confirmation_dialog"; +import { BluetoothPrinterStorage } from "./storage_manager"; /** * Bluetooth Connection Status Widget @@ -23,6 +24,7 @@ export class BluetoothConnectionStatus extends Component { setup() { this.dialog = useService("dialog"); this.notification = useService("notification"); + this.storageManager = new BluetoothPrinterStorage(); this.state = useState({ status: 'disconnected', @@ -109,6 +111,12 @@ export class BluetoothConnectionStatus extends Component { this.state.reconnectAttempts = info.reconnectAttempts; this.state.isReconnecting = info.isReconnecting; this.state.timestamp = info.timestamp; + + // Check if bypassed on this device + const posConfigId = this.props.posConfigId || 1; + if (this.storageManager.getBypassStatus(posConfigId)) { + this.state.status = 'bypassed'; + } } /** @@ -135,6 +143,8 @@ export class BluetoothConnectionStatus extends Component { return 'fa fa-bluetooth-b'; case 'connecting': return 'fa fa-bluetooth'; + case 'bypassed': + return 'fa fa-ban'; case 'error': return 'fa fa-exclamation-triangle'; default: @@ -158,6 +168,8 @@ export class BluetoothConnectionStatus extends Component { return this.state.isReconnecting ? `Reconnecting... (${this.state.reconnectAttempts}/3)` : 'Connecting...'; + case 'bypassed': + return 'Printer Bypassed (Web Print)'; case 'error': return 'Connection Error'; default: diff --git a/static/src/js/pos_receipt_printer.js b/static/src/js/pos_receipt_printer.js index e0585d6..025df02 100755 --- a/static/src/js/pos_receipt_printer.js +++ b/static/src/js/pos_receipt_printer.js @@ -50,6 +50,11 @@ const originalPrintHtml = PosPrinterService.prototype.printHtml; // Patch the PosPrinterService to add bluetooth printing functionality patch(PosPrinterService.prototype, { + setup(env) { + this.env = env; + super.setup(...arguments); + }, + /** * Override the printHtml method to use bluetooth printer * Falls back to browser print on any failure @@ -74,15 +79,17 @@ patch(PosPrinterService.prototype, { console.log('[BluetoothPrint] Web Bluetooth API available'); // Check if a Bluetooth printer is configured (from localStorage) - // We don't need POS config - we check if user has configured a printer const storage = new BluetoothPrinterStorage(); + // Get POS config ID dynamically from POS store service + const pos = this.env?.services?.pos; + const posConfigId = pos?.config?.id || 1; + // Check if user has explicitly bypassed bluetooth printer for this device - // We default to config ID 1 since it's hardcoded here as well - if (storage.getBypassStatus(1)) { + if (storage.getBypassStatus(posConfigId)) { console.log('[BluetoothPrint] Bluetooth printer bypassed on this device, using standard print'); try { - const result = await originalPrintHtml.call(this, el); + const result = await originalPrintHtml.apply(this, arguments); if (result === false) { await this._printViaBrowserDialog(el); } @@ -94,13 +101,13 @@ patch(PosPrinterService.prototype, { } } - const config = storage.loadConfiguration(1); // Default POS config ID + const config = storage.loadConfiguration(posConfigId); if (!config || !config.deviceId) { console.log('[BluetoothPrint] No Bluetooth printer configured, using standard print'); console.log('[BluetoothPrint] Calling originalPrintHtml with:', el); try { - const result = await originalPrintHtml.call(this, el); + const result = await originalPrintHtml.apply(this, arguments); console.log('[BluetoothPrint] originalPrintHtml returned:', result); // If original method returned false, it didn't handle the print @@ -174,7 +181,7 @@ patch(PosPrinterService.prototype, { } catch (dialogError) { console.error('[BluetoothPrint] Browser print dialog also failed:', dialogError); // Last resort - try original method - return await originalPrintHtml.call(this, el); + return await originalPrintHtml.apply(this, arguments); } } }, diff --git a/static/src/js/pos_session_integration.js b/static/src/js/pos_session_integration.js index ab5ebb4..c147ace 100755 --- a/static/src/js/pos_session_integration.js +++ b/static/src/js/pos_session_integration.js @@ -54,6 +54,12 @@ patch(PosStore.prototype, { return; } + // Check if user has explicitly bypassed bluetooth printer for this device + if (storageManager.getBypassStatus(this.config.id)) { + console.log('Bluetooth printer is bypassed for this device. Skipping initialization.'); + return; + } + // Load printer configuration from local storage const config = storageManager.loadConfiguration(this.config.id);