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

从JavaScript调用Odoo报表无打印输出的原因排查

问题:JavaScript调用Odoo报表函数后报表不打印

我开发了一个针对stock.move.line元素生成报表的向导,从列表视图调用时运行正常。现在希望通过条码界面的按钮触发JavaScript调用该报表(点击每个stock.move.line对应的按钮时执行)。尝试调用时,Python函数已被触发(服务器控制台能看到print()输出),但报表并未实际打印。单独测试Python函数是有效的。

点击界面按钮时,浏览器控制台能看到正确的nb_printing和stock_move_line值,服务器控制台也能看到"Hello, function is launched."输出,但报表就是不打印。


相关代码

JavaScript代码

odoo.define("colona_custo.print_product_label", function(require) {
"use strict";

var rpc = require("web.rpc");

function call_print_function(nb_printing, move_line_id)
{
    console.log(nb_printing);
    console.log(move_line_id);

    
    return rpc.query({
        model: 'print.product.label.wizard',
        method: 'print_product_label_from_js',
        args: [[], nb_printing, move_line_id]
    });
}

function print_product_label()
{
    var move_line_id = $(this).next().text();

    // 询问用户打印次数
    $(document.body).append("<div id='warning_popup' style='background: rgba(255, 255, 255, 0.9); width: 50vw; height: 50vh; border-radius: 5px; padding: 10px; z-index: 1000; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);'><h2 style='position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);'>How many times do you want to print the product label?</h2><input id='user_entry' style='position:relative;top:50%;left:45%;'/><button id='action_print' style='position: absolute; bottom: 5px; left: 100px;' class='btn btn-primary'>Print</button><button id='close_popup_printing' style='position: absolute; bottom: 5px; left: 5px;' class='btn btn-primary'>Close</button></div>")
    $('#close_popup_printing').on('click', function() {
        $('#warning_popup').hide();
    });

    $('#action_print').on('click', function() {
        var nb_printing = $('#user_entry').val();
        if (nb_printing > 0) {
            call_print_function(nb_printing, move_line_id);
        }

    });
}

$(document).on('click', '.o_button_print_product_label', print_product_label)});

Python代码

from odoo import api, fields, models
from odoo.exceptions import UserError

class SmlPrintProductLabelWizard(models.TransientModel):

    _name = 'print.product.label.wizard'

    nb_printing = fields.Integer()

    def print_product_label(self):
        if (self.nb_printing >= 0):
            return self.env.ref('colona_custo.action_report_product_label').report_action([], data={'stock_move_line_id': self.env.context.get('active_id'), 'nb_printing': self.nb_printing})
        else:
            raise UserError("The number of printing is incorrect.")

    def print_product_label_from_js(self, nb_printing=1, move_line_id=34):
        print("===========================")
        print("Hello, function is launched.")
        return self.env.ref('colona_custo.action_report_product_label').report_action([], data={'stock_move_line_id': int(move_line_id), 'nb_printing': int(nb_printing)})

问题原因与解决方法

核心原因

Odoo的report_action返回的是一个动作字典,列表视图调用时Odoo前端框架会自动处理这个字典并触发报表,但自定义JavaScript的RPC调用仅获取了字典,没有在前端执行对应的动作逻辑,所以报表不会被触发。

解决步骤

1. 修改JavaScript代码,处理RPC返回的动作

引入ActionManager并在RPC回调中执行报表动作:

odoo.define("colona_custo.print_product_label", function(require) {
"use strict";

var rpc = require("web.rpc");
var ActionManager = require('web.ActionManager');  // 新增引入

function call_print_function(nb_printing, move_line_id)
{
    console.log(nb_printing);
    console.log(move_line_id);

    return rpc.query({
        model: 'print.product.label.wizard',
        method: 'print_product_label_from_js',
        args: [[], nb_printing, move_line_id]
    }).then(function(action) {
        // 用ActionManager执行报表动作
        var actionManager = new ActionManager();
        actionManager.doAction(action);
        // 执行后关闭弹窗
        $('#warning_popup').hide();
    }).catch(function(error) {
        console.error('打印出错:', error);
    });
}

// 其余代码保持不变
function print_product_label()
{
    var move_line_id = $(this).next().text();

    $(document.body).append("<div id='warning_popup' style='background: rgba(255, 255, 255, 0.9); width: 50vw; height: 50vh; border-radius: 5px; padding: 10px; z-index: 1000; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);'><h2 style='position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);'>How many times do you want to print the product label?</h2><input id='user_entry' style='position:relative;top:50%;left:45%;'/><button id='action_print' style='position: absolute; bottom: 5px; left: 100px;' class='btn btn-primary'>Print</button><button id='close_popup_printing' style='position: absolute; bottom: 5px; left: 5px;' class='btn btn-primary'>Close</button></div>")
    $('#close_popup_printing').on('click', function() {
        $('#warning_popup').hide();
    });

    $('#action_print').on('click', function() {
        var nb_printing = $('#user_entry').val();
        if (nb_printing > 0) {
            call_print_function(nb_printing, move_line_id);
        }

    });
}

$(document).on('click', '.o_button_print_product_label', print_product_label)});

2. 优化Python方法(可选)

给print_product_label_from_js添加@api.model装饰器,明确为模型级方法:

@api.model
def print_product_label_from_js(self, nb_printing=1, move_line_id=34):
    print("===========================")
    print("Hello, function is launched.")
    return self.env.ref('colona_custo.action_report_product_label').report_action([], data={'stock_move_line_id': int(move_line_id), 'nb_printing': int(nb_printing)})

3. 额外优化建议

  • 增加用户输入校验,确保nb_printing是有效整数,避免类型转换错误。
  • 弹窗可以使用Odoo自带的弹窗组件(如Dialog),替代原生DOM拼接,提升兼容性和风格统一。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 19:54:24