news 2026/8/1 18:34:56

Odoo 18 二次开发实战:从零构建一个完整业务模块

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Odoo 18 二次开发实战:从零构建一个完整业务模块

1. Odoo 18二次开发入门:为什么选择模块化开发?

第一次接触Odoo二次开发时,很多人会问:为什么不直接修改源码?这个问题我也纠结过。直到有次升级系统,发现自己改过的核心代码全被覆盖,才真正理解模块化开发的价值。Odoo的模块化设计就像乐高积木,每个业务功能都是独立的模块,既能灵活组合又互不干扰。

最近给一家电商客户做库存预警系统时,我们完全通过新建模块实现功能。当客户临时需要增加供应商管理功能时,只需再开发一个供应商模块,两个模块通过依赖关系完美配合。这种开发方式让系统维护成本降低了60%,升级时再也不用提心吊胆。

2. 从零搭建库存预警模块

2.1 创建模块脚手架

先确保你已经配置好Odoo 18开发环境。打开终端,进入自定义模块目录(通常放在addons文件夹),执行这个神奇的命令:

python ../odoo-bin scaffold stock_alert my_addons

这个命令会在my_addons目录下生成stock_alert模块的初始结构。我习惯用业务功能命名模块,比如这里的stock_alert就明确表示了库存预警功能。

生成的文件结构中,最需要关注的是:

  • __manifest__.py:模块的身份证
  • models/:数据模型的家
  • views/:用户界面的工作室
  • security/:权限控制中心

2.2 配置manifest文件

打开__manifest__.py,这是模块的配置中心。最近做项目时发现几个容易踩的坑:

{ 'name': '库存预警系统', # 用中文名方便终端用户识别 'version': '1.0', 'summary': '实时监控库存水位,自动触发补货预警', 'description': """ 本模块提供: - 多级库存阈值设置 - 预警规则自定义 - 自动通知采购负责人 - 可视化预警仪表盘 """, # 详细描述会显示在应用商店 'author': '你的名字', 'website': 'https://yourdomain.com', 'category': 'Inventory', # 必须使用Odoo标准分类 'depends': ['stock'], # 依赖的模块,库存功能基于stock模块 'data': [ 'security/ir.model.access.csv', 'views/stock_warehouse_views.xml', ], 'demo': [], # 演示数据 'installable': True, 'application': True, 'license': 'LGPL-3', }

特别注意depends配置,有次我忘记添加mail模块依赖,导致消息通知功能报错,排查了半天才发现是这个原因。

3. 构建库存预警数据模型

3.1 设计预警规则模型

models/stock_alert.py中定义核心模型:

from odoo import models, fields, api class StockAlertRule(models.Model): _name = 'stock.alert.rule' _description = '库存预警规则' name = fields.Char('规则名称', required=True) active = fields.Boolean('启用', default=True) warehouse_id = fields.Many2one( 'stock.warehouse', '仓库', help="应用该规则的仓库" ) product_category_id = fields.Many2one( 'product.category', '产品分类', help="应用该规则的产品分类" ) threshold_type = fields.Selection([ ('quantity', '数量'), ('value', '金额'), ('day', '天数')], '阈值类型', default='quantity' ) warning_threshold = fields.Float('预警阈值') critical_threshold = fields.Float('严重阈值') action_ids = fields.One2many( 'stock.alert.action', 'rule_id', '触发动作' ) _sql_constraints = [ ('threshold_check', 'CHECK(warning_threshold < critical_threshold)', '预警阈值必须小于严重阈值') ]

这个模型设计有几个实用技巧:

  1. 使用active字段实现软删除
  2. 通过help参数添加字段说明
  3. 使用SQL约束保证业务逻辑正确性
  4. 采用标准的_name命名规范(模块名.模型名)

3.2 添加关联模型

继续在同一个文件中添加动作模型:

class StockAlertAction(models.Model): _name = 'stock.alert.action' _description = '预警触发动作' rule_id = fields.Many2one('stock.alert.rule', '所属规则') action_type = fields.Selection([ ('email', '发送邮件'), ('task', '创建任务'), ('order', '生成采购订单')], '动作类型', required=True ) recipient_ids = fields.Many2many( 'res.users', string='接收人' ) template_id = fields.Many2one( 'mail.template', '邮件模板', domain="[('model_id.model', '=', 'stock.alert.rule')]" ) @api.onchange('action_type') def _onchange_action_type(self): if self.action_type == 'email': return {'domain': {'template_id': [ ('model_id.model', '=', 'stock.alert.rule') ]}}

这里展示了Odoo强大的动态域功能:当动作类型选择"email"时,模板选择框只显示适用于库存预警规则的邮件模板。

4. 实现业务逻辑

4.1 添加定时检查方法

StockAlertRule类中添加核心业务逻辑:

def _check_stock_levels(self): """ 核心方法:检查库存水平并触发预警 """ ProductProduct = self.env['product.product'] StockQuant = self.env['stock.quant'] for rule in self: domain = [] if rule.warehouse_id: domain.append(('location_id.warehouse_id', '=', rule.warehouse_id.id)) if rule.product_category_id: domain.append(('product_id.categ_id', '=', rule.product_category_id.id)) quants = StockQuant.search(domain) for quant in quants: if rule.threshold_type == 'quantity': value = quant.quantity elif rule.threshold_type == 'value': value = quant.inventory_value else: # days value = (fields.Date.today() - quant.in_date.date()).days if value <= rule.critical_threshold: self._trigger_actions(quant, 'critical') elif value <= rule.warning_threshold: self._trigger_actions(quant, 'warning') def _trigger_actions(self, quant, level): """ 触发配置的动作 """ for action in self.action_ids: if action.action_type == 'email': self._send_alert_email(action, quant, level) elif action.action_type == 'task': self._create_alert_task(action, quant, level) elif action.action_type == 'order': self._generate_purchase_order(action, quant, level)

这段代码实现了:

  1. 根据规则条件构建查询域
  2. 获取库存数据并计算比较值
  3. 根据阈值触发不同级别的预警
  4. 执行配置的各类动作

4.2 实现邮件通知功能

继续添加邮件发送方法:

def _send_alert_email(self, action, quant, level): """ 发送预警邮件 """ if not action.recipient_ids or not action.template_id: return template = action.template_id.with_context( default_model='stock.alert.rule', default_res_id=self.id, quant=quant, level=level, rule=self ) for recipient in action.recipient_ids: template.send_mail(recipient.id, force_send=True)

这里使用了Odoo的邮件模板系统,通过上下文传递动态数据。建议提前在后台配置好邮件模板,包含类似这样的内容:

主题:库存预警 - ${level == 'critical' and '严重' or '警告'}级别 内容: 产品 ${quant.product_id.name} 在 ${quant.location_id.complete_name} 的库存${rule.threshold_type}已触发${level == 'critical' and '严重' or '警告'}预警! 当前值:${value} 阈值:${level == 'critical' and rule.critical_threshold or rule.warning_threshold}

5. 设计用户界面

5.1 表单视图设计

views/stock_warehouse_views.xml中添加:

<record id="view_stock_alert_rule_form" model="ir.ui.view"> <field name="name">stock.alert.rule.form</field> <field name="model">stock.alert.rule</field> <field name="arch" type="xml"> <form> <header> <button name="_check_stock_levels" string="立即检查" type="object" class="oe_highlight"/> <field name="active" widget="boolean_button"/> </header> <sheet> <group> <group> <field name="name"/> <field name="warehouse_id"/> <field name="product_category_id"/> </group> <group> <field name="threshold_type"/> <field name="warning_threshold"/> <field name="critical_threshold"/> </group> </group> <notebook> <page string="触发动作"> <field name="action_ids"> <tree editable="bottom"> <field name="action_type"/> <field name="recipient_ids" widget="many2many_tags"/> <field name="template_id"/> </tree> </field> </page> <page string="高级设置"> <!-- 可以添加更多高级选项 --> </page> </notebook> </sheet> </form> </field> </record>

这个表单视图包含了:

  1. 顶部按钮:手动触发库存检查
  2. 基本信息区域:规则名称、适用范围
  3. 阈值设置区域:预警参数配置
  4. 标签页:动作配置和高级设置

5.2 列表视图设计

继续添加列表视图:

<record id="view_stock_alert_rule_tree" model="ir.ui.view"> <field name="name">stock.alert.rule.tree</field> <field name="model">stock.alert.rule</field> <field name="arch" type="xml"> <tree> <field name="name"/> <field name="warehouse_id"/> <field name="product_category_id"/> <field name="threshold_type"/> <field name="warning_threshold"/> <field name="critical_threshold"/> <field name="active"/> </tree> </field> </record>

5.3 添加菜单和动作

最后配置菜单入口:

<!-- 动作定义 --> <record id="action_stock_alert_rule" model="ir.actions.act_window"> <field name="name">库存预警规则</field> <field name="res_model">stock.alert.rule</field> <field name="view_mode">tree,form</field> </record> <!-- 菜单定义 --> <menuitem id="menu_stock_alert_root" name="库存预警" parent="stock.menu_stock_root"/> <menuitem id="menu_stock_alert_rules" name="预警规则" parent="menu_stock_alert_root" action="action_stock_alert_rule"/>

这里将新模块的菜单挂载到了库存管理的根菜单下,保持了系统的整体性。

6. 配置权限和安全规则

6.1 定义访问权限

security/ir.model.access.csv中添加:

id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_stock_alert_rule,stock.alert.rule,model_stock_alert_rule,base.group_user,1,1,1,1 access_stock_alert_action,stock.alert.action,model_stock_alert_action,base.group_user,1,1,1,1

这个配置给普通用户(base.group_user)赋予了完整的CRUD权限。如果需要对不同角色设置不同权限,可以创建更多记录。

6.2 添加记录规则

有时候需要更细粒度的权限控制,可以在security/stock_alert_security.xml中添加记录规则:

<record id="stock_alert_rule_user_rule" model="ir.rule"> <field name="name">库存预警规则用户权限</field> <field name="model_id" ref="model_stock_alert_rule"/> <field name="domain_force">['|', ('warehouse_id', '=', False), ('warehouse_id.manager_id', '=', user.id)]</field> <field name="groups" eval="[(4, ref('stock.group_stock_user'))]"/> </record>

这条规则限制普通库存用户只能看到自己管理的仓库的预警规则。

7. 测试与部署

7.1 开发环境测试

安装模块前,建议先运行Odoo的测试模式:

python odoo-bin -i stock_alert --test-enable

这会自动执行模块中的测试用例。我们可以在tests/目录下添加测试类:

from odoo.tests.common import TransactionCase class TestStockAlert(TransactionCase): def setUp(self): super().setUp() self.Warehouse = self.env['stock.warehouse'] self.Product = self.env['product.product'] self.AlertRule = self.env['stock.alert.rule'] self.warehouse = self.Warehouse.create({ 'name': '测试仓库', 'code': 'TEST' }) self.product = self.Product.create({ 'name': '测试产品', 'type': 'product', 'categ_id': self.env.ref('product.product_category_all').id }) def test_alert_trigger(self): rule = self.AlertRule.create({ 'name': '测试规则', 'warehouse_id': self.warehouse.id, 'threshold_type': 'quantity', 'warning_threshold': 50, 'critical_threshold': 20 }) # 模拟库存变化 self.env['stock.quant'].create({ 'product_id': self.product.id, 'location_id': self.warehouse.lot_stock_id.id, 'quantity': 10 }) # 执行检查 rule._check_stock_levels() # 验证是否触发了严重预警 # 这里可以添加更多断言

7.2 生产环境部署

当测试通过后,在生产环境安装模块时建议:

  1. 先在测试环境完整验证
  2. 备份生产数据库
  3. 使用--stop-after-init参数先检查依赖:
    python odoo-bin -i stock_alert --stop-after-init
  4. 确认无误后再正式安装

8. 扩展与优化

8.1 添加仪表盘视图

为了让预警信息更直观,可以添加看板视图:

<record id="view_stock_alert_kanban" model="ir.ui.view"> <field name="name">stock.alert.kanban</field> <field name="model">stock.alert.rule</field> <field name="arch" type="xml"> <kanban default_group_by="warehouse_id"> <templates> <t t-name="kanban-box"> <div class="oe_kanban_card"> <div class="oe_kanban_content"> <strong><field name="name"/></strong> <div>仓库: <field name="warehouse_id"/></div> <div>产品分类: <field name="product_category_id"/></div> <div class="progress"> <div class="progress-bar" role="progressbar" t-att-style="'width: ' + (100 * (warning_threshold - critical_threshold) / warning_threshold) + '%'"> </div> </div> </div> </div> </t> </templates> </kanban> </field> </record>

8.2 实现自动定时检查

为了让系统自动运行库存检查,可以添加定时任务:

from odoo import api, models class IrCron(models.Model): _inherit = 'ir.cron' @api.model def _setup_stock_alert_cron(self): """ 创建或更新定时任务 """ cron = self.env.ref('stock_alert.cron_stock_alert', raise_if_not_found=False) if not cron: cron = self.env['ir.cron'].create({ 'name': '库存预警检查', 'model_id': self.env.ref('stock_alert.model_stock_alert_rule').id, 'state': 'code', 'code': 'model._check_stock_levels()', 'interval_number': 1, 'interval_type': 'hours', 'numbercall': -1, 'doall': False, 'active': True, }) return cron

然后在__manifest__.py的data列表中添加:

'data': [ 'security/ir.model.access.csv', 'views/stock_warehouse_views.xml', 'data/ir_cron.xml', ],

8.3 性能优化建议

当产品数量很多时,库存检查可能会比较耗时。可以考虑以下优化:

  1. 分批处理:将检查任务分成多个小任务
  2. 添加索引:在频繁查询的字段上添加数据库索引
  3. 缓存结果:对不常变动的数据使用缓存
  4. 异步执行:将耗时操作放到后台任务队列
def _check_stock_levels_batch(self, batch_size=100): """ 分批检查库存 """ for i in range(0, len(self), batch_size): batch = self[i:i+batch_size] batch._check_stock_levels() self.env.cr.commit() # 定期提交事务
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/14 15:00:20

灵毓秀-牧神-造相Z-Turbo与SpringBoot集成:打造智能文生图API服务

灵毓秀-牧神-造相Z-Turbo与SpringBoot集成&#xff1a;打造智能文生图API服务 本文介绍了如何将灵毓秀-牧神-造相Z-Turbo文生图模型集成到SpringBoot框架中&#xff0c;构建高效、易用的RESTful API服务&#xff0c;让开发者能够快速为应用添加智能图像生成能力。 1. 为什么需要…

作者头像 李华
网站建设 2026/7/14 15:00:36

机顶盒ADB调试功能一键开启合集|全型号兼容支持TBx1-2e等主流设备

温馨提示&#xff1a;文末有联系方式 一、机顶盒ADB调试功能全面整合上线 本套工具集已正式完成升级整合&#xff0c;支持多品牌、多型号机顶盒一键启用ADB调试模式&#xff0c;助力开发者与高级用户高效进行系统调试、应用安装及深度定制。 二、全新支持TBx1-2e专用工具&…

作者头像 李华
网站建设 2026/7/14 15:00:24

BMS中NTC温敏电阻的选型指南与代码实践

1. NTC温敏电阻在BMS中的核心作用 电池管理系统&#xff08;BMS&#xff09;就像电动汽车的"健康管家"&#xff0c;而NTC温敏电阻就是它最灵敏的"温度触角"。我在设计锂电池保护系统时&#xff0c;曾因为选错NTC型号导致整个模组温度监测失灵&#xff0c;最…

作者头像 李华
网站建设 2026/7/14 15:00:24

5个革新步骤:ALVR开源方案实现无线VR自由的实战指南

5个革新步骤&#xff1a;ALVR开源方案实现无线VR自由的实战指南 【免费下载链接】ALVR Stream VR games from your PC to your headset via Wi-Fi 项目地址: https://gitcode.com/gh_mirrors/alvr/ALVR 在VR体验中&#xff0c;线缆如同无形的枷锁&#xff0c;限制着玩家…

作者头像 李华
网站建设 2026/7/14 15:00:37

2026年写作小白救星!千笔AI,深得人心的AI论文工具

你是否曾为论文选题发愁&#xff0c;反复修改却仍不满意&#xff1f;是否在查重和格式上耗费大量时间&#xff0c;却收效甚微&#xff1f;论文写作的每一步都充满挑战&#xff0c;尤其是对初次接触学术写作的本科生来说。面对海量文献、复杂结构和严格规范&#xff0c;很多人都…

作者头像 李华