odoo 開發入門教程系列-模組互動

授客發表於2023-04-16

模組互動

在上一章中,我們使用繼承來修改模組的行為。在我們的房地產場景中,我們希望更進一步,能夠為客戶生成發票。Odoo提供了一個開發票模組,因此直接從我們的房地產模組建立發票是很簡單的,也就是說,一旦某個房產設定為“已售出”,就會在Invoicing應用程式中建立發票

一個具體示例: 記賬憑證(Account Move)

目標: 本節結束時:

  • 建立一個estate_account 模組

  • 建立房產時,為購買者開發票

預期效果動畫地址:https://www.odoo.com/documentation/14.0/zh_CN/_images/create_inv.gif

每當我們與另一個模組互動時,我們都需要記住模組化。如果我們打算將我們的應用程式賣給房地產代理,有些人可能想要發票功能,但有些人可能不想要。

此類使用案例的常見方法是建立“連結”模組。在我們的案例中,該模組依賴estateaccount,包括房產的發票建立邏輯。採用這種方式,estateaccount模組可以獨立安裝。當兩者都安裝後,連結模組將提供新功能。

練習--建立連結模組

建立依賴estateaccountestate_account 空殼模組,建立以後安裝該模組。你可能會注意到,Invoicing 應用也被安裝了。這是意料之中的,因為你的模組依賴它。 如果你解除安裝Invoicing模組,你的模組也會被解除安裝。

說明:__init__.py為空

重啟服務,安裝模組

建立發票

是時候生成發票了。我們希望為estate.property模型新增功能,即我們希望在出售房產時新增一些額外的邏輯。

第一步,我們需要擴點選“Sold”按鈕時呼叫的操作。為此,我們需要在estate_account模組中為建立一個模型,繼承estate.property模型。現在,重寫操作,僅返回super呼叫,拿個例子來說可能更清楚:

from odoo import models

class InheritedModel(models.Model):
    _inherit = "inherited.model"

    def inherited_action(self):
        return super().inherited_action()

可以在這找個具體的示例

https://github.com/odoo/odoo/blob/f1f48cdaab3dd7847e8546ad9887f24a9e2ed4c1/addons/account/models/account_move.py

class AccountMove(models.Model):
    _name = "account.move"
    _inherit = ['portal.mixin', 'mail.thread', 'mail.activity.mixin', 'sequence.mixin']
    _description = "Journal Entry"
    #... 略
    def action_invoice_paid(self):
        ''' Hook to be overrided called when the invoice moves to the paid state. '''
        pass
class AccountMove(models.Model):
    _inherit = 'account.move'

    def action_invoice_paid(self):
        """ When an invoice linked to a sales order selling registrations is
        paid confirm attendees. Attendees should indeed not be confirmed before
        full payment. """
        res = super(AccountMove, self).action_invoice_paid()
        self.mapped('line_ids.sale_line_ids')._update_registrations(confirm=True, mark_as_paid=True)
        return res
練習--新增建立發票的第一步
  • estate_account模組中的正確目錄建立 estate_property.py 檔案
  • _inherit estate.property 模組
  • 重寫 action_sold 方法(你可能已經將該方法命名為不同的名稱了) 以返回 super 呼叫

提示: 為了確保它正常工作,新增一個print 或者除錯斷點到重寫的方法中。

新增以下檔案:

odoo14\custom\estate_account\models\__init__.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-

from . import estate_property

odoo14\custom\estate_account\models\estate_property.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-

from odoo import models


class InheritedEstateProperty(models.Model):
    _inherit = "estate.property"

    def set_property_sold(self):
        return super().set_property_sold()

修改odoo14\custom\estate_account\__init__.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-

from . import models

它有效嗎?如果沒有,請檢查是否正確匯入了所有Python檔案。

如果重寫生效,我們可以繼續建立發票。不幸的是,沒有一種簡單的方法可以知道如何在Odoo中建立任何給定的物件。大多數時候,有必要檢視其模型,以找到所需的欄位並提供適當的值。

學習的一個好方法是看看其他模組是如何完成你想做的事情的。例如,銷售的一個基本流程是從銷售訂單建立發票。這看起來是一個很好的起點,因為它正是我們想要做的。花一些時間思考和理解建立發票方法。

為了建立了發票,我們需要以下資訊:

  • 一個 partner_id: 顧客
  • 一個move_type: 它有幾個可能的值
  • journal_id: the accounting journal

這足夠建立一個張空發票。

練習--新增發票建立第二步

重寫action_sold,並建立一個空的 account.move :

  • 從當前的estate.property獲取 partner_id
  • move_type 應該和Customer Invoice對應

提示:

  • 使用 self.env[model_name].create(values)建立一個物件, 其中values 為一個字典。
  • create 方法不接受結果集作為欄位值。

修改odoo14\custom\estate_account\models\estate_property.py

    def set_property_sold(self):
        self.env['account.move'].create({})
        return super().set_property_sold()

當房產設定為“已售出”時,你現在應該在Invoiceing/customer/Invoices中建立一個新的客戶發票。

顯然,到目前為止,我們沒有任何發票行。要建立發票行,我們需要以下資訊:

  • name:發票行的描述
  • quantity
  • price_unit

此外,發票行需要連結到發票。將發票行連結到發票的最簡單、最有效的方法是在建立發票時包含所有行。為此在account.move建立中包含invoice_line_ids欄位,這是一個One2many欄位。One2manyMany2many使用通用ORM方法中描述的特殊“commands”。這種格式是一個按順序執行的三元組列表,其中每個三元組都是要對結果集執行的命令。下面是一個在建立test.model時包含一個One2many欄位line_ids的簡單示例:

def inherited_action(self):
    self.env["test.model"].create(
        {
            "name": "Test",
            "line_ids": [
                (
                    0,
                    0,
                    {
                        "field_1": "value_1",
                        "field_2": "value_2",
                    },
                )
            ],
        }
    )
    return super().inherited_action()
練習--新增建立發票的第三步

建立account.move時新增兩個發票行。每個售出的房產都將按照以下條件開具發票:

  • 售價的6%
  • 額外100.00行政費

提示:按照上面的示例在建立時新增invoice_line_ids。對於每個發票行,我們需要一個 name, quantityprice_unit

#!/usr/bin/env python
# -*- coding:utf-8 -*-

from odoo import models
from odoo.exceptions import UserError

class InheritedEstateProperty(models.Model):
    _inherit = "estate.property"

    def set_property_sold(self):
        print('override set_property_sold')
        journal = self.env['account.move'].with_context(default_move_type='out_invoice')._get_default_journal()
        if not journal:
            raise UserError('Please define an accounting sales journal for the company')

        self.env['account.move'].create({
           'move_type': 'out_invoice',
           'partner_id': self.buyer_id,
           'journal_id': journal.id,  # company comes from the journal
            'invoice_line_ids': [{
                'name': 'Avaliable house 01',
                'quantity': 1,
                'price_unit': 0.6 * self.best_price
            },{
                'name': ' Administrative fees',
                'quantity': 1,
                'price_unit': 100
            }]
        })
        return super().set_property_sold()

重啟服務,驗證效果

相關文章