ミックスインと便利なクラス

Odooは、オブジェクトに頻繁に使用される動作を簡単に追加できる便利なクラスとミックスインをいくつか実装しています。 このガイドでは、それらのほとんどについて、例や使用事例について詳しく説明します。

メッセージ機能

メッセージの統合

基本的なメッセージシステム

メッセージ機能をモデルに統合するのは非常に簡単です。mailを継承するだけです。 hread mixinとchatter <chatter/> 要素をフォームビューに追加すると、すぐに起動して実行できます。 chatter 要素はフォームの動作を制御するいくつかのオプションをサポートしています。

  • open_attachments: 添付セクションをデフォルトで展開します。

  • reload_on_attachment: 添付ファイルが追加/削除されたときにフォームビューをリロードします

  • reload_on_follower : フォロワーが更新されたときにフォームビューをリロードします

  • reload_on_post: 新しいメッセージが投稿されたときにフォームビューをリロードします。

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="business_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 with options you might want to set -->
            <chatter open_attachments="True"/>
        </form>
    </field>
</record>

モデルにチャットサポートを追加したら、ユーザーは簡単にあなたのモデルの任意のレコードにメッセージや内部メモを追加できます。 すべてのフォロワーにメッセージを送る通知(ベース)があります。 roup_user) 内部ノートのユーザ)。 メールゲートウェイとキャッチオールアドレスが正しく設定されている場合、 これらの通知はメールで送信され、メールクライアントから直接返信することができます。 自動ルーティングシステムは正しいスレッドに答えをルーティングします

サーバー側では、メッセージを簡単に送信したり、あなたの記録上のフォロワーを管理するためのいくつかのヘルパー関数があります。

メッセージの投稿

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

既存のスレッドに新しいメッセージを投稿し、新しい mail.message ID を返します。

パラメータ
  • body (str | Markup) -- body of the message. Will be exceed if str. Use a Markup object for HTML content.

  • message_type (str) -- mail_message.message_type フィールドを参照

  • parent_id (int) -- プライベートディスカッションの場合、親パートナーをメッセージに追加して、以前のメッセージへの返信を処理する

  • attachments (list(tuple(str,str))) -- (name,content) という形式の添付ファイルのタプルのリストです。ここではコンテンツは base64 エンコードされていません。

  • body_is_html (bool) -- は、`str`であっても、`body`をHTMLとして扱うかどうかを示します。

  • **kwargs -- 新しいmail.message レコードのデフォルトカラム値として追加キーワード引数が使用されます

戻り値

新しく作成されたmail.messageのID

戻り値の型

int

message_post_with_view(views_or_xmlid, **kwargs):

Helper メソッドは、メールを送信します。また、view_id を使用して、ir.qweb エンジンを使用してレンダリングするメッセージを投稿します。 このメソッドはテンプレートと作曲者にはビューを一括処理できるものはないため、スタンドアロンです。 このメソッドは、テンプレートがiruiビューを処理するとおそらく消えます。

パラメータ

record (str or ir.ui.view) -- 送信されるべきビューの外部 ID または記録

message_post_with_template(template_id, **kwargs)

メールをテンプレートで送信するヘルパーメソッド

パラメータ
  • template_id -- メッセージの本文を作成するためのテンプレートのid

  • **kwargs -- mail.compose.message ウィザード(mail.messageから継承)を作成するためのパラメータ

メッセージの受信

これらのメソッドは、メールゲートウェイによって新しい電子メールが処理されたときに呼び出されます。 これらのメールは新しいスレッド( :ref:`alias <reference/mixins/mail/alias>`経由で到着した場合)または既存のスレッドからの返信である可能性があります。 これらをオーバーライドすると、メール自体の値に応じてスレッドのレコードに値を設定することができます (i. をクリックします。 日付または電子メールアドレスを更新し、CCのアドレスをフォロワーとして追加します。

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) -- 与えられたレコードを更新するための値を含む dict です。dict が None または void の場合、書込み操作は実行されません。

戻り値

True

フォロワー管理

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

戻り値

True

戻り値の型

bool

message_unsubscribe_users(user_ids=None)

ユーザーを使用して、message_subscribe 上の Wrapper です。

パラメータ

user_ids (list(int)) -- IDs of the users that will be unsubscribed to the record; if None, unsubscribe the current user instead.

戻り値

True

戻り値の型

bool

ログの変更

mail モジュールは、フィールドに強力なトラッキングシステムを追加し、レコードのチャット内の特定のフィールドに変更を記録することができます。 フィールドにトラッキングを追加するには、tracking属性を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 フィールドは通知にも表示され、通知についての詳細な説明を与えます (名前が変更されていない場合でも)。

サブタイプ

サブタイプは、メッセージをより詳細に制御することができます。 サブタイプは、通知の分類システムとして機能します。サブタイプは、受信したい通知のサブタイプをカスタマイズするために、ドキュメントに購読者を許可します。

サブタイプはモジュール内のデータとして作成されます。モデルには次のフィールドがあります。

name (必須) - Char

サブタイプの名前は通知カスタマイズポップアップに表示されます

description - Char

このサブタイプに対して投稿されるメッセージに追加される説明。無効の場合は、代わりに名前が追加されます。

internal - Boolean

内部サブタイプのメッセージは、base.group_user グループのメンバーなどの従業員のみ表示されます

parent_id - Many2one

自動契約のサブタイプをリンクします。たとえば、プロジェクトサブタイプはこのリンクを通じてタスクサブタイプにリンクされます。 誰かがプロジェクトを購読しているとき、彼は親サブタイプを使用して見つかったサブタイプのこのプロジェクトのすべてのタスクを購読します

relation_field - Char

例として、プロジェクトとタスクのサブタイプをリンクする場合、リレーションフィールドは tasks の project_id フィールドです。

res_model - Char

モデルのサブタイプが適用されます; False の場合、このサブタイプはすべてのモデルに適用されます。

default - Boolean

サブタイプの購読時にデフォルトで有効になっているかどうか

sequence - Integer

通知カスタマイズポップアップでサブタイプを注文するために使用されます

hidden - Boolean

サブタイプが通知カスタマイズポップアップで非表示になっているかどうか

フィールドトラッキングとのインターフェースサブタイプを使用すると、興味のあるユーザーによって異なる種類の通知を受け取ることができます。 これを行うには、 _track_subtype() 関数をオーバーライドします。

_track_subtype(init_values)

更新された値に従って、レコードの変更によってトリガーされたサブタイプを与えます。

パラメータ

init_values (dict) -- レコードの元の値。変更されたフィールドのみが 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)

通知のカスタマイズ

フォロワーに通知を送信する場合、テンプレート内のボタンを追加して、電子メールから直接アクションを実行できるようにすると便利です。 レコードのフォームビューに直接リンクするシンプルなボタンでも便利です。 しかし、ほとんどの場合、ポータルユーザーにこれらのボタンを表示したくありません。

通知システムでは、次の方法で通知テンプレートをカスタマイズできます。

  • *アクセスボタン*を表示:これらのボタンは通知メールの上部に表示され、受信者がレコードのフォームビューに直接アクセスできるようにします

  • 表示*フォローボタン*:これらのボタンは、受信者が直接レコードを購読することを可能にします

  • 表示*フォロー解除ボタン*:これらのボタンは、受信者がレコードから直接購読解除することを可能にします

  • *カスタムアクションボタン*を表示: これらのボタンは特定のルートへの呼び出しであり、電子メールから直接役に立ついくつかのアクションを利用できるようにします (i. をクリックします。 リードを商談に変換し、費用マネージャーの費用表を検証します。

これらのボタンの設定は、関数 _notify_get_groups をオーバーライドすることで、あなた自身を定義することができます。

_notify_get_groups(message, groups)

更新された値に従って、レコードの変更によってトリガーされたサブタイプを与えます。

パラメータ
  • message (record) -- mail.message レコードが現在送信されています

  • groups (list(tuple)) -- フォームのタプルのリスト (group_name, group_func, roup_data) where: group_name は、グループをオーバーライドして操作できるようにするためにのみ使用される識別子です。 デフォルトのグループは user (従業員ユーザにリンクされた受信者) です。 portal (ポータルユーザにリンクされた受信者) と customer (ユーザーにリンクされていない受信者) オーバーライドの使用例は、resにリンクされたグループを追加することです。 Hr Officersのように、特定のアクションボタンを設定します。 group_func はパートナーレコードをパラメータとして取り込む関数ポインタです。 このメソッドは、特定のグループに属しているかどうかを確認する受信者に適用されます。 最初の一致するグループのみが保持されます。 評価順はリスト順です。 group_data は、通知メールのパラメータを含む次のキーを含むディクトです。値: - has_button_access メールに Access <Document> を表示するかどうか。 新規グループのデフォルトは True で、ポータル / 顧客の False です。 - button_access dict - has_button_follow を表示するかどうかメールでフォローする (受信者が現在スレッドをフォローしていない場合)。 新規グループのデフォルトは True で、ポータル / 顧客の False です。 - button_follow dict with url and title of the button - has_button_unfollowing whether to display Unfollow in email (受信者が現在スレッドをフォローしている場合). 新規グループのデフォルトは True で、ポータル / 顧客の False です。 - button_unfollow dict dict with url and title of the button - actions list of action buttons to display in the notification email. 各アクションは、ボタンのURLとタイトルを含むディクトです。

戻り値

サブタイプがトリガーされていない場合は、サブタイプの完全な外部 ID または False

アクションリスト内の URL は、_notify_get_action_link() 関数を呼び出すことで自動的に生成できます。

現在のレコードで指定された型のリンクを生成します。(kwargs modelres_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)のメンバーのみに表示されます。 roup_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: any(
                user.sudo().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 にも設定できます。

コンテキストキー:

これらのコンテキストキーは mail を多少制御するために使うことができます。 ``create()write() (または便利な他のメソッド)への呼び出し時に自動購読やフィールドトラッキングのようなhread`` 機能。

  • mail_create_nosubscribe: at create or message_post, do not subscribe the current user to the record thread

  • mail_create_nolog : 作成時、自動でログを記録しない '<Document> 作成済み' メッセージ

  • mail_notrack: 作成時と書き込み時に、メッセージの作成時のトラッキング値を実行しないでください

  • tracking_disable: 作成時と書き込み時に、MailThreadの機能(自動購読、トラッキング、投稿、...)は実行されません。

  • mail_auto_delete : メール通知を自動的に削除します。

  • mail_notify_force_send: 送信する電子メール通知が 50 未満の場合、キューを使用する代わりに直接送信します。デフォルトでは True

  • mail_notify_user_signature : 電子メール通知に現在のユーザ署名を追加します。デフォルトは True

メールエイリアス

エイリアスは、特定のレコードにリンクされる設定可能な電子メールアドレスです (通常は mail を継承します)。 電子メールで連絡したときに新しいレコードを作成する lias.mixin モデル。 それらはあなたのシステムを外部からアクセスできる簡単な方法です。 ユーザーや顧客が直接Odooに接続することなく、データベース内のレコードをすばやく作成できるようにします。

エイリアス対受信メールゲートウェイ

一部の人は、この目的のために受信メールゲートウェイを使用しています。 エイリアスを使用するにはメールゲートウェイが正しく設定されている必要があります。 しかし、すべてのルーティングはOdoo内で行われるため、1つのキャッチオールドメインで十分です。 エイリアスにはメールゲートウェイよりもいくつかの利点があります:

  • 簡単に設定できます
    • 単一の入ってくるゲートウェイは多くのエイリアスで使用できます。 これにより、ドメイン名に複数のメールを設定する必要がなくなります(すべての設定はOdoo内で行われます)

    • エイリアスを構成するためにシステムアクセス権は必要ありません

  • より一貫性のある
    • 設定サブメニューではなく、関連レコードで設定可能

  • サーバー側をオーバーライドするのが簡単
    • Mixinモデルは最初から拡張されるように構築されています メールゲートウェイよりも簡単に受信メールから有用なデータを抽出できるようになります

エイリアスのサポート統合

エイリアスは通常、親モデルで構成され、電子メールで連絡すると特定のレコードを作成します。 たとえば、プロジェクトにはタスクや課題を作成するためのエイリアスがあります。営業チームにはリードを生成するためのエイリアスがあります。

注釈

エイリアスによって作成されるモデルは mail_thread モデルを継承する必要があります。

エイリアスのサポートは mail.alias.mixin を継承することで追加されます。このミックスインは新しいメールを生成します。 作成された親クラスの各レコードの lias`` レコード (例えば project.project レコードは mail.alias レコードが作成時に初期化されます) です。

注釈

エイリアスは手動で作成でき、単純な Many2one フィールドでサポートされます。 このガイドでは、エイリアス、レコード固有のデフォルト値などの自動作成とより完全な統合を想定しています。

mail.thread 継承とは異なり、mail.alias.mixin は特定のオーバーライドを正しく動作させる必要があります。 これらのオーバーライドはエイリアスの値を指定します。 例えば、それが作成しなければならないレコードの種類や、おそらくこれらのレコードが親オブジェクトに依存している可能性があります。

_get_alias_model_name(vals)

エイリアスのモデル名を返します。 既存のレコードに返信されていない受信メールは、このエイリアスモデルの新しいレコードを作成します。 値は vals に依存します。このモデルのレコードが作成されたときに create に渡される値の dict です。

パラメータ

dict (vals) -- エイリアスを保持する新しく作成されたレコードの値

戻り値

モデル名

戻り値の型

str

_get_alias_values()

値を返してエイリアスを作成するか、作成後にエイリアスに書き込みます。 完全に必須ではありませんが、通常、新しく作成されたレコードがエイリアスの親にリンクされることを確認する必要があります (i. を選択します。正しいプロジェクトで作成されるタスク) は、エイリアスの alias_defaults フィールドにデフォルト値の辞書を設定します。

戻り値

新しいエイリアスに書き込まれる値の辞書

戻り値の型

dict

_get_alias_values() のオーバーライドは、エイリアスの動作を簡単に変更できるため、特に興味深いものです。 エイリアスに設定できるフィールドの中で、以下に特に関心があります。

alias_name - Char

name of the email alias, e.g. 'jobs' if you want to catch emails for <jobs@example.odoo.com>

alias_user_id - Many2one (res.users)

このエイリアスのメールを受信した時に作成されたレコードの所有者; この項目が設定されていない場合、システムは送信者(From)アドレスに基づいて正しい所有者を見つけようとします。 または、そのアドレスに対してシステムユーザーが見つからない場合は、管理者アカウントを使用します

alias_defaults - Text

このエイリアスの新しいレコードを作成するときにデフォルト値を提供するために評価される Python 辞書

alias_force_thread_id - Integer

すべての受信メッセージが添付されるスレッド(レコード)の任意のID。返信しなかったとしても; 設定すると新しいレコードの作成が完全に無効になります

alias_contact - Selection

メールゲートウェイを使用して文書にメッセージを投稿するポリシー

  • everyone: 誰でも投稿可能

  • パートナー:認証済みパートナーのみ

  • フォロワー:関連文書または次のチャンネルのメンバーのみフォロワーします

エイリアスは :ref:`委譲継承 <reference/orm/inheritance>`を使用することに注意してください。 つまり、エイリアスが別のテーブルに保存されている間、親オブジェクトから直接これらのフィールドにアクセスすることができます。 これにより、レコードのフォームビューからエイリアスを簡単に設定できます。

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

アクティビティの追跡

アクティビティとは、ユーザーが電話をかけたり、会議を開催したりするなど、ドキュメント上で行う必要があるアクションです。 アクティビティは Chatter に統合されているため、メール モジュールに付属していますが、mail.thread にバンドルされていません。 アクティビティは``mail.activity`` クラスのレコードで、タイプは mail.activity です。 ype``), name, description, scheduled time (etc.) 保留中のアクティビティはチャットウィジェットのメッセージ履歴の上に表示されます。

mail.activityを使ってアクティビティを統合することができます。 フォームビューとレコードのカンバンビュー(``mail_activity および kanban_activity ウィジェット)で、オブジェクトとそれらを表示する特定のウィジェットにixin`` クラス。 それぞれ)。

Example

出張を整理することは退屈なプロセスであり、飛行機のチケットや空港のためのタクシーを注文するような必要な活動を追跡することは有用である可能性があります。 そうするために、私たちのモデルにアクティビティミックスを追加し、私たちの旅行のメッセージの歴史の中で次の予定されている活動を表示します。

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

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

旅行のフォームビューを変更して、次のアクティビティを表示します。

<record id="business_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 -->
            <chatter>
                <field name="message_follower_ids" widget="mail_followers"/>
                <field name="activity_ids" widget="mail_activity"/>
                <field name="message_ids" widget="mail_thread"/>
            </chatter>
        </form>
    </field>
</record>

統合の具体例は以下のモデルにあります。

  • CRM (crm) アプリケーションの crm.lead

  • Sale(sale)アプリケーションの``sale.order``

  • プロジェクト (project) アプリケーションの project.task

ウェブサイトの機能

訪問者の追跡

utm.mixin クラスは、指定されたリソースへのリンクで引数を介してオンラインマーケティング/コミュニケーションキャンペーンを追跡するために使用できます。 ミックスインは3つのフィールドをモデルに追加します。

  • campaign_id: Many2one フィールドから utm.campaign オブジェクト (例: Christmas_Special, Fall_Collection, etc.)

  • source_id: Many2one フィールド utm.source オブジェクト (検索エンジン、メーリングリストなど)

  • medium_id: Many2one フィールド utm.medium オブジェクト (例: カタツムリメール、電子メール、ソーシャルネットワークの更新など)

これらのモデルは単一のフィールド name を持っています(つまり、キャンペーンを区別するためだけに存在しますが、特定の動作はありません)。

顧客がこれらのパラメータをURLに設定してウェブサイトにアクセスすると(例: https://www.odoo.com/?campaign_id=mixin_talk&source_id=ww.odoo) om&medium_id=website), これらのパラメータについては、訪問者のウェブサイトで3つのクッキーが設定されます. utm.mixinを継承するオブジェクトがウェブサイトから作成されると (i. をクリックします。リードフォーム、ジョブアプリケーションなど)、utm.mixinコードが開始され、クッキーから値を取得して新しいレコードに設定します。 これが完了したら、レポートとビュー(グループなど)を定義する際に、キャンペーン/ソース/媒体フィールドを他のフィールドとして使用できます。

この動作を拡張するには、単純なモデルにリレーショナルフィールドを追加するだけです(モデルは quick create (i) をサポートする必要があります)。 をクリックします。単一の 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

これにより、URL パラメータ my_field にある odoo_utm_my_field という名前のクッキーを作成するようにシステムに指示します。 ウェブサイトのフォームからの呼び出しによってこのモデルの新しいレコードが作成されると、utmの``create() メソッドの一般的なオーバーライドが行われます。 ixin`` は、このフィールドのデフォルト値をクッキーから取得します (そして my_module)。 y_track レコードがまだ存在しない場合は、その場で作成されます)。

統合の具体例は以下のモデルにあります。

  • CRM (crm) アプリケーションの crm.lead

  • 募集プロセスの``hr.applicant`` (hr_recritment)

  • Helpdesk の helpdesk.ticket (helpdesk - Odoo Enterprise のみ) アプリケーション

ウェブサイトの表示

任意のレコードにウェブサイトの表示切り替えを簡単に追加できます。 このミックスインは手動で実装するのは非常に簡単ですが、mail.thread 継承の後に最も頻繁に使用されます。 このミックスインの典型的なユースケースは、フロントエンドページを持つオブジェクトです。 ページの可視性を制御できるようになれば、ページを編集中に時間をかけて、満足した時にのみ公開することができます。

機能を含めるには、 website.published.mixin を継承するだけです。

class BlogPost(models.Model):
    _name = "blog.post"
    _description = "Blog Post"
    _inherit = ['website.published.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 変数として qweb レンダリングエンジンにost`` レコードが渡されました。公開管理テンプレートにこれを指定する必要があります。 publish_edit 変数はフロントエンドボタンをバックエンドにリンクさせることができます (フロントエンドからバックエンドに切り替えることができます) 設定されていれば は、バックエンドで action 変数内で呼び出したいアクションの完全な外部IDを指定する必要があります (モデルにフォームビューが存在する必要があります)。

アクション website_publish_button はミックスインで定義され、その動作をオブジェクトに適応します。クラスに website_url 計算関数がある場合。 ユーザーはボタンをクリックするとフロントエンドにリダイレクトされます ユーザーは、フロントエンドから直接ページを公開できます。 これにより、誤ってオンラインパブリケーションが発生しないことが保証されます。計算関数がない場合は、boolean website_published がトリガーされます。

ウェブサイトメタデータ

このシンプルなミックスインを使用すると、フロントエンドページにメタデータを簡単に挿入できます。

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

このミックスインは、モデルに3つのフィールドを追加します。

  • website_meta_title: Char 項目で、あなたのページに追加のタイトルを設定できます。

  • website_meta_description: Char フィールドにページの簡単な説明が含まれています (検索エンジンの結果で使用されることがあります)

  • website_meta_keywords: :class:`~odoo.fields har`フィールドには、検索エンジンによってより正確に分類されるためのキーワードが含まれています。 「プロモーション」ツールは、辞書に関連するキーワードを簡単に選択するのに役立ちます

これらの項目は、エディタツールバーの「プロモーション」ツールを使用してフロントエンドで編集できます。 これらの項目を設定すると、検索エンジンがページのインデックスを向上させるのに役立ちます。 検索エンジンはこれらのメタデータのみをベースにしないことに注意してください。 SEOの最善の方法は信頼できる情報源によって参照されるべきである。

その他

顧客評価

レーティングミックスインを使用すると、電子メールを送信して顧客のレーティングを要求したり、カンバンプロセスで自動移行を行ったり、評価に関する統計を集計したりできます。

あなたのモデルに評価を追加しています

評価サポートを追加するには、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')

ミックスインの動作は、次のモデルに適応します。

  • rating.rating レコードはモデルの partner_id フィールドにリンクされます (フィールドが存在する場合)。

    • この動作は partner_id 以外のフィールドを使用する場合、関数 rating_get_partner_id() で上書きできます。

  • rating.rating レコードは、モデルの user_id フィールドのパートナーにリンクされます (フィールドが存在する場合) (i. を選択します。評価されたパートナー)

    • この動作は user_id 以外のフィールドを使用する場合、関数 rating_get_rated_partner_id() でオーバーライドできます(関数は res を返す必要があることに注意してください)。 artner の場合、システムは自動的にユーザーのパートナーを取得します。

  • チャット履歴は評価イベントを表示します(モデルが 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>

デフォルトのビュー(kanban、pivot、グラフ)があることに注意してください。これにより、顧客評価の迅速なバードビューが可能になります。

統合の具体例は以下のモデルにあります。

  • プロジェクト (rating_project) アプリケーションの project.task

  • Helpdesk の helpdesk.ticket (helpdesk - Odoo Enterprise のみ) アプリケーション