Odoo10销售订单unlink方法重写及订单行验证移除问题咨询
1. 如何重写销售订单(Sale Order)的unlink方法?
重写销售订单的unlink方法其实很简单,你只需要在自定义模块里继承sale.order模型,重新定义unlink方法即可,步骤如下:
- 准备自定义模块:确保你有一个可用的自定义模块(如果没有,先创建包含
__manifest__.py等核心文件的模块)。 - 继承目标模型:在模块的
models目录下创建Python文件,导入必要模块后继承sale.order。 - 重写
unlink方法:用@api.multi装饰器(Odoo 10中unlink默认使用该装饰器)编写自定义逻辑,最后调用父类方法完成实际删除操作。
示例代码参考:
from odoo import models, api, exceptions, _ class SaleOrder(models.Model): _inherit = 'sale.order' @api.multi def unlink(self): # 自定义验证逻辑:禁止删除金额超1000的已完成订单 forbidden_orders = self.filtered(lambda x: x.state == 'done' and x.amount_total > 1000) if forbidden_orders: raise exceptions.UserError(_('无法删除金额超过1000的已完成订单!')) # 调用父类方法执行实际删除 return super(SaleOrder, self).unlink()
你可以根据业务需求修改逻辑,比如跳过某些默认验证、添加删除前的清理操作等。
2. 重写销售订单行(Sale Order Line)的unlink方法时,函数已被调用,但无法移除原有的UserError验证
这个问题很常见,核心原因是你重写方法时依然调用了原sale.order.line的unlink方法,原方法的验证逻辑会被触发。先回顾Odoo默认的订单行unlink逻辑:
@api.multi
def unlink(self):
if self.filtered(lambda x: x.state in ('sale', 'done')):
raise UserError(_('You can not remove a sale order line.\nDiscard changes and try setting the quantity to 0.'))
return super(SaleOrderLine, self).unlink()
原方法会先检查订单行状态,若为sale或done则抛出错误。要移除这个验证,你需要跳过原方法的逻辑,或者完全替换验证规则,以下是两种解决方案:
方案1:完全移除原验证,允许删除任何状态的订单行
如果你想放开所有状态订单行的删除权限,可以直接调用最上层父类models.Model的unlink方法,跳过原sale.order.line的验证:
from odoo import models, api, exceptions, _ class SaleOrderLine(models.Model): _inherit = 'sale.order.line' @api.multi def unlink(self): # 可添加自定义验证(比如仅允许管理员删除已确认订单行) # if self.filtered(lambda x: x.state in ('sale', 'done')) and not self.env.user.has_group('base.group_system'): # raise exceptions.UserError(_('仅管理员可删除已确认的订单行!')) # 跳过原SaleOrderLine的验证,直接执行底层删除逻辑 return super(models.Model, self).unlink()
方案2:修改原验证逻辑,保留部分限制
如果你只想调整验证条件(比如禁止删除已发货的订单行,但允许删除未发货的),可以替换原有的过滤规则:
from odoo import models, api, exceptions, _ class SaleOrderLine(models.Model): _inherit = 'sale.order.line' @api.multi def unlink(self): # 自定义过滤:禁止删除已发货的订单行 forbidden_lines = self.filtered(lambda x: x.state in ('sale', 'done') and x.qty_delivered > 0) if forbidden_lines: raise exceptions.UserError(_('无法删除已发货的订单行!')) # 调用父类方法完成删除(此时原验证逻辑已被覆盖) return super(SaleOrderLine, self).unlink()
这样修改后,原有的UserError就不会再触发了,验证逻辑完全由你自定义。
内容的提问来源于stack exchange,提问作者Pawan Kumar Sharma

