如何确保RPC调用完成后再打印Odoo 12 POS收据?
Odoo 12 POS 收据延迟打印以等待RPC数据加载问题修复
问题背景
在Odoo 12 POS系统中,需要通过RPC调用获取数据并展示在POS收据上,但当前收据会在RPC调用完成前就打印,导致无法展示所需信息。尝试扩展PaymentScreenWidget强制等待RPC完成后再打印,但出现两处错误:
- 调用
this._super(force_validate)后报错 - 执行
self.pos.proxy('print_receipt')时提示“self.pos.proxy is not a function”
已完成的操作:
- 保存原方法引用以避免
_super调用报错 - 扩展Order模型控制RPC状态
- 在
push_order中添加RPC调用
错误分析与修复方案
1. _super调用错误
原validate_order方法可能未返回Promise,直接使用.then()会导致报错。需要用Promise.resolve()包裹原方法调用,确保链式调用正常执行。
2. 打印方法错误
Odoo 12中POS的打印接口并非pos.proxy,而是pos.chrome.print_receipt,proxy方法属于chrome对象。
3. Order模型字段判断错误
export_for_printing中使用的this.rpc_completed未定义,应改为判断this.rpc_state === 'completed'。
修复后的完整代码
odoo.define('mymodule.sincronize_receitp', function (require) { "use strict"; var models = require('point_of_sale.models'); var screens = require('point_of_sale.screens'); var rpc = require('web.rpc'); var core = require('web.core'); var _t = core._t; // 保存原方法引用 var originalOrderInitialize = models.Order.prototype.initialize; var originalOrderExportForPrinting = models.Order.prototype.export_for_printing; var originalPushOrder = models.PosModel.prototype.push_order; // 扩展Order模型控制RPC状态 models.Order = models.Order.extend({ initialize: function() { if (originalOrderInitialize) { originalOrderInitialize.apply(this, arguments); } this.rpc_state = 'pending'; this.rpc_data = {}; this.print_callbacks = []; }, add_print_callback: function(callback) { if (this.rpc_state === 'completed') { callback(); } else { this.print_callbacks.push(callback); } }, export_for_printing: function() { var receipt = originalOrderExportForPrinting ? originalOrderExportForPrinting.apply(this, arguments) : {}; receipt.rpc_data = this.rpc_state === 'completed' ? this.rpc_data : { status: 'loading' }; return receipt; } }); // 在push_order中添加RPC调用 models.PosModel = models.PosModel.extend({ push_order: function(order) { var self = this; if (!order) { return Promise.resolve(); } order.rpc_state = 'pending'; order.rpc_data = { status: 'loading' }; // 先执行原push_order方法,再执行RPC return (originalPushOrder ? originalPushOrder.apply(this, arguments) : Promise.resolve()) .then(function() { return rpc.query({ model: 'pos.order', method: 'get_data_rpc', args: [order.unique_id], }).then(function(response) { order.rpc_data = response || {}; order.rpc_state = 'completed'; // 执行打印回调(如果有的话) while (order.print_callbacks.length) { order.print_callbacks.shift()(); } }).catch(function(error) { console.error('RPC Error:', error); order.rpc_data = { error: error.message || 'Erro de comunicação', details: error.data ? error.data.message : '' }; order.rpc_state = 'failed'; }); }); } }); // 扩展PaymentScreenWidget,确保RPC完成后再打印 screens.PaymentScreenWidget.include({ validate_order: function(force_validate) { var self = this; var order = this.pos.get_order(); if (!order || order.is_empty()) { return this._super(force_validate); } // 用Promise.resolve包裹原方法调用,确保链式调用正常 return Promise.resolve(this._super(force_validate)).then(function() { // 等待push_order中的RPC完成 return self.pos.push_order(order).then(function() { // 使用正确的打印方法 self.pos.chrome.print_receipt(order.export_for_printing()); }); }).catch(function(error) { console.error('Validation/Print Error:', error); // 添加错误提示给用户 self.gui.show_popup('error', { title: _t('Error'), body: _t('Failed to process order and print receipt: ') + error.message, }); }); } }); });
关键修复点说明
- Order模型修正:将
rpc_completed改为rpc_state === 'completed',确保状态判断正确;初始化时设置默认rpc_state为pending。 - push_order优化:添加错误处理的
catch块,确保RPC失败时状态正确更新;同时执行打印回调队列,处理可能的延迟打印请求。 - validate_order修复:
- 用
Promise.resolve()包裹this._super(force_validate),避免原方法不返回Promise导致的链式调用错误。 - 替换打印方法为
self.pos.chrome.print_receipt,符合Odoo 12 POS的API规范。 - 添加全局错误捕获,提升用户体验。
- 用
内容的提问来源于stack exchange,提问作者Paulo Matos
相关产品推荐
相关产品推荐

