双附件小票

Odoo POS 为什么会给顾客发两张 JPG:basic_receipt 开关、前端截图与附件命名链路

不再泛讲电子小票整条邮件链,而是聚焦 basic_receipt 打开后为什么会同时生成 full、basic 两张 JPEG,小票图像是谁在前端渲染、谁在后端落成附件、附件名字为什么会带 -1。

POS
进阶 开发者 1 分钟阅读
0 评论 0 点赞 0 收藏 5 阅读

这篇只盯一个细节:为什么会有两张图

很多人谈 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() 会先做一件保护:

  • 如果订单还没同步到服务器,直接弹提示,不走发送

只有订单已同步时,它才会:

  1. 生成 fullTicketImage
  2. 判断 this.pos.config.basic_receipt
  3. 如果配置开启,再生成 basicTicketImage
  4. 把两份图一起传给 pos.order.action_send_receipt

所以双附件并不是默认行为,而是两个条件叠加后的结果:

  • 订单已同步
  • POS 配置启用了 basic_receipt

如果其中任一条件不成立,最终就不会走出“双 JPEG”这条链。

第三段:后端并不重画小票,只负责落附件

到了 pos_order.pyaction_send_receipt() 收到的是:

  • email
  • ticket_image
  • basic_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 这里不是单纯做了两次截图,而是在传递两份不同票据语义。

实战排查时最该看哪里

如果你遇到“为什么顾客只收到一张 / 收到两张 / 文件名奇怪”的问题,优先按这个顺序查:

  1. 前端 POS 配置有没有开启 basic_receipt
  2. 订单在发送前是否已经 synced
  3. generateTicketImage(true) 有没有被执行
  4. action_send_receipt() 收到的 basic_image 是否为空
  5. _get_mail_attachments() 最终创建了几个 ir.attachment

通常查完这五步,问题就能定位到:

  • 是前端没生成
  • 还是后端没落附件

总结

POS 电子小票里最容易被忽略的,不是“邮件发没发”,而是:

  • 小票图像先在前端渲染
  • basic_receipt 决定是否生成第二张 basic 图
  • 后端把它们变成两份 JPG 附件
  • 第二张通过 -1 命名避免重名

如果只记一句,就记这句:

Odoo POS 发出的两张 JPG,不是重复附件,而是 full receipt 与 basic receipt 两份不同票据版本在邮件侧的并列落档。

DISCUSSION

评论区

想参与讨论?先 登录 再发表评论。
还没有评论,你可以成为第一个留言的人。