ODOO 代码修改后,如何生效

本文介绍了Odoo服务器代码升级的流程,包括Python、XML、CSS及JS等文件的修改方式及其对服务的影响。对于Python文件,需要重启服务;XML文件则通过升级模块实现;而CSS和JS文件只需刷新浏览器即可看到效果。
服务器升级ODOO 代码需要做的工作可以根据修改文件不同分为以下几种:
  • 修改 python 文件: 必须重启服务,以重写编译生产 *.pyc 文件。 如果是修改函数,不需要升级模块,如果修改模型字段或依赖关系,需要升级模块。
  • 修改 XML 文件: 不需要重启服务, 升级相关模块。
  • 修改CSS 文件: 刷新浏览器重新加载。
  • 修改JS 文件: 刷新浏览器重新加载。
<think>我们正在将之前为Odoo 8/9/10等旧版本编写的代码迁移到Odoo 16。Odoo 16使用了Python 3.8+,并引入了许多API变化。以下是针对之前添加的`multi.level.commission`模型代码修改点,以使其兼容Odoo 16: ### 1. 模型文件修改 (`models/commission_level.py`) #### 修改点: - **移除`# -*- coding: utf-8 -*-`**:Python 3默认使用UTF-8,不需要特别声明。 - **字段字符串参数**:在Odoo 16中,字段的字符串参数(即显示名称)应该放在第一个位置,并明确使用`string`关键字参数(虽然旧版也可以,但新版更规范)。 - **`api.one`和`api.multi`的替代**:使用`api.model`和`api.depends`等替代。 - **`_description`类属性**:在Odoo 16中,每个模型必须定义`_description`。 - **`default`参数**:在`fields.Many2one`中,`default`参数现在更推荐使用可调用对象(如lambda函数),但旧写法仍然兼容。 - **`_constraints`和`_sql_constraints`**:仍然有效,但约束方法可以使用`@api.constrains`装饰器。 - **浮点数比较**:避免直接比较浮点数,使用工具函数(如`float_compare`)来比较。 #### 修改后的代码: ```python from odoo import models, fields, api, exceptions, tools class MultiLevelCommission(models.Model): _name = 'multi.level.commission' _description = 'Multi-level Sales Commission Rules' _order = 'sequence, id' name = fields.Char(string='规则名称', required=True) sequence = fields.Integer(string='优先级', default=10, help="数字越小优先级越高") active = fields.Boolean(string='激活', default=True) company_id = fields.Many2one( 'res.company', string='公司', default=lambda self: self.env.company) # 佣金层级定义 level_lines = fields.One2many( 'commission.level.line', 'commission_id', string='佣金层级') # 适用条件 apply_on = fields.Selection([ ('global', '全局规则'), ('team', '销售团队'), ('salesman', '销售人员'), ('category', '产品类别')], string='适用对象', default='global', required=True) team_id = fields.Many2one('crm.team', string='销售团队') salesman_id = fields.Many2one('res.users', string='销售人员') category_id = fields.Many2one('product.category', string='产品类别') # 生效日期范围 date_from = fields.Date(string='生效日期') date_to = fields.Date(string='截止日期') # 约束条件 _sql_constraints = [ ('date_range_check', "CHECK (date_from <= date_to OR date_to IS NULL)", "截止日期必须晚于生效日期"), ] @api.constrains('level_lines') def _check_level_ranges(self): for record in self: ranges = [] for line in record.level_lines: # 检查范围重叠 for r in ranges: if max(line.min_value, r['min']) <= min(line.max_value, r['max']): raise exceptions.ValidationError( "层级范围重叠: %s 与 %s" % (line.name, r['name'])) ranges.append({ 'min': line.min_value, 'max': line.max_value, 'name': line.name }) class CommissionLevelLine(models.Model): _name = 'commission.level.line' _description = 'Commission Level Line' _order = 'min_value asc' name = fields.Char(string='层级名称', compute='_compute_name', store=True) commission_id = fields.Many2one( 'multi.level.commission', string='佣金规则', required=True, ondelete='cascade') # 层级条件 min_value = fields.Float(string='最小值', required=True) max_value = fields.Float(string='最大值', required=True) commission_percent = fields.Float(string='佣金比例(%)', required=True) # 自动计算层级名称 @api.depends('min_value', 'max_value') def _compute_name(self): for line in self: if line.max_value == float('inf'): line.name = f"{line.min_value}+" else: line.name = f"{line.min_value}-{line.max_value}" ``` ### 2. 视图文件修改 (`views/commission_level_views.xml`) #### 修改点: - **视图结构**:Odoo 16的视图结构基本兼容旧版,但需要注意: - 按钮的`type`属性:旧版中`type="object"`仍然有效,但推荐使用`type="action"`或`type="method"`(根据具体用途)。 - 归档按钮:Odoo 16中可以使用`<field name="active"/>`字段和内置的归档/取消归档操作,不需要自定义按钮。 - 使用`<field>`的`options`属性来传递一些参数。 #### 修改后的视图(简化并更新): ```xml <?xml version="1.0" encoding="utf-8"?> <odoo> <!-- 佣金规则表单视图 --> <record id="view_multi_level_commission_form" model="ir.ui.view"> <field name="name">multi.level.commission.form</field> <field name="model">multi.level.commission</field> <field name="arch" type="xml"> <form> <header> <button name="action_archive" type="object" string="归档" class="oe_stat_button" attrs="{'invisible': [('active','=',False)]}"/> <button name="action_unarchive" type="object" string="取消归档" class="oe_stat_button" attrs="{'invisible': [('active','=',True)]}"/> </header> <sheet> <group> <field name="name"/> <field name="sequence"/> <field name="apply_on"/> <field name="team_id" attrs="{'invisible': [('apply_on','!=','team')]}"/> <field name="salesman_id" attrs="{'invisible': [('apply_on','!=','salesman')]}"/> <field name="category_id" attrs="{'invisible': [('apply_on','!=','category')]}"/> <field name="date_from"/> <field name="date_to"/> </group> <field name="level_lines"> <tree editable="bottom"> <field name="name" readonly="1"/> <field name="min_value"/> <field name="max_value"/> <field name="commission_percent"/> </tree> </field> </sheet> </form> </field> </record> <!-- 佣金规则树形视图 --> <record id="view_multi_level_commission_tree" model="ir.ui.view"> <field name="name">multi.level.commission.tree</field> <field name="model">multi.level.commission</field> <field name="arch" type="xml"> <tree> <field name="name"/> <field name="apply_on"/> <field name="team_id"/> <field name="salesman_id"/> <field name="active"/> </tree> </field> </record> <!-- 佣金规则菜单和动作 --> <menuitem id="menu_commission_level_root" name="佣金规则" parent="sale_commission.menu_commission_root"/> <menuitem id="menu_commission_level" name="多级佣金规则" parent="menu_commission_level_root" action="action_multi_level_commission"/> <record id="action_multi_level_commission" model="ir.actions.act_window"> <field name="name">多级佣金规则</field> <field name="res_model">multi.level.commission</field> <field name="view_mode">tree,form</field> </record> </odoo> ``` ### 3. 修改佣金计算逻辑(`sale_commission_salesman`的`sale_order.py`) #### 修改点: - **`@api.depends`**:在Odoo 16中,计算字段的依赖关系仍然使用`@api.depends`。 - **搜索方法**:`search`方法的使用方式相同,但注意Odoo 16中的记录集操作更严格。 - **浮点数比较**:使用`tools.float_compare`来避免浮点数精度问题。 #### 修改后的计算逻辑: ```python from odoo import models, fields, api, tools class SaleOrderLine(models.Model): _inherit = 'sale.order.line' @api.depends('price_subtotal', 'product_id', 'order_id.user_id') def _compute_commission(self): """重写佣金计算方法以支持多层规则""" super(SaleOrderLine, self)._compute_commission() for line in self.filtered(lambda l: l.price_subtotal > 0): # 获取适用的佣金规则 rules = self.env['multi.level.commission'].search([ '|', ('date_from', '<=', line.order_id.date_order.date()), ('date_from', '=', False), '|', ('date_to', '>=', line.order_id.date_order.date()), ('date_to', '=', False), '|', ('apply_on', '=', 'global'), '&', ('apply_on', '=', 'team'), ('team_id', '=', line.order_id.team_id.id), '&', ('apply_on', '=', 'salesman'), ('salesman_id', '=', line.order_id.user_id.id), '&', ('apply_on', '=', 'category'), ('category_id', '=', line.product_id.categ_id.id), ], order='sequence') # 应用匹配的规则 commission_val = 0.0 for rule in rules: for level in rule.level_lines: # 使用浮点数比较工具 if tools.float_compare(line.price_subtotal, level.min_value, precision_digits=2) >= 0 and \ (tools.float_compare(line.price_subtotal, level.max_value, precision_digits=2) <= 0 or level.max_value == float('inf')): commission_val = line.price_subtotal * level.commission_percent / 100 break if commission_val: break line.commission = commission_val ``` ### 4. 访问权限文件 (`security/ir.model.access.csv`) 在Odoo 16中,权限文件的格式没有变化,但注意模型标识(`model_id/id`)的格式应为`model_<model_name>`,其中`<model_name>`是模型名称(点替换为下划线)。例如,`multi.level.commission`模型对应的标识为`model_multi_level_commission`。 ### 5. 其他注意事项 - **Python 3语法**:确保使用Python 3的语法(如`print`函数,除法运算符等)。 - **导入路径**:确保在`__init__.py`中正确导入模型文件。 - **菜单结构**:Odoo 16的菜单结构没有重大变化,但注意父菜单的XML ID是否存在。 - **多公司支持**:在计算佣金规则时,考虑当前记录的公司(如果规则中定义了公司)。 ### 测试建议 1. 在Odoo 16环境中安装模块,检查是否有错误。 2. 创建佣金规则并测试计算逻辑。 3. 测试不同适用条件(全局、团队、销售人员、产品类别)的规则。 4. 测试日期范围限制和优先级。 通过以上修改代码应该能够在Odoo 16中正常运行。如果遇到问题,请检查Odoo日志以获取详细错误信息[^1]。 §§相关问题§§ 1. 在Odoo 16中如何调试自定义模块的计算字段? 2. 如何为佣金规则添加多公司支持? 3. 如何优化佣金规则搜索以提高性能? 4. 佣金计算如何考虑折扣和税费?</think>### 修改代码以兼容 Odoo 16 的关键调整 以下是针对 Odoo 16 的核心修改点,主要涉及 API 变更、字段定义和计算逻辑优化: #### 1. 模型文件修改 (`models/commission_level.py`) ```python from odoo import models, fields, api, exceptions class MultiLevelCommission(models.Model): _name = 'multi.level.commission' _description = '多层级销售佣金规则' # Odoo 16 强制要求_description _order = 'sequence, id' # 字段定义使用 string 参数在前 name = fields.Char(string='规则名称', required=True) sequence = fields.Integer(string='优先级', default=10, help="数字越小优先级越高") active = fields.Boolean(string='激活', default=True) company_id = fields.Many2one( 'res.company', string='公司', default=lambda self: self.env.company) # 使用 env.company # 适用条件选择字段 apply_on = fields.Selection( selection=[ # Odoo 16 要求 selection 参数名 ('global', '全局规则'), ('team', '销售团队'), ('salesman', '销售人员'), ('category', '产品类别') ], string='适用对象', default='global', required=True ) # 约束条件更新 @api.constrains('level_lines') def _check_level_ranges(self): for record in self: ranges = [] for line in record.level_lines: for r in ranges: if max(line.min_value, r['min']) <= min(line.max_value, r['max']): raise exceptions.ValidationError( "层级范围重叠: %s 与 %s" % (line.name, r['name'])) # 移除 f-string ranges.append({ 'min': line.min_value, 'max': line.max_value, 'name': line.name }) class CommissionLevelLine(models.Model): _name = 'commission.level.line' _description = '佣金层级明细' # 添加描述 _order = 'min_value asc' # 计算字段定义 name = fields.Char(string='层级名称', compute='_compute_name', store=True) @api.depends('min_value', 'max_value') def _compute_name(self): for line in self: if line.max_value == float('inf'): line.name = "%s+" % line.min_value # 兼容 Python 2/3 的格式化 else: line.name = "%s-%s" % (line.min_value, line.max_value) ``` #### 2. 佣金计算逻辑修改 (`sale_commission_salesman/models/sale_order.py`) ```python from odoo import models, api, tools class SaleOrderLine(models.Model): _inherit = 'sale.order.line' @api.depends('price_subtotal', 'product_id', 'order_id.user_id') def _compute_commission(self): """重写佣金计算方法""" super()._compute_commission() # Odoo 16 推荐 super() 语法 for line in self.filtered(lambda l: l.price_subtotal > 0): # 使用安全的日期比较 order_date = fields.Date.to_date(line.order_id.date_order) # 构建域条件 domain = [ '|', ('date_from', '<=', order_date), ('date_from', '=', False), '|', ('date_to', '>=', order_date), ('date_to', '=', False), '|', ('apply_on', '=', 'global'), '|', '&', ('apply_on', '=', 'team'), ('team_id', '=', line.order_id.team_id.id), '|', '&', ('apply_on', '=', 'salesman'), ('salesman_id', '=', line.order_id.user_id.id), '&', ('apply_on', '=', 'category'), ('category_id', '=', line.product_id.categ_id.id) ] # 搜索并排序 rules = self.env['multi.level.commission'].search(domain, order='sequence') # 使用 float_compare 处理浮点数精度 for rule in rules: for level in rule.level_lines: subtotal = line.price_subtotal if ( tools.float_compare(subtotal, level.min_value, precision_digits=2) >= 0 and (tools.float_compare(subtotal, level.max_value, precision_digits=2) <= 0 or level.max_value == float('inf')) ): line.commission = subtotal * level.commission_percent / 100 break if line.commission: break ``` #### 3. 视图文件修改 (`views/commission_level_views.xml`) ```xml <!-- 更新按钮定义 --> <header> <button name="toggle_active" type="object" string="归档" class="oe_stat_button" icon="fa-archive" attrs="{'invisible': [('active','=', False)]}"/> <button name="toggle_active" type="object" string="取消归档" class="oe_stat_button" icon="fa-undo" attrs="{'invisible': [('active','=', True)]}"/> </header> <!-- 添加安全组控制 --> <record id="group_commission_manager" model="res.groups"> <field name="name">佣金规则管理员</field> <field name="category_id" ref="base.module_category_sales"/> </record> ``` #### 4. 权限文件修改 (`security/ir.model.access.csv`) ```csv id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink access_multi_level_commission,multi.level.commission,model_multi_level_commission,group_commission_manager,1,1,1,1 access_commission_level_line,commission.level.line,model_commission_level_line,group_commission_manager,1,1,1,1 ``` ### Odoo 16 兼容性关键修改点 1. **字段定义规范**: - 所有字段必须明确 `string` 参数 - 选择字段使用 `selection=` 参数 - 强制要求 `_description` 属性 2. **API 变更**: - 使用 `super().method()` 代替 `super(Class, self).method()` - 计算字段推荐使用 `@api.depends` 而非 `depends` - 移除 `api.one` 装饰器,统一使用 `api.model` 3. **视图系统更新**: - 按钮操作使用 `toggle_active` 代替自定义归档方法 - 图标使用 Font Awesome 5 (例如 `fa-archive`) - 安全组需明确指定分类 4. **浮点数处理**: - 使用 `tools.float_compare()` 处理精度问题 - 避免直接比较浮点相等性 5. **日期处理**: - 使用 `fields.Date.to_date()` 转换日期时间 - 时区敏感操作使用 `fields.Datetime` 上下文 6. **权限系统**: - 推荐使用安全组而非全局权限 - 权限组需关联应用分类 ### 测试建议(Odoo 16 特定) 1. **多公司测试**: ```python # 确保公司字段正确处理 rule = self.env['multi.level.commission'].create({ 'name': '测试规则', 'company_id': self.env.company.id # 显式设置当前公司 }) ``` 2. **时区测试**: ```python # 测试带时区的日期比较 with self.env.cr.savepoint(): self.env.user.tz = 'Asia/Shanghai' # 创建跨时区订单测试 ``` 3. **权限测试**: ```python # 验证安全组控制 with self.assertRaises(AccessError): self.env['multi.level.commission'].with_user(test_user).create({...}) ``` 这些修改确保您的模块符合 Odoo 16 的 ORM 规范、视图系统和安全模型,同时保持原有业务逻辑不变[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值