第 13 章:与其他模块交互

在 上一章 中,我们使用继承修改了模块的行为。在我们的房地产场景中,我们希望更进一步,能够为客户生成发票。Odoo 提供了开票模块,因此直接从房地产模块创建发票会非常方便,也就是说,一旦房产被设为“已售出”,就会在开票应用中创建一张发票。

具体示例:会计分录

注解

目标:本节结束时:

  • 应创建一个新的 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()

在 此处 可以找到一个实际示例。

练习

添加创建发票的第一步。

  • 在 estate_account 模块的正确文件夹中创建 estate_property.py 文件。

  • 对 estate.property 模型使用 _inherit。

  • 重写 action_sold 方法(你可能用了其他名称),使其返回 super 调用。

提示:为确保其生效,可在重写的方法中添加 print 或调试器断点。

它生效了吗?如果没有,请检查所有 Python 文件是否都已正确导入。

如果重写生效,我们就可以继续创建发票了。遗憾的是,在 Odoo 中没有简单的方法能知道如何创建任意对象。大多数情况下,需要查看其模型以找到必需字段并提供合适的值。

学习的一个好方法是看看其他模块是如何实现你想要的功能的。例如,销售的基本流程之一就是从销售订单创建发票。这看起来是一个很好的起点,因为它所做的正是我们想做的事。花点时间阅读并理解 _create_invoices 方法。当你因为这个看似简单的任务却异常复杂而哭完之后,我们就可以继续教程了。

要创建发票,我们需要以下信息:

  • 一个 partner_id:客户

  • 一个 move_type:它有多个 可选值

  • 一个 journal_id:会计日记账

这足以创建一张空的发票。

练习

添加创建发票的第二步。

在 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()

练习

添加创建发票的第三步。

在创建 account.move 时添加两条发票行。每套售出的房产将按照以下条件开票:

  • 售价的 6%

  • 额外收取 100.00 的管理费

提示:参照上面的示例,在创建时添加 invoice_line_ids。每一行都需要 name、quantity 和 price_unit。

本章可能是目前最难的一章,但它最接近实际 Odoo 开发的样子。在 下一章 中,我们将介绍 Odoo 中使用的模板机制。