这篇只盯一个细节:为什么会有两张图
很多人谈 Odoo POS 电子小票时,注意力都放在:
- 邮件有没有发出去
- 顾客有没有收到
但实际项目里,另一个很常见的问题是:
- 为什么附件里不是一张票,而是两张 JPG
- 第二张为什么文件名会多一个
-1
这个现象并不是邮件模板的巧合,而是 basic_receipt 开关驱动的一条明确链路。
这篇不再泛讲 POS 整体发邮件逻辑,只回答这一个问题:
当前端开启 basic receipt 后,full receipt 和 basic receipt 是怎么被分别渲染、上传并命名成两份附件的?
第一段:两张图其实都是前端先渲染出来的
在 receipt_screen.js 里,真正生成票据图像的不是 Python,而是前端的 renderer.toJpeg()。
generateTicketImage() 会把 OrderReceipt 组件渲染成 JPEG:
- 默认生成完整小票
- 传
basic_receipt: true时生成 basic 版小票
这说明电子小票的附件,并不是后端拿订单数据再二次排版成图片,而是:
- 前端先把用户现场看到的票据样式转成 JPEG
- 然后把这份图像数据传回服务端
也正因为如此,双附件现象的第一触发点不在后端,而在前端有没有额外再跑一次 generateTicketImage(true)。
第二段:什么时候会真的生成第二张 basic 图
同一个文件里,_sendReceiptToCustomer() 会先做一件保护:
- 如果订单还没同步到服务器,直接弹提示,不走发送
只有订单已同步时,它才会:
- 生成
fullTicketImage - 判断
this.pos.config.basic_receipt - 如果配置开启,再生成
basicTicketImage - 把两份图一起传给
pos.order.action_send_receipt
所以双附件并不是默认行为,而是两个条件叠加后的结果:
- 订单已同步
- POS 配置启用了
basic_receipt
如果其中任一条件不成立,最终就不会走出“双 JPEG”这条链。
第三段:后端并不重画小票,只负责落附件
到了 pos_order.py,action_send_receipt() 收到的是:
ticket_imagebasic_image
它并不会重新计算 receipt 样式,而是直接调用 _get_mail_attachments() 把图片落成 ir.attachment。
这一步特别值得记住,因为它解释了两个常见误区:
误区 1:后端才是小票图片生成者
不是。后端主要是附件归档和邮件投递方。
误区 2:附件样式跟邮件模板耦合在一起
也不是。模板负责发信,附件内容已经在前端阶段定型。
第四段:为什么文件名会出现 -1
_get_mail_attachments() 里,第一张附件名字是:
Receipt-<order>.jpg
如果 basic_ticket 存在,第二张会命名为:
Receipt-<order>-1.jpg
这个命名策略虽然简单,但很实用:
- 避免两张附件重名
- 又保持它们明显属于同一张订单的小票组
因此你在顾客邮箱里看到一个正常票据和一个 -1 结尾的附件,不是系统“重复发送”,而是 Odoo 明确把:
- 完整票据
- basic 票据
作为两个并列附件处理。
为什么要把 basic receipt 单独做成附件
从业务语义看,basic receipt 不是“完整版小票的备用样式”,而更像:
- 面向礼品、简版展示或不暴露价格的票据版本
如果它只是在正文里临时渲染,后续保存和转发都不方便; 如果把它单独做成附件,就能和完整版一起保留、下载、复查。
所以 Odoo 这里不是单纯做了两次截图,而是在传递两份不同票据语义。
实战排查时最该看哪里
如果你遇到“为什么顾客只收到一张 / 收到两张 / 文件名奇怪”的问题,优先按这个顺序查:
- 前端 POS 配置有没有开启
basic_receipt - 订单在发送前是否已经 synced
generateTicketImage(true)有没有被执行action_send_receipt()收到的basic_image是否为空_get_mail_attachments()最终创建了几个ir.attachment
通常查完这五步,问题就能定位到:
- 是前端没生成
- 还是后端没落附件
总结
POS 电子小票里最容易被忽略的,不是“邮件发没发”,而是:
- 小票图像先在前端渲染
basic_receipt决定是否生成第二张 basic 图- 后端把它们变成两份 JPG 附件
- 第二张通过
-1命名避免重名
如果只记一句,就记这句:
Odoo POS 发出的两张 JPG,不是重复附件,而是 full receipt 与 basic receipt 两份不同票据版本在邮件侧的并列落档。
DISCUSSION
评论区