Odoo中通过XMLRPC创建带批次的stock.picking验证失败问题
Odoo创建stock.picking验证失败问题解决
错误提示
无法验证库存调拨:未预留或完成任何数量。
问题场景
在Odoo内部通过Python代码创建stock.picking并执行验证操作时触发上述错误,原代码如下:
picking_data = { 'picking_type_id': 1, # 替换为实际调拨类型ID 'location_dest_id': 8, # 替换为实际目标位置ID 'location_id': 4, # 替换为实际源位置ID 'move_ids': [ (0, 0, { "name":"Movida1", 'location_id': 4, 'location_dest_id': 8, 'product_id': 376, # 替换为实际产品ID 'product_uom_qty': 10, 'product_uom': 1, # 替换为实际单位ID 'move_line_ids': [ (0, 0, { 'product_id': 376, # 替换为实际产品ID 'lot_id':12, 'qty_done':5, 'lot_name':'LOT001' } ), (0, 0, { 'product_id': 376, # 替换为实际产品ID 'lot_id':14, 'qty_done':5, 'lot_name':'LOT003' } ), ], }), ], } picking = self.env['stock.picking'].create(picking_data) picking.action_confirm() picking.action_assign() picking.button_validate()
问题原因
- 创建
move时直接嵌套move_line_ids的写法存在问题,执行action_assign时Odoo会自动生成预留库存行,覆盖手动设置的qty_done数据 - 同时指定
lot_id和lot_name会造成数据冲突,lot_id已明确时无需再传lot_name - 验证时系统检测不到有效的已完成数量,因此抛出错误
修正方案
方案一:手动维护库存行(推荐)
创建调拨后先确认动作,再手动生成包含qty_done的库存行,避免自动预留覆盖数据:
picking_data = { 'picking_type_id': 1, 'location_dest_id': 8, 'location_id': 4, 'move_ids': [ (0, 0, { "name": "Movida1", 'location_id': 4, 'location_dest_id': 8, 'product_id': 376, 'product_uom_qty': 10, 'product_uom': 1, }), ], } picking = self.env['stock.picking'].create(picking_data) picking.action_confirm() # 遍历所有调拨行,手动创建库存行 for move in picking.move_ids: # 清除自动生成的预留库存行 move.move_line_ids.unlink() # 添加自定义库存行,明确设置qty_done move.move_line_ids = [ (0, 0, { 'product_id': 376, 'lot_id': 12, 'qty_done': 5, 'location_id': move.location_id.id, 'location_dest_id': move.location_dest_id.id, 'product_uom_id': move.product_uom.id, }), (0, 0, { 'product_id': 376, 'lot_id': 14, 'qty_done': 5, 'location_id': move.location_id.id, 'location_dest_id': move.location_dest_id.id, 'product_uom_id': move.product_uom.id, }), ] # 执行验证 picking.button_validate()
方案二:强制跳过预留验证
若无需执行库存预留逻辑,可通过上下文参数直接强制验证:
picking_data = { # 保持原数据结构,可移除move_line_ids嵌套 'picking_type_id': 1, 'location_dest_id': 8, 'location_id': 4, 'move_ids': [ (0, 0, { "name": "Movida1", 'location_id': 4, 'location_dest_id': 8, 'product_id': 376, 'product_uom_qty': 10, 'product_uom': 1, }), ], } picking = self.env['stock.picking'].create(picking_data) picking.action_confirm() # 通过skip_immediate上下文跳过预留,直接验证 picking.with_context(skip_immediate=True).button_validate()
关键注意事项
- 避免在创建
move时直接嵌套move_line_ids,优先在确认调拨后手动维护库存行 - 已指定
lot_id时不要重复设置lot_name,防止数据冲突 - 验证前必须确保
move_line的qty_done总和与move的product_uom_qty匹配
内容的提问来源于stack exchange,提问作者hidura
相关产品推荐
相关产品推荐

