Odoo 13:按卖家ID拆分销售订单奖励折扣时write()函数更新错误记录问题求助
Hey there! Let's break down what's going wrong and how to fix your reward discount splitting by seller ID in Odoo.
First, Identify the Root Issues
From your code and problem description, the write() function updating the wrong records likely stems from inconsistent grouping logic for reward lines, plus Odoo's default behavior of matching reward lines based on tax IDs (and other core fields) instead of your new seller ID field. Here are the key pain points:
Inconsistent Reward Dictionary Keys
In thecheapest_productbranch, you're usingline.tax_id(a recordset) as the dictionary key, but in thespecific_products/on_orderbranches, you're using a string likeseller_id-tax_id. These key types don't match, so Odoo can't correctly group or match existing reward lines when updating.Tax ID Handling for Multi-Tax Lines
If a line has multiple taxes (e.g., compound taxes), usingstr(line.tax_id.id)will only get the first tax's ID, leading to duplicate keys for lines with different tax combinations but the same first tax ID.Missing Seller ID in Reward Line Matching
Odoo's default reward line update logic doesn't know about your newpartner_vendor_idfield. Even if you set it, Odoo might still match reward lines by tax ID/product ID alone, causing it to overwrite the wrong line instead of creating a new one for a different seller.
Step-by-Step Fixes
1. Unify Reward Dictionary Keys Across All Branches
Update the key generation logic to use a consistent, unique string based on seller ID + all tax IDs for every branch. This ensures lines with different sellers (even same taxes) get their own reward entries.
Adjust the cheapest_product branch:
elif program.discount_apply_on == 'cheapest_product': line = self._get_cheapest_line() if line: discount_line_amount = min(line.price_reduce * (program.discount_percentage / 100), amount_total) if discount_line_amount: # Get seller ID (handle cases where no seller exists) seller = line.product_id._select_seller() if not seller: continue # or assign a default ID like 0 seller_id = seller.name.id # Generate unique key with all tax IDs (comma-separated) tax_ids_str = ','.join(str(tax.id) for tax in line.tax_id) select_key = f"{seller_id}-{tax_ids_str}" taxes = line.tax_id if self.fiscal_position_id: taxes = self.fiscal_position_id.map_tax(taxes) reward_dict[select_key] = { 'name': _("Discount: ") + program.name + f" - Seller: {seller.name.name}", 'product_id': program.discount_line_product_id.id, 'price_unit': -discount_line_amount if discount_line_amount > 0 else 0, 'product_uom_qty': 1.0, 'product_uom': program.discount_line_product_id.uom_id.id, 'is_reward_line': True, 'tax_id': [(4, tax.id, False) for tax in taxes], 'partner_vendor_id': seller_id, # Add seller ID here too }
Update the specific_products/on_order branch's key generation to handle multi-tax lines properly:
# Replace your existing _select_seller_id line with this: seller = line.product_id._select_seller() if not seller: continue seller_id = seller.name.id tax_ids_str = ','.join(str(tax.id) for tax in line.tax_id) select_key = f"{seller_id}-{tax_ids_str}"
2. Ensure Odoo Recognizes partner_vendor_id for Reward Line Matching
Odoo's default _update_reward_lines method uses fields like product_id, tax_id, and is_reward_line to match existing lines. Override this method to include the seller ID in the matching criteria:
def _update_reward_lines(self): # Run Odoo's default logic first super()._update_reward_lines() # Ensure reward lines are split by seller ID existing_reward_lines = self.order_line.filtered(lambda l: l.is_reward_line) # Get active discount programs (adjust this to match your actual program retrieval) active_programs = self._get_applicable_programs() for program in active_programs: reward_vals_list = self._get_reward_values_discount(program) for reward_vals in reward_vals_list: # Match existing lines by product, reward flag, tax ID, AND seller ID match_lines = existing_reward_lines.filtered( lambda l: l.product_id.id == reward_vals['product_id'] and l.tax_id.ids == [tax[1] for tax in reward_vals['tax_id']] and l.partner_vendor_id == reward_vals['partner_vendor_id'] ) if len(match_lines) > 1: # Clean up duplicate lines match_lines[1:].unlink() elif not match_lines: # Create new line if no match exists self.order_line.create(reward_vals) else: # Update existing line with correct values match_lines.write(reward_vals)
3. Handle Edge Cases
- Products Without Sellers: Add fallback logic (like assigning a default seller ID or skipping the discount line) to avoid errors when
_select_seller()returns nothing. - Max Discount Amount: Verify your max amount calculation correctly splits across seller-specific reward lines, not just tax lines.
Testing Tips
- Enable debug logging for your
reward_dictto verify each seller+tax combination gets a unique entry. - Check the
partner_vendor_idfield on created reward lines to confirm it's set correctly. - Test scenarios with multiple sellers, multi-tax lines, and mixed discount types to ensure all cases work as expected.
内容的提问来源于stack exchange,提问作者Deepak Raj

