Odoo 17中如何关联stock.picking与account.move(发票)并显示智能按钮
Odoo发票过账自动创建出库单并关联智能按钮问题解决
问题概述
定制需求:account.move(发票)过账时自动创建stock.picking(出库单),并完成关联以让发票上的发货智能按钮正常显示。已知这是Odoo默认逻辑,但当前手动创建出库单后无法关联,找不到对应关联字段;手动新增字段后问题仍存在,智能按钮依旧不显示。
当前代码如下:
from odoo import fields, models, api, _ class AccountMove(models.Model): _inherit = 'account.move' def action_post(self): res = super(AccountMove, self).action_post() if not self.invoice_line_ids.sale_line_ids and self.move_type == 'out_invoice': picking_type = self.env.ref('stock.picking_type_out') stock_picking = self.env['stock.picking'].create({ 'picking_type_id': picking_type.id, 'location_id': picking_type.default_location_src_id.id, 'location_dest_id': self.env.ref('stock.stock_location_customers').id, 'partner_id': self.partner_id.id, 'origin': self.name, 'move_type': 'direct', 'move_ids': [(0, 0, { 'name': line.name, 'product_id': line.product_id.id, 'product_uom_qty': line.quantity, 'product_uom': line.product_uom_id.id, 'location_id': picking_type.default_location_src_id.id, 'location_dest_id': self.env.ref('stock.stock_location_customers').id, }) for line in self.invoice_line_ids if line.product_id.type == 'product'] }) stock_picking.action_confirm() for move in stock_picking.move_ids: self.env['stock.move.line'].create({ 'move_id': move.id, 'product_id': move.product_id.id, 'product_uom_id': move.product_uom.id, 'location_id': move.location_id.id, 'location_dest_id': self.env.ref('stock.stock_location_customers').id, 'state': 'done', 'picking_id': move.picking_id.id, }) # Link the invoice to the picking #self.write({ # 'move_ids': [(4, stock_picking.id)] #}) stock_picking.button_validate() return res
问题分析与修复方案
核心问题点
- 关联字段错误:注释中尝试用
move_ids关联发票和出库单,但move_ids是account.move关联自身会计分录行的字段,与stock.picking无关。 - 库存移动未关联发票行:创建
stock.move时未绑定对应的account.move.line,导致发票无法识别关联的出库记录,智能按钮无数据可显示。 - 出库单验证逻辑错误:将
stock_picking.button_validate()放在循环内部,会在每创建一条库存明细行后就触发验证,逻辑混乱。 - 库存明细行缺失必填项:创建
stock.move.line时未设置qty_done,直接设state='done'会导致验证失败。
修改后的代码
from odoo import fields, models, api, _ class AccountMove(models.Model): _inherit = 'account.move' def action_post(self): res = super(AccountMove, self).action_post() if not self.invoice_line_ids.sale_line_ids and self.move_type == 'out_invoice': picking_type = self.env.ref('stock.picking_type_out') # 构建库存移动数据,关联对应的发票行 move_vals_list = [] for line in self.invoice_line_ids: if line.product_id.type == 'product': move_vals_list.append((0, 0, { 'name': line.name, 'product_id': line.product_id.id, 'product_uom_qty': line.quantity, 'product_uom': line.product_uom_id.id, 'location_id': picking_type.default_location_src_id.id, 'location_dest_id': self.env.ref('stock.stock_location_customers').id, 'invoice_line_id': line.id, # 关键:绑定到发票行 })) stock_picking = self.env['stock.picking'].create({ 'picking_type_id': picking_type.id, 'location_id': picking_type.default_location_src_id.id, 'location_dest_id': self.env.ref('stock.stock_location_customers').id, 'partner_id': self.partner_id.id, 'origin': self.name, 'move_type': 'direct', 'move_ids': move_vals_list, }) stock_picking.action_confirm() for move in stock_picking.move_ids: self.env['stock.move.line'].create({ 'move_id': move.id, 'product_id': move.product_id.id, 'product_uom_id': move.product_uom.id, 'location_id': move.location_id.id, 'location_dest_id': self.env.ref('stock.stock_location_customers').id, 'qty_done': move.product_uom_qty, # 新增:设置已完成数量 'picking_id': move.picking_id.id, }) # 所有明细行创建完成后再验证出库单 stock_picking.button_validate() return res
关键修改说明
- 绑定库存移动到发票行:在创建
stock.move时添加invoice_line_id: line.id,让库存移动与发票分录行建立关联,这样发票的stock_move_ids会自动包含这些移动记录,触发智能按钮显示。 - 调整验证时机:将
stock_picking.button_validate()移到循环外部,确保所有库存明细行都创建完成后再执行验证,避免逻辑错误。 - 补充必填字段:在
stock.move.line中添加qty_done并设置为对应数量,保证出库单能正常验证通过。
内容的提问来源于stack exchange,提问作者Rahma Begag
相关产品推荐
相关产品推荐

