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

OdooRPC创建Manufacturing Order(MO)时如何生成关联库存调拨单

Odoo 15 编程创建生产订单(MO)时自动生成关联库存调拨单的解决方案

问题场景

在Odoo 15中通过代码创建生产订单(Manufacturing Order, MO)时,MO能成功生成,但关联的库存调拨单(stock.pickings) 未按预期创建。手动在前端创建MO时,库存调拨单可正常生成,尝试用onchange方法解决但无效,需找到编程创建MO时自动生成并关联库存调拨单的可行方案。

原代码示例

import odoorpc

def create_mo(product_id, product_qty, picking_type_id):
    # Define the connection parameters
    db = ''
    url = ''
    username = ''
    password = ''

    # Initialize the connection
    odoo = odoorpc.ODOO(url)

    # Authenticate
    odoo.login(db, username, password)

    # Get the picking type record
    picking_type = odoo.env['stock.picking.type'].browse(picking_type_id)

    # Access the mrp.bom model
    mrp_bom_model = odoo.env['mrp.bom']

    # Get the product template ID from the product ID
    product_template_id = odoo.env['product.product'].browse(product_id).product_tmpl_id.id

    # Define the search domain based on the product template ID
    search_domain = [('product_tmpl_id', '=', product_template_id)]

    # Search for the BOM record
    bom_ids = mrp_bom_model.search(search_domain)

    # Check if a BOM was found
    if bom_ids:
        # Retrieve the BOM record
        bom_record = mrp_bom_model.browse(bom_ids[0])

        # Access the mrp.production model to create the MO
        mrp_production_model = odoo.env['mrp.production']

        # Define the values for the new MO record
        values = {
            'product_id': product_id,
            'product_qty': product_qty,
            'bom_id': bom_record.id,
            'product_uom_id': bom_record.product_uom_id.id,
            'picking_type_id': picking_type.id,
            'location_src_id': 17,
            'location_dest_id': 18,
            
        }

        # Calculate the components from the BOM lines
        components = []
        for line in bom_record.bom_line_ids:
            components.append({
                'name': line.product_id.name,
                'product_id': line.product_id.id,
                'product_uom': line.product_uom_id.id,
                'product_uom_qty': line.product_qty * product_qty,
                'location_id': picking_type.default_location_src_id.id,
                'location_dest_id': picking_type.default_location_dest_id.id,
            })

        # Add the components to the MO values
        values['move_raw_ids'] = [(0, 0, line) for line in components]

        # Create the MO
        new_mo_id = mrp_production_model.create(values)

        # Confirm the MO
        mrp_production_model.button_plan([new_mo_id])


        # Browse the newly created MO
        new_mo = mrp_production_model.browse(new_mo_id)

        # Print the ID of the new MO
        print("New Manufacturing Order created with ID:", new_mo_id)
    else:
        print("No BOM found for the specified product.")

create_mo(6666,1,8)

问题分析与修正方案

核心问题

手动构建move_raw_ids跳过了Odoo内部的关联逻辑,且方法调用顺序不符合前端创建MO的流程,导致库存调拨单未被触发生成。

修正后的代码

import odoorpc

def create_mo(product_id, product_qty, picking_type_id):
    # 连接参数
    db = ''
    url = ''
    username = ''
    password = ''

    # 初始化连接并认证
    odoo = odoorpc.ODOO(url)
    odoo.login(db, username, password)

    # 获取领料类型记录
    picking_type = odoo.env['stock.picking.type'].browse(picking_type_id)

    # 查找对应产品的BOM
    mrp_bom_model = odoo.env['mrp.bom']
    product_template_id = odoo.env['product.product'].browse(product_id).product_tmpl_id.id
    bom_ids = mrp_bom_model.search([('product_tmpl_id', '=', product_template_id)])

    if bom_ids:
        bom_record = mrp_bom_model.browse(bom_ids[0])
        mrp_production_model = odoo.env['mrp.production']

        # 基础MO参数,不手动添加move_raw_ids
        values = {
            'product_id': product_id,
            'product_qty': product_qty,
            'bom_id': bom_record.id,
            'product_uom_id': bom_record.product_uom_id.id,
            'picking_type_id': picking_type.id,
            # 使用领料类型默认位置,避免硬编码
            'location_src_id': picking_type.default_location_src_id.id,
            'location_dest_id': picking_type.default_location_dest_id.id,
        }

        # 创建MO
        new_mo_id = mrp_production_model.create(values)
        new_mo = mrp_production_model.browse(new_mo_id)

        # 模拟前端onchange_bom_id逻辑,自动生成物料移动记录
        new_mo.onchange_bom_id()

        # 按正确顺序执行确认、计划操作,触发调拨单生成
        new_mo.button_confirm()
        new_mo.button_plan()

        # 验证调拨单生成情况
        picking_ids = new_mo.move_raw_ids.mapped('picking_id')
        if picking_ids:
            print(f"生产订单 {new_mo_id} 创建成功,关联库存调拨单ID: {[p.id for p in picking_ids]}")
        else:
            print(f"生产订单 {new_mo_id} 创建成功,但未生成库存调拨单,请检查参数配置")
    else:
        print("未找到该产品对应的BOM")

create_mo(6666, 1, 8)

关键修正点

  • 移除手动构建move_raw_ids:让Odoo通过onchange_bom_id()自动生成物料移动记录,确保携带完整的关联上下文。
  • 使用领料类型默认位置:替换硬编码的位置ID,保持与前端创建逻辑一致。
  • 调整方法调用顺序:先执行button_confirm()确认MO,再执行button_plan()计划生产,触发库存调拨单的生成逻辑。
  • 添加调拨单验证:生成MO后检查关联的调拨单,确认结果。

额外检查项

  • 确认领料类型(picking_type_id)的默认源位置、目标位置配置正确。
  • 检查BOM物料行的库存位置设置是否正常。
  • 确保产品具备可库存、可生产的属性配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 14:37:32