第 13 章:与其他模块交互¶
在 上一章 中,我们使用继承来修改模块的行为。在我们的房地产场景中,我们希望更进一步,能够为客户生成发票。Odoo 提供了一个账单模块,因此直接从我们的房地产模块创建发票会非常方便,即当房产状态设置为“已售出”时,账单模块中会生成一张发票。
具体示例:会计凭证¶
注解
目标:在本节结束时:
应创建一个新模块
estate_account
当房产售出时,应为买家开具发票

每次我们与其他模块交互时,都需要牢记模块化。如果我们打算将应用程序出售给房地产机构,有些可能需要开票功能,而另一些则可能不需要。
链接模块¶
针对此类用例的常见方法是创建一个“链接”模块。在我们的例子中,该模块将依赖于 estate
和 account
,并包含房地产属性的发票创建逻辑。这样,房地产和会计模块可以独立安装。当两者都安装时,链接模块提供新功能。
Exercise
创建一个链接模块。
创建 estate_account
模块,它依赖于 estate
和 account
模块。目前,它将是一个空壳。
提示:您已经在教程的 开头 做过这个了。过程非常相似。
当 estate_account
模块出现在列表中时,请继续安装它!您会注意到账单应用程序也会被安装。这是预期的行为,因为您的模块依赖于它。如果您卸载账单应用程序,您的模块也会被卸载。
发票创建¶
现在是时候生成发票了。我们希望为 estate.property
模型添加功能,即当我们出售房产时,添加一些额外的逻辑。这听起来熟悉吗?如果不熟悉,建议回到 上一章 ,您可能错过了一些内容 ;-)
第一步,我们需要扩展按下房产上的 “已售出”按钮 时调用的操作。为此,我们需要在 estate_account
模块中为 estate.property
模型创建 模型继承 。目前,重写后的操作将简单地返回 super
调用。也许一个示例会让事情更清楚::
from odoo import models
class InheritedModel(models.Model):
_inherit = "inherited.model"
def inherited_action(self):
return super().inherited_action()
一个实际示例可以在这里找到: 这里 。
Exercise
添加发票创建的第一步。
在
estate_account
模块的正确文件夹中创建一个estate_property.py
文件。通过
_inherit
继承estate.property
模型。重写
action_sold
方法(您可能使用了不同的名称),并返回super
调用。
提示:为确保其正常工作,可以在重写的方法中添加 print
或调试断点。
它是否正常工作?如果不是,也许检查一下所有 Python 文件是否正确导入。
如果重写生效,我们可以继续创建发票。不幸的是,Odoo 中没有简单的方法知道如何创建任何给定的对象。大多数情况下,有必要查看其模型以找到所需的字段并提供适当的值。
学习的一个好方法是看看其他模块是如何实现您想做的事情的。例如,销售的基本流程之一是从销售订单创建发票。这看起来是一个很好的起点,因为它正是我们要做的事情。花点时间阅读并理解 _create_invoices 方法。当您因为这个看似简单的任务实际上如此复杂而感到崩溃时,我们可以继续教程。
要创建发票,我们需要以下信息:
一个
partner_id
:客户一个
move_type
:它有多个 可能的值一个
journal_id
:会计账簿
这些信息足以创建一张空发票。
Exercise
添加发票创建的第二步。
在 action_sold
方法的重写中创建一个空的 account.move
:
partner_id
从当前的estate.property
中获取。move_type
应对应于“客户发票”。
提示:
要创建对象,请使用
self.env[model_name].create(values)
,其中values
是一个字典(dict
)。create
方法不接受记录集作为字段值。
当房产状态设置为“已售出”时,现在应该在“账单 / 客户 / 发票”中生成一张新的客户发票。
显然,到目前为止我们还没有任何发票行。要创建发票行,我们需要以下信息:
name
:行的描述quantity
:数量price_unit
:单价
此外,发票行需要与发票相关联。将行链接到发票的最简单且最有效的方法是在创建发票时包含所有行。为此,在创建 account.move
时会包含 invoice_line_ids
字段,该字段是一个 One2many
。 One2many 和 Many2many 使用特殊的“命令”,这些命令通过 Command
命名空间变得更加人性化。该命名空间表示对一组记录执行的三元组命令。最初,三元组是执行这些命令的唯一选项,但现在使用命名空间已成为标准。其格式是将它们放在一个列表中,按顺序执行。以下是一个简单的示例,展示如何在创建 test_model
时包含一个 One2many 字段 line_ids
::
from odoo import Command
def inherited_action(self):
self.env["test_model"].create(
{
"name": "Test",
"line_ids": [
Command.create({
"field_1": "value_1",
"field_2": "value_2",
})
],
}
)
return super().inherited_action()
Exercise
添加发票创建的第三步。
在创建 account.move
时添加两条发票行。每个已售出的属性将根据以下条件开具发票:
售价的 6%
额外收取 100.00 的行政费用
提示:按照上面的示例,在创建时添加 invoice_line_ids
。对于每一行,我们需要一个 name
、quantity
和 price_unit
。
本章可能是迄今为止涵盖的最难内容之一,但它最接近实际 Odoo 开发的工作方式。在 下一章 中,我们将介绍 Odoo 中使用的模板机制。