You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Odoo中实现销售订单确认时自动下载关联电子表格?

Odoo销售订单确认时自动下载关联电子表格的实现方案

针对你需要在销售订单确认时自动下载所有订单行关联电子表格的需求,这里提供两种可行的实现思路,结合Odoo的后端逻辑和前端交互完成:

方案一:直接在确认动作中返回下载响应

这种方式会在确认订单后直接触发文件下载,适合不需要保留原确认后跳转逻辑的场景。

后端代码实现

重写sale.order模型的action_confirm方法,收集关联的电子表格并处理下载:

from odoo import models, api
import zipfile
import io

class SaleOrder(models.Model):
    _inherit = 'sale.order'

    def action_confirm(self):
        # 先执行原确认逻辑
        res = super().action_confirm()
        
        # 收集所有订单行关联的电子表格(替换成你实际的many2one字段名)
        attachments = self.order_line.mapped('your_spreadsheet_field')
        if not attachments:
            return res
        
        # 多文件打包成ZIP下载
        if len(attachments) > 1:
            zip_buffer = io.BytesIO()
            with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
                for att in attachments:
                    # 从附件中读取二进制内容并写入ZIP
                    zip_file.writestr(att.name, att.datas.decode('base64'))
            zip_buffer.seek(0)
            
            # 创建临时ZIP附件并返回下载动作
            zip_att = self.env['ir.attachment'].create({
                'name': f"订单{self.name}_关联表格.zip",
                'datas': zip_buffer.getvalue().encode('base64'),
                'res_model': 'sale.order',
                'res_id': self.id,
                'type': 'binary',
            })
            return {
                'type': 'ir.actions.act_url',
                'url': f'/web/content/{zip_att.id}?download=true',
                'target': 'self',
            }
        else:
            # 单个文件直接返回下载链接
            att = attachments[0]
            return {
                'type': 'ir.actions.act_url',
                'url': f'/web/content/{att.id}?download=true',
                'target': 'self',
            }
        
        return res

方案二:不打断原确认流程,通过前端触发下载

如果需要保留订单确认后跳转到订单页面的原有逻辑,可以采用后端提供文件接口、前端监听确认事件触发下载的方式。

1. 后端新增方法和路由

# sale/models/sale_order.py
from odoo import models, api
import zipfile
import io
from odoo.http import route, Controller

class SaleOrder(models.Model):
    _inherit = 'sale.order'

    def get_associated_spreadsheets(self):
        # 返回所有关联电子表格的ID列表
        return self.order_line.mapped('your_spreadsheet_field').ids

    @api.model
    def generate_spreadsheet_zip(self, order_id):
        order = self.browse(order_id)
        attachments = order.order_line.mapped('your_spreadsheet_field')
        if not attachments:
            return None
        
        zip_buffer = io.BytesIO()
        with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
            for att in attachments:
                zip_file.writestr(att.name, att.datas.decode('base64'))
        zip_buffer.seek(0)
        
        # 生成下载响应
        return self.env['ir.http'].make_response(
            zip_buffer.getvalue(),
            headers=[
                ('Content-Type', 'application/zip'),
                ('Content-Disposition', f'attachment; filename="订单{order.name}_关联表格.zip"'),
            ]
        )

# sale/controllers/main.py
class SaleDownloadController(Controller):
    @route('/web/sale/order/download_spreadsheets/<int:order_id>', type='http', auth='user')
    def download_spreadsheets(self, order_id):
        return self.env['sale.order'].generate_spreadsheet_zip(order_id)

2. 前端视图添加JS监听

在销售订单表单视图中嵌入JS,监听确认按钮点击事件:

<odoo>
    <record id="sale_order_form_inherit" model="ir.ui.view">
        <field name="name">sale.order.form.inherit</field>
        <field name="model">sale.order</field>
        <field name="inherit_id" ref="sale.view_order_form"/>
        <field name="arch" type="xml">
            <form position="inside">
                <script type="text/javascript">
                    odoo.define('sale.auto.download.spreadsheets', function(require) {
                        var FormController = require('web.FormController');
                        var rpc = require('web.rpc');

                        FormController.include({
                            _onButtonClicked: function(ev) {
                                var self = this;
                                // 判断点击的是确认按钮
                                if (ev.data.attrs.name === 'action_confirm') {
                                    this._super(ev).then(function() {
                                        // 请求后端获取关联表格ID
                                        rpc.query({
                                            model: 'sale.order',
                                            method: 'get_associated_spreadsheets',
                                            args: [self.renderer.state.res_id],
                                        }).then(function(att_ids) {
                                            if (att_ids.length > 0) {
                                                if (att_ids.length > 1) {
                                                    // 多文件下载ZIP
                                                    window.open(`/web/sale/order/download_spreadsheets/${self.renderer.state.res_id}`, '_self');
                                                } else {
                                                    // 单文件直接下载
                                                    window.open(`/web/content/${att_ids[0]}?download=true`, '_self');
                                                }
                                            }
                                        });
                                    });
                                } else {
                                    this._super(ev);
                                }
                            }
                        });
                    });
                </script>
            </form>
        </field>
    </record>
</odoo>

关键注意事项

  • 替换代码中your_spreadsheet_field为你实际在sale.order.line中新增的many2one字段名称
  • 确保你的many2one字段关联的是ir.attachment模型(Odoo默认的文件存储模型),如果是自定义文档模型,需要调整读取文件内容的逻辑
  • 验证用户权限:确保操作订单的用户拥有ir.attachment的读取和下载权限
  • 大文件处理:如果关联的电子表格体积较大,建议添加文件大小检查,避免打包超时或占用过多服务器资源

内容的提问来源于stack exchange,提问作者Jack Sparrow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 10:35:00