混合類和有用的類?

Odoo 實現了一些有用的類和 mixin,使您可以輕松地在對象上添加經常使用的行為。本指南將詳細介紹其中大部分,包括示例和用例。

消息功能?

消息集成?

基本消息系統?

將消息功能集成到您的模型非常容易。只需繼承 mail.thread 模型并將消息字段(及其適當的小部件)添加到您的表單視圖中,即可立即運行。

Example

讓我們創建一個簡單的模型來代表商務旅行。由于組織這種旅行通常涉及到很多人和很多討論,因此讓我們在模型上添加消息交換的支持。

class BusinessTrip(models.Model):
    _name = 'business.trip'
    _inherit = ['mail.thread']
    _description = 'Business Trip'

    name = fields.Char()
    partner_id = fields.Many2one('res.partner', 'Responsible')
    guest_ids = fields.Many2many('res.partner', 'Participants')

在表單視圖中:

<record id="businness_trip_form" model="ir.ui.view">
    <field name="name">business.trip.form</field>
    <field name="model">business.trip</field>
    <field name="arch" type="xml">
        <form string="Business Trip">
            <!-- Your usual form view goes here
            ...
            Then comes chatter integration -->
            <div class="oe_chatter">
                <field name="message_follower_ids" widget="mail_followers"/>
                <field name="message_ids" widget="mail_thread"/>
            </div>
        </form>
    </field>
</record>

一旦您在您的模型上添加了聊天支持,用戶可以輕松地在您模型的任何記錄上添加消息或內部備注;每個消息都會發送通知(對于消息,發送給所有關注者,對于內部備注,發送給員工( base.group_user )用戶)。如果您的郵件網關和通配符地址已正確配置,則這些通知將通過電子郵件發送,并可直接從您的郵件客戶端回復;自動路由系統將路由答案到正確的線程。

服務器端,有一些輔助函數可幫助您輕松發送消息并管理記錄的關注者:

發布消息

message_post(self, body='', subject=None, message_type='notification', subtype=None, parent_id=False, attachments=None, **kwargs)?

在現有的線程中發布新消息,返回新的郵件消息 ID。

參數
  • body (str) – 消息正文,通常是將被清理的原始HTML

  • message_type (str) – 請參閱 mail_message.message_type 字段

  • parent_id (int) – 在私人討論中,通過將父級合作伙伴添加到消息中來處理對先前消息的回復

  • attachments (list(tuple(str,str))) – 以 (name,content) 形式表示的附件元組列表,其中 content 未經過 base64 編碼

  • **kwargs – 額外的關鍵字參數將用作新郵件消息記錄的默認列值

返回

新創建的郵件消息的ID

返回類型

int

message_post_with_view(views_or_xmlid, **kwargs):

使用 view_id 渲染 ir.qweb 引擎來發送郵件/發布消息的輔助方法。這個方法是獨立的,因為在模板和 composer 中沒有任何處理批量視圖的方法。當模板處理 ir ui 視圖時,這個方法可能會消失。

參數

record (str or ir.ui.view) – 應發送的視圖的外部ID或記錄

message_post_with_template(template_id, **kwargs)?

使用模板發送郵件的輔助方法

參數
  • template_id – 用于創建消息正文的模板的ID

  • **kwargs – 創建一個繼承自 mail.message 的 mail.compose.message 向導的參數

接收消息

當郵件網關處理新郵件時,會調用這些方法。這些郵件可以是新的線程(如果它們通過一個 別名 到達)或者只是現有線程的回復。重寫它們可以讓你根據郵件本身的一些值(例如更新日期或電子郵件地址,將抄送地址添加為關注者等)在線程記錄上設置值。

message_new(msg_dict, custom_values=None)?

當給定線程模型收到新消息且該消息不屬于現有線程時,由 message_process 調用。

默認行為是創建相應模型的新記錄(基于從消息中提取的一些基本信息)??梢酝ㄟ^覆蓋此方法來實現其他行為。

參數
  • msg_dict (dict) – 一個包含電子郵件詳細信息和附件的映射。有關詳細信息,請參見 message_processmail.message.parse 。

  • custom_values (dict) – 可選的字典類型參數,用于在創建新的線程記錄時傳遞給 create() 方法;請注意,這些值可能會覆蓋來自消息的任何其他值

返回類型

int

返回

新創建的線程對象的ID

message_update(msg_dict, update_vals=None)?

當現有線程收到新消息時,由 message_process 調用。默認行為是使用來自傳入電子郵件的 update_vals 更新記錄。

可以通過覆蓋此方法來實現其他行為。

參數
  • msg_dict (dict) – 一個包含電子郵件詳細信息和附件的映射;有關詳細信息,請參見 message_processmail.message.parse() 。

  • update_vals (dict) – 一個包含根據其ID更新記錄的值的字典;如果該字典為None或為空,則不執行寫操作。

返回

關注者管理

message_subscribe(partner_ids=None, channel_ids=None, subtype_ids=None, force=True)?

將合作伙伴添加到記錄的關注者中。

參數
  • partner_ids (list(int)) – 將訂閱該記錄的合作伙伴的ID

  • channel_ids (list(int)) – 將訂閱記錄的頻道的ID

  • subtype_ids (list(int)) – 訂閱頻道/合作伙伴的子類型ID(如果為“None”,則默認為默認子類型)

  • force – 如果為True,則在使用參數中給定的子類型創建新的關注者之前刪除現有的關注者

返回

成功/失敗

返回類型

bool

message_unsubscribe(partner_ids=None, channel_ids=None)?

從記錄的關注者中移除合作伙伴。

參數
  • partner_ids (list(int)) – 將訂閱該記錄的合作伙伴的ID

  • channel_ids (list(int)) – 將訂閱記錄的頻道的ID

返回

返回類型

bool

message_unsubscribe_users(user_ids=None)?

使用用戶的 message_subscribe 包裝器。

參數

user_ids (list(int)) – 將取消訂閱記錄的用戶的ID;如果為None,則取消訂閱當前用戶。

返回

返回類型

bool

記錄更改?

“mail” 模塊為字段添加了強大的跟蹤系統,允許您記錄記錄聊天中特定字段的更改。要將跟蹤添加到字段,請將跟蹤屬性設置為 True。

Example

讓我們跟蹤商務旅行的名稱和負責人的變化:

class BusinessTrip(models.Model):
    _name = 'business.trip'
    _inherit = ['mail.thread']
    _description = 'Business Trip'

    name = fields.Char(tracking=True)
    partner_id = fields.Many2one('res.partner', 'Responsible',
                                 tracking=True)
    guest_ids = fields.Many2many('res.partner', 'Participants')

從現在開始,每次更改行程的名稱或責任人都會在記錄上記錄一個注釋。即使名稱沒有更改,通知中也會顯示“名稱”字段,以提供有關通知的更多上下文。

子類型?

子類型可以更細粒度地控制消息。子類型作為通知的分類系統,允許文檔的訂閱者自定義他們希望接收的通知的子類型。

子類型是作為模塊中的數據創建的;該模型具有以下字段:

name (必填)- Char

子類型名稱,將顯示在通知自定義彈出窗口中

description - Char

將添加到此子類型發布的消息中的描述。如果為空,則將添加名稱。

internal - Boolean

具有內部子類型的消息僅對員工可見,也就是 base.group_user 組的成員可見。

parent_id - Many2one

自動訂閱的鏈接子類型;例如,項目子類型通過此鏈接與任務子類型相關聯。當有人訂閱項目時,他將訂閱此項目下所有使用父子類型找到的任務子類型。

relation_field - Char

例如,當鏈接項目和任務子類型時,關系字段是任務的 project_id 字段。

res_model - Char

適用于的模型子類型;如果為 False,則適用于所有模型

default - Boolean

訂閱時是否默認激活子類型

sequence - Integer

用于在通知自定義彈出窗口中排序子類型

hidden - Boolean

通知自定義彈出窗口中是否隱藏子類型

將子類型與字段跟蹤接口相結合,可以訂閱不同類型的通知,具體取決于用戶可能感興趣的內容。為此,您可以覆蓋 _track_subtype() 函數:

_track_subtype(init_values)?

根據已更新的值,給出由記錄更改觸發的子類型。

參數

init_values (dict) – 記錄的原始值;字典中僅包含修改過的字段

返回

一個子類型的完整外部 ID,如果沒有觸發子類型,則為 False

Example

讓我們在示例類上添加一個“state”字段,并在該字段更改值時觸發具有特定子類型的通知。

首先,讓我們定義我們的子類型:

<record id="mt_state_change" model="mail.message.subtype">
    <field name="name">Trip confirmed</field>
    <field name="res_model">business.trip</field>
    <field name="default" eval="True"/>
    <field name="description">Business Trip confirmed!</field>
</record>

然后,我們需要重寫 track_subtype() 函數。該函數由跟蹤系統調用,以了解應根據當前應用的更改使用哪個子類型。在我們的情況下,當 state 字段從 draft 更改為 confirmed 時,我們希望使用我們閃亮的新子類型:

class BusinessTrip(models.Model):
    _name = 'business.trip'
    _inherit = ['mail.thread']
    _description = 'Business Trip'

    name = fields.Char(tracking=True)
    partner_id = fields.Many2one('res.partner', 'Responsible',
                                 tracking=True)
    guest_ids = fields.Many2many('res.partner', 'Participants')
    state = fields.Selection([('draft', 'New'), ('confirmed', 'Confirmed')],
                             tracking=True)

    def _track_subtype(self, init_values):
        # init_values contains the modified fields' values before the changes
        #
        # the applied values can be accessed on the record as they are already
        # in cache
        self.ensure_one()
        if 'state' in init_values and self.state == 'confirmed':
            return self.env.ref('my_module.mt_state_change')
        return super(BusinessTrip, self)._track_subtype(init_values)

自定義通知?

當向關注者發送通知時,在模板中添加按鈕以允許直接從電子郵件中進行快速操作非常有用。 即使是一個簡單的按鈕直接鏈接到記錄的表單視圖也很有用;但是在大多數情況下,您不希望向門戶用戶顯示這些按鈕。

通知系統可以通過以下方式自定義通知模板:

  • 顯示 訪問按鈕 :這些按鈕在通知電子郵件的頂部可見,允許收件人直接訪問記錄的表單視圖

  • 顯示 關注按鈕 :這些按鈕允許收件人直接從記錄中快速訂閱

  • 顯示 取消關注按鈕 :這些按鈕允許收件人直接快速取消對記錄的訂閱

  • 顯示 自定義操作按鈕 :這些按鈕是對特定路由的調用,允許您直接從電子郵件中執行一些有用的操作(例如將潛在客戶轉換為機會,為費用經理驗證費用報銷單等)。

這些按鈕設置可以應用于不同的組,您可以通過覆蓋函數 _notify_get_groups 來自定義這些組。

_notify_get_groups(message, groups)?

根據已更新的值,給出由記錄更改觸發的子類型。

參數
  • message (record) – 正在發送的 mail.message 記錄

  • groups (list(tuple)) – 列表,元素為元組(group_name, group_func, group_data),其中: group_name是一個標識符,僅用于覆蓋和操作組。默認組為“user”(與員工用戶相關的收件人)、“portal”(與門戶用戶相關的收件人)和“customer”(未與任何用戶相關的收件人)。覆蓋使用示例是添加一個與res.groups相關聯的組,例如Hr Officers,以為它們設置特定的操作按鈕。group_func是一個函數指針,以合作伙伴記錄為參數。此方法將應用于收件人,以了解他們是否屬于給定的組。僅保留第一個匹配組。評估順序是列表順序。group_data是一個包含通知電子郵件參數的字典,具有以下可能的鍵值對: - has_button_access:是否在電子郵件中顯示Access <Document>。對于新組,默認為True,對于門戶/客戶端,默認為False。 - button_access:按鈕的url和標題的字典 - has_button_follow:是否在電子郵件中顯示Follow(如果收件人當前沒有關注該線程)。對于新組,默認為True,對于門戶/客戶端,默認為False。 - button_follow:按鈕的url和標題的字典 - has_button_unfollow:是否在電子郵件中顯示Unfollow(如果收件人當前正在關注該線程)。對于新組,默認為True,對于門戶/客戶端,默認為False。 - button_unfollow:按鈕的url和標題的字典 - actions:在通知電子郵件中顯示的操作按鈕列表。每個操作都是一個包含按鈕的url和標題的字典。

返回

一個子類型的完整外部 ID,如果沒有觸發子類型,則為 False

操作列表中的URL可以通過調用 _notify_get_action_link() 函數自動生成:

生成當前記錄(或如果設置了kwargs“model”和“res_id”,則在特定記錄上)的給定類型的鏈接。

參數

link_type (str) – 要生成的鏈接類型;可以是以下任何值: view 鏈接到記錄的表單視圖 assign 將登錄用戶分配給記錄的 user_id 字段(如果存在) follow 自解釋 unfollow 自解釋 method 調用記錄上的方法;方法的名稱應作為 kwarg method 提供 new 打開一個新記錄的空表單視圖;您可以通過在 kwarg action_id 中提供其 id(數據庫 id 或完全解析的外部 id)來指定特定操作

返回

所選記錄類型的鏈接

返回類型

str

Example

讓我們向出差狀態更改通知添加自定義按鈕;此按鈕將把狀態重置為草稿,并且僅對(虛構的)Travel Manager組( business.group_trip_manager )的成員可見。

class BusinessTrip(models.Model):
    _name = 'business.trip'
    _inherit = ['mail.thread', 'mail.alias.mixin']
    _description = 'Business Trip'

    # Pevious code goes here

    def action_cancel(self):
        self.write({'state': 'draft'})

    def _notify_get_groups(self, message, groups):
        """ Handle Trip Manager recipients that can cancel the trip at the last
        minute and kill all the fun. """
        groups = super(BusinessTrip, self)._notify_get_groups(message, groups)

        self.ensure_one()
        if self.state == 'confirmed':
            app_action = self._notify_get_action_link('method',
                                method='action_cancel')
            trip_actions = [{'url': app_action, 'title': _('Cancel')}]

        new_group = (
            'group_trip_manager',
            lambda partner: bool(partner.user_ids) and
            any(user.has_group('business.group_trip_manager')
            for user in partner.user_ids),
            {
                'actions': trip_actions,
            })

        return [new_group] + groups

請注意,我可以在此方法之外定義我的評估函數,并定義全局函數來代替lambda,但為了在這些有時會很無聊的文檔文件中更加簡潔和不冗長,我選擇前者而不是后者。

覆蓋默認值?

您可以通過多種方式自定義 mail.thread 模型的行為,包括但不限于以下方式:

_mail_post_access - Model 屬性

需要發布模型消息的必要訪問權限;默認情況下需要 write 訪問權限,也可以設置為 read

上下文鍵:

這些上下文鍵可用于在調用 create()write() (或任何其他可能有用的方法)期間,有些控制 mail.thread 功能,如自動訂閱或字段跟蹤。

  • mail_create_nosubscribe : 在創建或發送消息時,不訂閱當前用戶到記錄線程

  • mail_create_nolog : 在創建時,不記錄自動的’<Document>已創建’消息

  • mail_notrack : 在創建和寫入時,不執行值跟蹤創建消息

  • tracking_disable : 在創建和寫入時,不執行MailThread功能(自動訂閱,跟蹤,發布等)

  • mail_auto_delete : 自動刪除郵件通知;默認為True

  • mail_notify_force_send : 如果要發送的電子郵件通知少于50個,則直接發送而不使用隊列;默認為True

  • mail_notify_user_signature : 在電子郵件通知中添加當前用戶簽名;默認為True

郵件別名?

別名是可配置的電子郵件地址,它們與特定記錄鏈接(通常繼承“mail.alias.mixin”模型),當通過電子郵件聯系時將創建新記錄。它們是使您的系統從外部可訪問的簡單方法,允許用戶或客戶快速在您的數據庫中創建記錄,而無需直接連接到Odoo。

別名 vs. 郵件入口網關?

有些人使用傳入郵件網關來實現同樣的目的。但是,您仍然需要一個正確配置的郵件網關來使用別名,但是一個單獨的萬能域名就足夠了,因為所有路由都將在Odoo內部完成。別名比郵件網關具有幾個優點:

  • 更容易配置
    • 一個入站網關可以被多個別名使用;這樣可以避免在您的域名上配置多個電子郵件(所有配置都在Odoo內部完成)。

    • 配置別名無需系統訪問權限

  • 更連貫
    • 可在相關記錄上配置,而不是在設置子菜單中

  • 更容易在服務器端進行覆蓋
    • Mixin模型從一開始就被構建為可擴展的,使您可以比郵件網關更輕松地從傳入的電子郵件中提取有用的數據。

別名支持集成?

通常情況下,別名是在父模型上配置的,當通過電子郵件聯系時,將創建特定的記錄。例如,項目具有用于創建任務或問題的別名,銷售團隊具有用于生成潛在客戶的別名。

注解

別名創建的模型 必須 繼承 mail_thread 模型。

通過繼承 mail.alias.mixin 來添加別名支持;這個 mixin 將為每個父類記錄生成一個新的 mail.alias 記錄(例如,每個 project.project 記錄在創建時都會初始化其 mail.alias 記錄)。

注解

別名也可以手動創建,并由一個簡單的 Many2one 字段支持。本指南假定您希望更完整地集成,自動創建別名,記錄特定的默認值等。

mail.thread 繼承不同, mail.alias.mixin 需要 一些特定的重寫才能正常工作。這些重寫將指定創建的別名的值,例如它必須創建的記錄類型,以及根據父對象可能具有的一些默認值。

_get_alias_model_name(vals)?

返回別名的模型名稱。未回復現有記錄的傳入電子郵件將導致創建此別名模型的新記錄。該值可能取決于“vals”,即在創建此模型的記錄時傳遞給“create”的值字典。

參數

dict (vals) – 新創建的記錄將持有別名的值

返回

模型名稱

返回類型

str

_get_alias_values()?

返回值用于創建別名,或在創建后對別名進行寫入。雖然不是完全必需的,但通常需要通過在別名的“alias_defaults”字段中設置默認值字典來確保新創建的記錄將鏈接到別名的父級(即在正確的項目中創建任務)。

返回

將寫入新別名的值的字典

返回類型

dict

_get_alias_values() 覆蓋方法非常有趣,因為它可以輕松修改別名的行為??梢栽趧e名上設置以下字段,這些字段特別有趣:

alias_name - Char

電子郵件別名的名稱,例如,如果您想捕獲 <jobs@example.odoo.com> 的電子郵件,則為“jobs”

alias_user_id - Many2one ( res.users )

在收到此別名的電子郵件時創建記錄的所有者;如果未設置此字段,則系統將嘗試根據發件人(From)地址找到正確的所有者,如果找不到該地址的系統用戶,則將使用管理員帳戶。

alias_defaults - Text

Python 字典,用于在為此別名創建新記錄時提供默認值

alias_force_thread_id - Integer

可選的線程(記錄)ID,所有傳入的消息都將附加到其中,即使它們沒有回復它;如果設置,這將完全禁用新記錄的創建

alias_contact - Selection

使用郵件網關在文檔上發布消息的策略

  • 所有人 : 所有人都可以發布

  • 合作伙伴 :僅限已認證的合作伙伴

  • followers : 僅限于相關文檔的關注者或者關注頻道的成員

請注意,別名使用 委托繼承 ,這意味著雖然別名存儲在另一個表中,但您可以直接從父對象訪問所有這些字段。這使得您可以輕松地從記錄的表單視圖中配置別名。

Example

讓我們在出差類上添加別名,通過電子郵件即可即時創建費用。

class BusinessTrip(models.Model):
    _name = 'business.trip'
    _inherit = ['mail.thread', 'mail.alias.mixin']
    _description = 'Business Trip'

    name = fields.Char(tracking=True)
    partner_id = fields.Many2one('res.partner', 'Responsible',
                                 tracking=True)
    guest_ids = fields.Many2many('res.partner', 'Participants')
    state = fields.Selection([('draft', 'New'), ('confirmed', 'Confirmed')],
                             tracking=True)
    expense_ids = fields.One2many('business.expense', 'trip_id', 'Expenses')
    alias_id = fields.Many2one('mail.alias', string='Alias', ondelete="restrict",
                               required=True)

    def _get_alias_model_name(self, vals):
    """ Specify the model that will get created when the alias receives a message """
        return 'business.expense'

    def _get_alias_values(self):
    """ Specify some default values that will be set in the alias at its creation """
        values = super(BusinessTrip, self)._get_alias_values()
        # alias_defaults holds a dictionary that will be written
        # to all records created by this alias
        #
        # in this case, we want all expense records sent to a trip alias
        # to be linked to the corresponding business trip
        values['alias_defaults'] = {'trip_id': self.id}
        # we only want followers of the trip to be able to post expenses
        # by default
        values['alias_contact'] = 'followers'
        return values

class BusinessExpense(models.Model):
    _name = 'business.expense'
    _inherit = ['mail.thread']
    _description = 'Business Expense'

    name = fields.Char()
    amount = fields.Float('Amount')
    trip_id = fields.Many2one('business.trip', 'Business Trip')
    partner_id = fields.Many2one('res.partner', 'Created by')

我們希望在出差表單視圖中輕松配置我們的別名,因此讓我們將以下內容添加到我們的表單視圖中:

<page string="Emails">
    <group name="group_alias">
        <label for="alias_name" string="Email Alias"/>
        <div name="alias_def">
            <!-- display a link while in view mode and a configurable field
            while in edit mode -->
            <field name="alias_id" class="oe_read_only oe_inline"
                    string="Email Alias" required="0"/>
            <div class="oe_edit_only oe_inline" name="edit_alias"
                 style="display: inline;" >
                <field name="alias_name" class="oe_inline"/>
                @
                <field name="alias_domain" class="oe_inline" readonly="1"/>
            </div>
        </div>
        <field name="alias_contact" class="oe_inline"
                string="Accept Emails From"/>
    </group>
</page>

現在我們可以直接從表單視圖更改別名地址,并更改可以向別名發送電子郵件的人。

我們可以在我們的費用模型上重寫 message_new() 方法,以便在創建費用時從我們的電子郵件中獲取值:

class BusinessExpense(models.Model):
    # Previous code goes here
    # ...

    def message_new(self, msg, custom_values=None):
        """ Override to set values according to the email.

        In this simple example, we simply use the email title as the name
        of the expense, try to find a partner with this email address and
        do a regex match to find the amount of the expense."""
        name = msg_dict.get('subject', 'New Expense')
        # Match the last occurrence of a float in the string
        # Example: '50.3 bar 34.5' becomes '34.5'. This is potentially the price
        # to encode on the expense. If not, take 1.0 instead
        amount_pattern = '(\d+(\.\d*)?|\.\d+)'
        expense_price = re.findall(amount_pattern, name)
        price = expense_price and float(expense_price[-1][0]) or 1.0
        # find the partner by looking for it's email
        partner = self.env['res.partner'].search([('email', 'ilike', email_address)],
                                                 limit=1)
        defaults = {
            'name': name,
            'amount': price,
            'partner_id': partner.id
        }
        defaults.update(custom_values or {})
        res = super(BusinessExpense, self).message_new(msg, custom_values=defaults)
        return res

活動跟蹤?

活動是用戶在文檔上必須執行的操作,例如打電話或組織會議?;顒与S郵件模塊一起提供,因為它們集成在 Chatter 中,但 不與 mail.thread 捆綁 ?;顒邮?mail.activity 類的記錄,具有類型( mail.activity.type )、名稱、描述、計劃時間(等等)。待處理的活動在聊天窗口小部件中的消息歷史記錄上方可見。

您可以在您的對象上使用 mail.activity.mixin 類來集成活動,并使用特定的小部件(通過字段 activity_ids )在記錄的表單視圖和看板視圖中顯示它們(分別使用 mail_activitykanban_activity 小部件)。

Example

組織商務旅行是一個繁瑣的過程,跟蹤需要的活動,如訂購飛機票或機場出租車可能會很有用。為此,我們將在我們的模型上添加活動mixin,并在我們的旅行消息歷史記錄中顯示下一個計劃的活動。

class BusinessTrip(models.Model):
    _name = 'business.trip'
    _inherit = ['mail.thread', 'mail.activity.mixin']
    _description = 'Business Trip'

    name = fields.Char()
    # [...]

我們修改旅行的表單視圖以顯示它們的下一個活動:

<record id="businness_trip_form" model="ir.ui.view">
    <field name="name">business.trip.form</field>
    <field name="model">business.trip</field>
    <field name="arch" type="xml">
        <form string="Business Trip">
            <!-- Your usual form view goes here -->
            <div class="oe_chatter">
                <field name="message_follower_ids" widget="mail_followers"/>
                <field name="activity_ids" widget="mail_activity"/>
                <field name="message_ids" widget="mail_thread"/>
            </div>
        </form>
    </field>
</record>

您可以在以下模型中找到具體的集成示例:

  • crm.lead 在CRM( crm )應用程序中

  • 銷售( sale )應用程序中的 sale.order

  • project.task 在項目( project )應用程序中

網站功能?

訪客追蹤?

utm.mixin 類可以通過鏈接到指定資源的參數來跟蹤在線營銷/通信活動。該 mixin 將向您的模型添加 3 個字段:

  • campaign_id : Many2one 字段,指向 utm.campaign 對象(例如 Christmas_Special、Fall_Collection 等)

  • source_id : Many2one 字段,指向 utm.source 對象(例如搜索引擎、郵件列表等)

  • medium_id : Many2one 字段,指向 utm.medium 對象(例如: 郵件、電子郵件、社交網絡更新等)

這些模型只有一個字段 name (即它們只是用來區分活動,但沒有任何特定的行為)。

一旦客戶使用這些參數訪問您的網站(即 https://www.odoo.com/?campaign_id=mixin_talk&source_id=www.odoo.com&medium_id=website),這些參數將在訪問者的網站上設置三個cookie。一旦從網站(即潛在客戶表單、職位申請等)創建了繼承utm.mixin的對象,utm.mixin代碼將啟動并從cookie中獲取值以將其設置在新記錄中。完成后,您可以像定義報告和視圖(按組等)時使用其他字段一樣使用campaign/source/medium字段。

要擴展此行為,只需將關系字段添加到簡單模型中(該模型應支持“快速創建”(即使用單個“name”值調用 create() )并擴展函數 tracking_fields()

class UtmMyTrack(models.Model):
    _name = 'my_module.my_track'
    _description = 'My Tracking Object'

    name = fields.Char(string='Name', required=True)


class MyModel(models.Models):
    _name = 'my_module.my_model'
    _inherit = ['utm.mixin']
    _description = 'My Tracked Object'

    my_field = fields.Many2one('my_module.my_track', 'My Field')

    @api.model
    def tracking_fields(self):
        result = super(MyModel, self).tracking_fields()
        result.append([
        # ("URL_PARAMETER", "FIELD_NAME_MIXIN", "NAME_IN_COOKIES")
            ('my_field', 'my_field', 'odoo_utm_my_field')
        ])
        return result

這將告訴系統創建一個名為 odoo_utm_my_field 的cookie,其中包含在url參數 my_field 中找到的值;一旦通過網站表單的調用創建了此模型的新記錄, utm.mixin 的通用 create() 方法將從cookie中獲取此字段的默認值(如果尚不存在,則將動態創建 my_module.my_track 記錄)。

您可以在以下模型中找到具體的集成示例:

  • crm.lead 在CRM( crm )應用程序中

  • hr.applicant 在招聘流程( hr_recruitment )應用程序中

  • helpdesk.ticket 在 Helpdesk 應用程序中 ( helpdesk - 僅限 Odoo 企業版)

網站可見性?

您可以很容易地在任何記錄上添加網站可見性切換。雖然這個 mixin 手動實現起來很容易,但它是繼 mail.thread 繼承之后最常用的 mixin;這證明了它的實用性。這個 mixin 的典型用例是任何具有前端頁面的對象;能夠控制頁面的可見性允許您在編輯頁面時花費時間,并在滿意時才發布它。

如果要包含此功能,您只需要繼承 website.published.mixin

class BlogPost(models.Model):
    _name = "blog.post"
    _description = "Blog Post"
    _inherit = ['website.published.mixin']

此 mixin 在您的模型上添加了 2 個字段:

  • website_published : Boolean 字段,表示發布狀態

  • website_url : Char 字段,表示通過該字段訪問對象的 URL

注意,最后一個字段是計算字段,必須為您的類實現:

def _compute_website_url(self):
    for blog_post in self:
        blog_post.website_url = "/blog/%s" % (log_post.blog_id)

一旦機制到位,您只需調整前端和后端視圖即可使其可訪問。在后端,通常是在按鈕框中添加一個按鈕:

<button class="oe_stat_button" name="website_publish_button"
    type="object" icon="fa-globe">
    <field name="website_published" widget="website_button"/>
</button>

在前端,需要進行一些安全檢查,以避免向網站訪問者顯示“編輯”按鈕:

<div id="website_published_button" class="float-right"
     groups="base.group_website_publisher"> <!-- or any other meaningful group -->
    <t t-call="website.publish_management">
      <t t-set="object" t-value="blog_post"/>
      <t t-set="publish_edit" t-value="True"/>
      <t t-set="action" t-value="'blog.blog_post_action'"/>
    </t>
</div>

請注意,您必須將您的對象作為變量 object 傳遞給模板;在此示例中, blog.post 記錄被傳遞為 blog_post 變量到 qweb 渲染引擎,因此在發布管理模板中必須指定。 publish_edit 變量允許前端按鈕鏈接到后端(允許您輕松地在前端和后端之間切換);如果設置了該變量,則必須在 action 變量中指定要在后端調用的完整外部 ID(請注意,模型必須存在一個表單視圖)。

在Mixin中定義了 website_publish_button 操作,并根據您的對象調整其行為:如果類具有有效的 website_url 計算函數,則用戶單擊按鈕時將被重定向到前端;然后用戶可以直接從前端發布頁面。這確保不會發生意外的在線發布。如果沒有計算函數,則簡單地觸發布爾值 website_published 。

網站元數據?

這個簡單的mixin允許您輕松地在前端頁面中注入元數據。

class BlogPost(models.Model):
    _name = "blog.post"
    _description = "Blog Post"
    _inherit = ['website.seo.metadata', 'website.published.mixin']

此 mixin 在您的模型上添加了 3 個字段:

  • website_meta_title : Char 字段,允許您為頁面設置額外的標題

  • website_meta_description : Char 字段,包含頁面的簡短描述(有時用于搜索引擎結果)

  • website_meta_keywords : Char 字段,包含一些關鍵詞,幫助您的頁面被搜索引擎更精確地分類;”Promote” 工具將幫助您輕松選擇詞匯相關的關鍵詞

這些字段可以使用編輯器工具欄中的“Promote”工具在前端進行編輯。設置這些字段可以幫助搜索引擎更好地索引您的頁面。請注意,搜索引擎不僅僅基于這些元數據來生成結果;最佳的SEO實踐仍然是獲得可靠來源的引用。

其他?

客戶評分?

評分 mixin 允許發送電子郵件請求客戶評分,在看板流程中自動轉換并聚合您的評分統計信息。

在您的模型上添加評分?

要添加評分支持,只需繼承 rating.mixin 模型:

class MyModel(models.Models):
    _name = 'my_module.my_model'
    _inherit = ['rating.mixin', 'mail.thread']

    user_id = fields.Many2one('res.users', 'Responsible')
    partner_id = fields.Many2one('res.partner', 'Customer')

Mixin的行為會根據您的模型進行調整:

  • 如果您的模型中存在 partner_id 字段,則 rating.rating 記錄將鏈接到該字段。

    • 如果您使用的字段不是 partner_id ,則可以使用函數 rating_get_partner_id() 覆蓋此行為。

  • The rating.rating 記錄將鏈接到您模型的 user_id 字段的合作伙伴(如果該字段存在)(即被評價的合作伙伴)

    • 如果您使用的字段不是 user_id ,則可以使用函數 rating_get_rated_partner_id() 覆蓋此行為(請注意,該函數必須返回一個 res.partner 對象,對于 user_id ,系統會自動獲取用戶的合作伙伴)

  • 如果您的模型繼承自 mail.thread ,聊天記錄將顯示評分事件。

通過電子郵件發送評分請求?

如果您希望發送電子郵件請求評分,只需生成一封電子郵件,其中包含指向評分對象的鏈接。一個非?;镜碾娮余]件模板可能如下所示:

<record id="rating_my_model_email_template" model="mail.template">
            <field name="name">My Model: Rating Request</field>
            <field name="email_from">${object.rating_get_rated_partner_id().email or '' | safe}</field>
            <field name="subject">Service Rating Request</field>
            <field name="model_id" ref="my_module.model_my_model"/>
            <field name="partner_to" >${object.rating_get_partner_id().id}</field>
            <field name="auto_delete" eval="True"/>
            <field name="body_html"><![CDATA[
% set access_token = object.rating_get_access_token()
<p>Hi,</p>
<p>How satsified are you?</p>
<ul>
    <li><a href="/rate/${access_token}/5">Satisfied</a></li>
    <li><a href="/rate/${access_token}/3">Okay</a></li>
    <li><a href="/rate/${access_token}/1">Dissatisfied</a></li>
</ul>
]]></field>
</record>

然后您的客戶將收到一封電子郵件,其中包含指向一個簡單網頁的鏈接,允許他們提供有關與您的用戶的交互的反饋(包括自由文本反饋消息)。

您可以通過為評分定義一個操作,輕松地將評分與表單視圖集成起來:

<record id="rating_rating_action_my_model" model="ir.actions.act_window">
    <field name="name">Customer Ratings</field>
    <field name="res_model">rating.rating</field>
    <field name="view_mode">kanban,pivot,graph</field>
    <field name="domain">[('res_model', '=', 'my_module.my_model'), ('res_id', '=', active_id), ('consumed', '=', True)]</field>
</record>

<record id="my_module_my_model_view_form_inherit_rating" model="ir.ui.view">
    <field name="name">my_module.my_model.view.form.inherit.rating</field>
    <field name="model">my_module.my_model</field>
    <field name="inherit_id" ref="my_module.my_model_view_form"/>
    <field name="arch" type="xml">
        <xpath expr="//div[@name='button_box']" position="inside">
            <button name="%(rating_rating_action_my_model)d" type="action"
                    class="oe_stat_button" icon="fa-smile-o">
                <field name="rating_count" string="Rating" widget="statinfo"/>
            </button>
        </xpath>
    </field>
</record>

請注意,評級有默認視圖(看板、透視圖、圖表),可以快速查看客戶評級的總體情況。

您可以在以下模型中找到具體的集成示例:

  • project.task 在項目( rating_project )應用程序中

  • helpdesk.ticket 在 Helpdesk 應用程序中 ( helpdesk - 僅限 Odoo 企業版)