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

Odoo12修改stock.picking的batch_id触发CacheMiss错误求助

Fixing Odoo 12 CacheMiss Error When Updating stock.picking's batch_id

I've run into this exact kind of cache issue in Odoo before, so let's break down what's causing your error and how to fix it.

What's Causing the CacheMiss?

Your error points to stock.picking.batch(31,).picking_batch_moves missing from the cache, and there are two key culprits here:

  1. Bypassing ORM with raw SQL: Your compute method uses self.env.cr.execute to fetch data, which skips Odoo's built-in cache tracking. When you update a picking's batch_id, Odoo tries to refresh the batch's computed fields but can't sync the cache with the raw database changes.
  2. Incorrect recordset initialization: Inside your batch loop, you set linked = batch_moves_obj (the entire model object) instead of an empty recordset. This leads to invalid data being assigned to picking_batch_moves, confusing Odoo's cache system.

Step-by-Step Fix

Let's rewrite the compute method to use Odoo's ORM properly and fix the recordset handling:

1. Replace Raw SQL with ORM Queries

Using ORM ensures Odoo tracks data changes and maintains cache consistency. Here's the updated compute method:

@api.depends("picking_ids", "picking_ids.move_lines")
def _compute_picking_get_batch_lines(self):
    batch_moves_obj = self.env["stock.picking.batch.move"]
    for batch in self:
        if isinstance(batch.id, models.NewId):
            continue
        
        # Fetch all moves linked to this batch via pickings
        moves = self.env['stock.move'].search([
            ('picking_id.batch_id', '=', batch.id)
        ])
        
        # Group moves by product, UOM, locations, state, and picking type
        grouped_data = {}
        for move in moves:
            group_key = (
                move.product_id.id,
                move.product_uom.id,
                move.location_id.id,
                move.location_dest_id.id,
                move.state,
                move.picking_type_id.id
            )
            if group_key not in grouped_data:
                grouped_data[group_key] = {
                    'product_id': move.product_id.id,
                    'product_uom_id': move.product_uom.id,
                    'location_id': move.location_id.id,
                    'location_dest_id': move.location_dest_id.id,
                    'state': move.state,
                    'picking_type_id': move.picking_type_id.id,
                    'product_uom_qty': 0.0,
                    'move_ids': []
                }
            grouped_data[group_key]['product_uom_qty'] += move.product_uom_qty
            grouped_data[group_key]['move_ids'].append(move.id)
        
        # Get existing batch moves for this batch
        existing_batch_moves = batch_moves_obj.search([("batch_id", "=", batch.id)])
        linked = self.env["stock.picking.batch.move"]  # Start with empty recordset
        
        for group in grouped_data.values():
            line_data = {
                "batch_id": batch.id,
                "product_id": group['product_id'],
                "product_uom_id": group['product_uom_id'],
                "location_id": group['location_id'],
                "location_dest_id": group['location_dest_id'],
                "state": group['state'],
                "picking_type_id": group['picking_type_id'],
                "product_uom_qty": group['product_uom_qty'],
                "move_lines": [(6, 0, group['move_ids'])],
            }
            
            # Find matching existing batch move
            matched = existing_batch_moves.filtered(
                lambda x: (x.product_id.id == group['product_id'] and 
                           x.product_uom_id.id == group['product_uom_id'] and 
                           x.location_id.id == group['location_id'] and 
                           x.location_dest_id.id == group['location_dest_id'] and 
                           x.state == group['state'])
            )
            
            if matched.exists():
                matched.write(line_data)
                linked += matched
            else:
                new_line = batch_moves_obj.create(line_data)
                linked += new_line
        
        # Clean up old batch moves that no longer have matching moves
        to_unlink = existing_batch_moves - linked
        if to_unlink:
            to_unlink.unlink()
        
        # Assign the valid recordset to the batch field
        batch.picking_batch_moves = linked

2. Remove recompute=False Context

You were using with_context(recompute=False) when creating/writing batch moves, which prevents Odoo from updating related computed fields and cache. Removing this ensures the cache stays in sync with your data changes.

3. Add Cleanup Logic

The new code includes a step to delete old batch moves that don't have any matching stock moves anymore. This keeps your data consistent and avoids orphaned records that could also cause cache issues.

Why This Works

  • ORM Usage: Odoo's ORM automatically tracks all data operations, so when you update a picking's batch_id, the cache is refreshed correctly for the related batch.
  • Proper Recordset Handling: Initializing linked as an empty recordset ensures you only assign valid, batch-specific moves to picking_batch_moves.
  • Cache Consistency: By letting Odoo manage data changes instead of bypassing it with raw SQL, you eliminate the cache mismatch that caused the CacheMiss error.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 13:57:31