如何在Odoo 16的POS收据中添加自定义二维码?
问题描述
我正在做一个项目,需要基于订单信息生成二维码并打印到POS收据上。已经通过以下Python代码在pos.order模块添加了自定义字段并生成保存二维码:
from odoo import models, fields, api import logging try: import qrcode except ImportError: qrcode = None try: import base64 except ImportError: base64 = None from io import BytesIO _logger = logging.getLogger(__name__) class PosOrder(models.Model): _inherit = "pos.order" revenue_counter = fields.Float() qr_code_image = fields.Binary() qr_code_value = fields.Text() @api.model def action_pos_order_paid(self): _logger.error("It has been paid") res = super(PosOrder, self).action_pos_order_paid() _logger.error("It has been paid 2") if qrcode and base64: qr = qrcode.QRCode( version=1, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=3, border=4, ) qr.add_data("Hello -- Test") qr.make(fit=True) img = qr.make_image() _logger.error("Image was created") temp = BytesIO() _logger.error("Temp was created") img.save(temp, format="PNG") img.save("Qr-Code.png") _logger.error("Temp was initialized: ") _logger.error("Temp was initialized: %r ", temp.getvalue()) qr_image = base64.b64encode(temp.getvalue()) _logger.error("QR-Code binary was created: %r ", qr_image) self.qr_code_value = qr_image self.qr_code_image = qr_image return res @api.model def _order_fields(self, ui_order): order_values = super(PosOrder, self)._order_fields(ui_order) order_values['qr_code_image'] = ui_order.get('qr_code_image') order_values['qr_code_value'] = ui_order.get('qr_code_value') return order_values
同时用以下XML代码修改了收据模板:
<?xml version="1.0" encoding="UTF-8"?> <t t-name="OrderReceipt" t-inherit="point_of_sale.OrderReceipt" t-inherit-mode="extension" owl="1"> <xpath expr="//div[@t-if='receipt.pos_qr_code']" position="replace"> <div> <br /><br /> <div class="pos-receipt-order-data"> Scan me to request an invoice for your purchase. </div> </div> </xpath> </t>
现在的问题是自定义二维码字段无法在收据视图中生效,请问该怎么解决?当前的实现方式是否正确?
问题分析与解决方案
一、当前实现的核心问题
- 字段赋值无效:
action_pos_order_paid里直接给self.qr_code_image赋值,此时self是模型类而非具体订单记录,不会把数据保存到数据库。 - 收据模板未渲染二维码:现有XML只替换了文本内容,没有添加图片标签关联生成的二维码字段,而且前端收据数据里根本没有
qr_code_image这个值。 - 多余的前端字段同步:
_order_fields方法是用来接收POS前端传递的字段值,当前场景是后端生成二维码,这个方法完全没必要,反而可能覆盖数据。
二、修复步骤
1. 修正Python代码的字段保存逻辑
把直接赋值改成write()方法,确保数据写入具体订单记录,同时处理Text字段的编码问题:
@api.model def action_pos_order_paid(self): res = super(PosOrder, self).action_pos_order_paid() # 确保self是有效订单记录集,且依赖库存在 if qrcode and base64 and self: qr = qrcode.QRCode( version=1, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=3, border=4, ) # 替换成实际订单信息,比如订单编号 qr.add_data(f"订单号: {self.name}") qr.make(fit=True) img = qr.make_image() temp = BytesIO() img.save(temp, format="PNG") qr_image_bytes = base64.b64encode(temp.getvalue()) # 用write保存到数据库 self.write({ 'qr_code_image': qr_image_bytes, 'qr_code_value': qr_image_bytes.decode('utf-8') # Binary转字符串存Text字段 }) return res
2. 把二维码字段同步到POS前端收据数据
添加_export_for_ui方法,将自定义字段注入到前端可用的收据数据中:
@api.model def _export_for_ui(self, order): result = super(PosOrder, self)._export_for_ui(order) # 把二维码字段加入前端收据数据 result['qr_code_image'] = order.qr_code_image return result
3. 修改XML模板渲染二维码图片
调整XML,在合适位置插入二维码图片,比如收据页脚前:
<?xml version="1.0" encoding="UTF-8"?> <t t-name="OrderReceipt" t-inherit="point_of_sale.OrderReceipt" t-inherit-mode="extension" owl="1"> <xpath expr="//div[@class='pos-receipt-footer']" position="before"> <div class="pos-receipt-qr-code" t-if="receipt.qr_code_image"> <br/> <div class="pos-receipt-order-data">扫描二维码查看订单详情</div> <!-- 渲染base64格式的图片 --> <img t-att-src="'data:image/png;base64,' + receipt.qr_code_image" style="width:80px;height:80px;"/> </div> </xpath> </t>
原模板里的
receipt.pos_qr_code节点大概率不存在,直接在已知节点附近插入更可靠。
4. 移除多余代码
删掉_order_fields方法,因为不需要从前端接收二维码字段,避免干扰后端生成的数据。
三、额外注意事项
- 在模块的
__manifest__.py中添加依赖声明:'external_dependencies': {'python': ['qrcode']},确保Odoo能检测到依赖。 - 重启Odoo服务,更新模块,然后清除浏览器缓存(POS前端是单页应用,缓存会导致修改不生效)。
- 如果使用POS离线模式,需要额外处理字段同步逻辑,但支付后生成二维码的场景一般在在线模式下运行,无需额外配置。
内容的提问来源于stack exchange,提问作者Raphael
相关产品推荐
相关产品推荐

