全书完整目录请见:Odoo 14开发者指南(Cookbook)第四版
集成Email是Odoo的最突出的一个功能。可以通过Odoo用户界面直接发送和接收邮件。甚至可以在业务文档中直接管理email来往记录,如线索、销售订单和项目。本章中,我们将探讨一些在Odoo中处理邮件的重要方式。
这里我们将讲解如下主题:
- 配置邮件接收和发送服务器
- 管理文档中的聊天器
- 管理文档中的活动
- 使用Jinja模板发送邮件
- 使用QWeb模板发送邮件
- 管理邮件别名
- 在聊天器中记录用户修改
- 定期发送摘要邮件
技术准备
本章中使用的所有代码均可通过GitHub仓库进行下载:https://github.com/alanhou/odoo14-cookbook/tree/main/Chapter23。
配置接收和发送邮件服务器
在Odoo中发送和接收邮件之前,需要配置接收和发送邮件服务器。本节中,我们将学习如何在Odoo中配置邮件服务器。
准备工作
本节中无需进行任何开发,但需要有邮件服务器的信息,如服务端URL,端口、服务类型、用户名和密码。我们将使用这些信息来配置邮件服务器。
📝注:如果你在使用在线Odoo或Odoo.sh,则无需配置邮件服务器。在这些平台上无需进行任何复杂配置即可发送并接收邮件。本节针对的是自有主机Odoo实例。
如何实现…
配置接收和发送邮件服务器包含一些通用步骤和一些特定服务的单独步骤。因此首先我们将了解通用的配置步骤,然后我们单独配置接收和发送邮件服务器。下面是配置接收和发送邮件服务器都需要做的步骤:
- 在菜单中打开通用设置,Settings > General Settings。(译者注:应至少安装 Discuss 模块)
- 进入Discuss版块并启用External Email Servers。会显示如下选项:
图23.1 – 设置别名域名 - 在Alias Domain字段中,输入邮件服务器所使用的域名。然后保存配置。
配置接收邮件服务器
执行如下步骤配置接收邮件服务器:
- 打开通用配置并点击 Incoming Email Servers链接。会重定向到一个接收邮件服务器的列表视图。
- 点击Create按钮,会打开如下的表单视图。输入接收邮件服务器的详情(参见运行原理一节了解对每个字段的讲解):
图23.2 – 配置接收邮件服务器 - 点击Test & Confirm按钮来验证配置。如果配置接收邮件服务器错误的话会显示错误信息。
译者注:如上图中使用了腾讯企业邮箱,错误信息为:Server replied with following exception: Please using authorized code to login. More information at http://service.mail.qq.com/cgi-bin/help?subtype=1&&id=28&&no=1001256
配置发送邮件服务器
按照如下步骤配置发送邮件服务器:
- 打开通用设置并点击External Email Servers选项,然后点击Outgoing Email Servers链接。会重定向到发送邮件服务器的列表视图。
- 点击Create,会打开如下的表单视图。输入发送邮件服务器的详情(查看运行原理一节了解对每个字段的讲解):
图23.3 – 配置发送邮件服务器 - 点击页面底部的Test connection验证配置。如果配置发送邮件服务器出错的话会显示错误信息。
发送邮件服务器即使在配置正确时也可能会显示报错弹框。注意查看报错弹框中的 Connection Test Succeeded! Everything seems properly set up! 消息。这表示发送邮件服务器已配置正确。
运行原理…
本节中给出的步骤已经很清楚了,无需进一步解释。但是发送邮件和接收邮件记录有一些字段,下面我们来看看它们的用途。
以下是用于配置接收邮件服务器的字段列表:
- Name:服务器的名称,有助于我们在配置了多个接收邮件服务器时识别出具体的接收邮件服务器。
- Server Type:这里需要从3个选项中进行选择:POP, IMAP和Local。这个字段的值基于邮件服务提供商。
- Server Name:服务所运行的服务器域名。
- Port:服务所运行的端口号。
- SSL/TLS:如果使用了SSL/TLS加密的话请勾选这一字段。
- Username:收取邮件的邮箱地址。
- Password:所提供的邮箱地址的密码。
- Active: Active字段用于启用或禁用接收邮件服务器。
- Keep Attachment: 如果希望通过接收邮件管理附件的话关闭该选项。
- Keep Original: 如果希望保留原始及前置邮件,开启该选项。
以下是在配置发送邮件服务器时所使用的字段列表:
- Description:服务器的描述,有助于我们在配置了多个发送邮件服务器识别出指定的发送邮件服务器。
- Priority:这个字段用于定义发送邮件服务器的优先级。数字越小优先级越高,因此优先级数字越低的服务器使用得越多。
- SMTP server:服务所运行的服务端域名。
- SMTP port:服务所运行的端口号。
- Connection security:用于发送邮件的安全类型。
- Username:用于发送邮件的邮箱账号。
- Password:所提供邮箱账号的密码。
- Active: Active字段用于启用或禁用发送邮件服务器。
扩展知识…
默认每5分钟获取一次接收邮件。如果想要修改这一间隔,可按照如下步骤进行操作:
- 激活开发者模式
- 通过Settings > Technical > Automation > Scheduled Actions打开计划动作列表
- 搜索并打开名为Mail: Fetchmail的计划动作
- 使用标记为Execute Every的字段来修改间隔
译者注:’Mail Delivery Failed’, “Mail delivery failed via SMTP server ‘None’.出现这一报错有很多种解决方案,最快速的可能是在开发者模式下进入 Settings > Technical > Parameters > System Parameters删除mail.bounce.alias(设置了 Alias Domain 还需删除mail.catchall.domain),在Odoo 第三方邮件服务发送设置中有过稍微详细些的描述。
管理文档中的聊天器
本节中,我们将学习如何管理文档中的聊天器,并对记录添加通讯线程。
准备工作
本节我们将复用第八章 高级服务端开发技巧中的my_library模块。可以从本书GitHub仓库的Chapter23/ 00_initial_module目录中获取该模块的拷贝。本节中我们将对library.book.rent模型添加聊天器。
如何实现…
按照如下步骤来对library.book.rent模型的记录添加聊天器:
- 在__manifest__.py文件中添加mail模块依赖:
123...'depends': ['base', 'mail'],... - 在library.book.rent模型的定义中继承mail.thread:
1234class LibraryBookRent(models.Model):_name = 'library.book.rent'_inherit = ['mail.thread']... - 在library.book.rent模型的表单视图中添加聊天器微件:
123456789...</sheet><div class="oe_chatter"><field name="message_follower_ids"widget="mail_followers"/><field name="message_ids" widget="mail_thread"/></div></form>... - 安装my_library模块来实时查看修改:
图23.4 – 借书表单视图聊天器
如以上截图所示,在安装该模块之后就能够在表单视图中看到聊天器。
运行原理…
要对任意模型启动聊天器,首先需要安装mail模块。这是因为用于启动聊天器或邮件功能的所有代码都属于mail模块。因此在第1步中我们在my_library模块的声明文件中添加了对mail模块的依赖。这会在安装my_library模块时自动安装mail模块。
操作聊天器的字段和方法是mail.thread模型的一部分。mail.thread是一个抽象模型,仅用于继承使用。在第2步中,我们在library.book.rent模型中继承了mail.thread模型。这会在library.book.rent模型中添加聊天器所需的必要字段和方法。如果你不知道模型继承如何运作,可参见第四章 应用模型中的为可复用模型功能使用抽象模型一节。
在前两步中,我们添加了聊天器所需要的所有字段和方法。对聊天器所剩的只是要在表单视图中添加用户界面。在第3步中,我们添加了消息线程和关注者微件 。你可能在想message_follower_ids和message_ids字段是什么。这些字段没有在library.book.rent模型定义中添加,但通过对mail.thread模型的继承进行了添加。
扩展知识…
在聊天器中提交消息时,会发送邮件给关注者。如果注意观察本节中的示例,图书的借阅者并不是记录的关注者,因此他们不会接收到消息。如果想要向借阅者发送邮件通知,需要将其添加到借阅者列表中。可以手动通过用户界面添加关注者,但如果想要自动添加,可以使用message_subscribe()方法。查看如下代码 – 在我们将图书置为借阅时,下面的代码会自动将借阅者添加到关注者列表中:
1 2 3 4 5 |
@api.model def create(self, vals): res = super(LibraryBookRent, self).create(vals) res.message_subscribe(partner_ids=[res.borrower_id.id]) return res |
类似地,如果希望从列表中删除关注者,可以使用message_unsubscribe()方法。
管理文档中的活动
在使用聊天器时,还可以添加活动。它们用于对记录计划你的动作。这是一种对每条记录的待办事项列表。本节中,我们将学习如何对任意模型启用活动。
准备工作
本节我们将使用前一小节管理文档中的聊天器中的my_library模块。我们对library.book.rent模型添加活动。
如何实现…
按照如下步骤来对library.book.rent模型添加活动:
- 在library.book.rent 模型的Python定义中继承mail.activity.mixin:
1234class LibraryBookRent(models.Model):_name = 'library.book.rent'_inherit = ['mail.thread', 'mail.activity.mixin']... - 在library.book.rent模型的聊天器中添加mail_activity微件:
12345678...<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>... - 更新my_library模块来应用这些修改。这时会显示聊天器活动:
图23.5 – 借书表单视图活动管理器
此处用户可管理不同的聊天器活动。注意由一个用户所设置的计划活动对其他用户均可见。
运行原理…
活动是mail模块的一部分,并且可以选择在聊天器中启用它们。要对记录启用活动,需要继承mail.activity.mixin。类似mail.thread模型,mail.activity.mixin也是一个抽象模型。继承mail.activity.mixin将在模块中添加所有的必要字段和方法。这些方法和字段用于对记录管理活动。在第1步中,我们对library.book.rent模型添加了mail.activity.mixin。因此,对library.book.rent的继承将获取管理活动所要求的所有方法和字段。
在第2步中,我们在表单视图中添加了mail_activity微件。它将显示管理活动的UI界面。通过继承在library.book.rent模型中添加了activity_ids字段。
活动可以为不同的类型。默认,可以创建类型为Email、电话、会议和待办事项的活动。如果希望添加自己的活动类型,可以通过在开发者模式下访问Settings > Technical > Email > Activity Types来实现。
扩展知识…
如果想要自动设置一个定时活动,可以使用mail.activity.mixin模型的 activity_schedule()方法。它会按指定日期创建该活动。可以通过activity_schedule()方法手动创建定时活动,如下:
1 2 3 4 5 6 7 |
@api.model def create(self, vals): res = super(LibraryBookRent, self).create(vals) if res.return_date: res.activity_schedule('mail.mail_activity_data_call', date_deadline=res.return_date) return res |
本例将在有人借阅图书时为图书管理员设置定时电话活动。活动的截止日期会设置为图书的归还日期,因此图书管理员可在当天对借阅者打电话。
使用Jinja模板发送邮件
Odoo支持通过Jinja模板创建动态邮件。Jinja是一个基于文本的模板引擎,用于动态生成HTML内容。本节中我们将创建一个Jinja邮件模板,然后用它发送邮件。
准备工作
本节中我们将使用前一小节管理文档中的活动中的my_library模块。我们将添加Jinja模板来发送邮件给借阅者告诉他/她们图书已逾期。
如何实现…
按照如下步骤向借阅者发送提醒邮件:
- 创建名为my_library/data/mail_template.xml的文件并添加邮件模板:
12345678910111213141516171819202122232425<?xml version="1.0" encoding="utf-8"?><odoo noupdate="1"><record id="book_return_reminder" model="mail.template"><field name="name">Book Return Reminder</field><field name="email_from">${object.book_id.create_uid.email}</field><field name="email_to">${object.borrower_id.email}</field><field name="subject">Reminder for book return</field><field name="model_id" ref="my_library.model_library_book_rent"/><field name="body_html"><![CDATA[<p>Dear ${object.borrower_id.name},</p><p>You had rented the<b>${object.book_id.name}</b> book on${format_date(object.rent_date)}<br/>The due date of book is <bstyle="color:red;">${format_date(object.return_date)}.</b></p><br/><p>Best regards,<br/> Librarian</p>]]></field></record></odoo> - 在声明文件中注册模板文件:
12345678910...'data': ['security/groups.xml','security/ir.model.access.csv','views/library_book.xml','views/library_book_categ.xml','views/library_book_rent.xml','data/mail_template.xml'],... - 在library.book.rent模型的表单视图中添加Send reminder按钮来发送邮件:
1234567...<header><button name="book_return" string="Return the Book" states="ongoing" type="object"/><button name="book_return_reminder" string="Send reminder" states="ongoing" type="object"/><field name="state" widget="statusbar"/></header>... - 在library.book.rent模型中添加book_return_reminder()方法:
1234...def book_return_reminder(self):template_id = self.env.ref('my_library.book_return_reminder')self.message_post_with_template(template_id.id)
更新my_library模块应用修改。这会在library.book.rent模型的表单视图中添加一个Send reminder按钮。在点击该按钮时,订阅者会收到如下消息:
本节中所展示的流程在想要通过邮件向客户发送更新时会很有用。借助Jinja模板,可以动态地发送基于单条记录的邮件。
运行原理…
第1步中,我们使用Jinja创建了一个邮件模板。Jinja模板帮助我们根据记录数据生成动态邮件。邮件模板存储在mail.template模型中。让我们来看一下为创建Jinja邮件模板需要传递的字段列表:
- name:用于标识指定模板的模板名称。
- email_from:该字段的值是发送邮件所使用的邮箱地址。
- email_to:该字段的值是接收者的邮箱地址。
- email_cc:该字段的值用于发送邮件拷贝的邮箱地址。
- subject:该字段包含邮件的标题。
- model_id:该字段包含对模型的引用。邮件模板会使用这个模型的数据进行渲染。
- body_html:这个字段将包含邮件模板的内容主体。它是一个Jinja模板,因此可以使用变量、循环、条件等。如果想要学习有关Jinja模板的更多知识,可访问http://jinja.pocoo.org/docs/2.10/。通常我们在CDATA标签中包裹内容,这样body中的内容会被看作字符数据而不是标记语言。
- auto_delete:这是一个在邮件发送后用于删除邮件的布尔字段。该字段的默认值为False。
- lang:这个字段用于将邮件模板翻译为其它语言。
- scheduled_date: 该字段用于计划未来的邮件。
📝小贴士:可以在email_from, email_to, email_cc, subject, scheduled_date和lang字段中使用${}。这有助于我们动态设置值。参见本节的第1步,我们使用了${object.borrower_id.email}来动态设置了email_to字段。
如果仔细查看body_html字段的内容,会发现我们使用了${object.borrower_id.name}。这里,该对象是一个library.book.rent模型的记录集。在渲染期间,${object.borrower_id.name}使用借阅者的名字进行替换。类似object,在渲染上下文中传递了一些其它帮助函数和变量。以下是传递给渲染器上下文的帮助函数列表:
- object:该变量包含模型的记录集,通过model_id字段在模板中进行设置。
- format_date:这是对用于格式化日期时间对象的方法的引用。
- format_datetime: 这是一个用于转化UTC日期时间为基它时区的日期时间方法的引用。
- format_amount:这是一个对通过货币符号将浮点型转化为字符串的方法的引用。
- format_duration: 该方法用于将浮点值转化为时间,如将1.5转化为01:30。
- user:这是当前用户的记录集。
- ctx:包含环境上下文字典。
📝注:如果想要查看模板列表,开启开发者模式,打开Settings > Technical > Email > Templates菜单。模板的表单视图还提供预览渲染后模板的按钮。
第2步中,我们在声明文件中注册了模板文件。
第3步中,我们在表单视图中添加了一个按钮来调用book_return_reminder()方法,它会向关注者发送邮件。
第4步中,我们添加了book_return_reminder()方法,通过点击按钮进行调用。message_post_with_template()方法用于发送邮件。message_post_with_template()方法在模型中通过mail.thread来继承。要发送该邮件,只需要传递模板ID来作为参数。
扩展知识…
message_post_with_template()方法用于通过Jinja模板发送邮件。如果只是想要通过普通文本发送邮件,可以使用message_post()方法:
1 |
self.message_post(body="Please return your book on time") |
以上的代码会在聊天器中添加一条Please return your book on time 的消息。所有的关注者会收到这条通知消息。如果只是想要记下这条消息,通过subtype_id参数调用该方法。
使用QWeb模板发送邮件
在前一节中,我们学习了如何使用Jinja模板发送邮件。本节中,我们了解发送动态邮件的另一种方式。我们将借助于QWeb模板来发送邮件。
准备工作
本节,我们将使用前一节使用Jinja模板发送邮件中的my_library模块。我们将使用QWeb模板来向借阅者发送邮件来告诉他/她们图书已逾期。
如何实现…
按照如下步骤来向借阅者发送提醒邮件:
- 在my_library/data/mail_template.xml文件中添加QWeb模板:
12345678910111213141516171819<template id="book_return_reminder_qweb"><p>Dear <span t-field="object.borrower_id.name"/>,</p><p>You had rented the<b><span t-field="object.book_id.name"/></b> book on <span t-field="object.rent_date"/><br/>The due date of book is<b style="color:red;"><span t-field="object.return_date"/></b></p><br/><p>Best regards,<br/>Librarian</p></template> - 在library.book.rent模型的表单视图中添加Send reminder (QWeb) 按钮来发送邮件:
12345678...<header><button name="book_return" string="Return the Book" states="ongoing" type="object"/><button name="book_return_reminder" string="Send reminder" states="ongoing" type="object"/><button name="book_return_reminder_qweb" string="Send reminder(QWeb)" states="ongoing" type="object"/><field name="state" widget="statusbar"/></header>... - 在library.book.rent模型中添加book_return_reminder_qweb()方法:
123...def book_return_reminder_qweb(self):self.message_post_with_view('my_library.book_return_reminder_qweb') - 更新my_library模块来应用修改。这会在library.book.rent模型的表单视图中添加一个Send reminder (QWeb)按钮。在点击该按钮时,关注者会收到一条如下的消息:
图23.7 –通过QWeb模板发送的邮件
本节中所展示的流程和前一节使用Jinja模板发送邮件基本一致。唯一的不同是模板类型,因为本节中使用QWeb模板。
译者注:QWeb 模板的内容通过后台Settings > Technical > User Interface > Views 进行查看
运行原理…
第1步中,我们通过book_return_reminder_qweb ID创建了一个QWeb模板。如果查看这个模板,我们不再使用 format_date()数据字段方法。这是因为QWeb渲染引擎自动根据用户的语言处理并展示日期。出于同样的原因,你不需要使用format_amount() 方法来展示货币符号。QWeb渲染引擎将会自动对其进行管理。如果想要了解更多有关QWeb模板的知识,可参见第十四章 CMS网站开发中的创建或更改模板 – QWeb一节。
在第2步中,我们在表单视图中添加了一个按钮来调用book_return_reminder_qweb()方法,它向关注者发送邮件。
在第3步中,我们添加了book_return_reminder_qweb()方法,它通过按钮的点击进行调用。message_post_with_view()方法用于发送邮件。message_post_with_view()方法在模型中通过mail.thread来继承。要发送邮件,只需传递网页模板的XML ID来作为参数。
通过QWeb模板发送邮件与前一节的运行方式相同,但QWeb邮件模板和Jinja邮件模板之间有一些细微的差别。以下是对这两种模板的快速对比:
- 在邮件模板中没有简单的发送额外参数的方式。需要在对象变量中使用记录集来获取动态数据。另一方面,QWeb邮件模板可以通过values参数在渲染器上下文中传递额外的值:
1234self.message_post_with_view('my_library.book_return_reminder_qweb',values={'extra_data': 'test'}) - 要管理日期格式、时区和带有货币符号的金额,在Jinja模板中需要使用format_date、format_tz和format_amount函数,而在QWeb模板中则是自动进行管理的。
- 在Jinja中不能修改其它模块的已有模板,但在QWeb模板中可以通过继承修改邮件模板。如果想要了解更多有关QWeb继承的知识,请参见第十四章 CMS网站开发中的创建或更改模板 – QWeb一节。
- 可以直接通过消息编辑器选择并使用Jinja模板。在下图中,右下角的下拉菜单用于选择一个Jinja模板:
图23.8 – 模板选项 - 使用QWeb,并不能直接通过消息编辑器来选择模板。
扩展知识…
所有的方法(message_post, message_post_with_template和message_post_with_view)都和用户首选项有关。如果用户通过用户首选项修改通知管理选项,该用户将不会收到邮件:取而代之的是他们将在Odoo的用户界面中接收到通知。对于客户同样如此,如果用户取消邮件订阅,他们将不会通过邮件收到任何更新。
此外,Odoo的消息线程遵循一种称为子类型(subtypes)的概念。子类型仅用于接收你所感兴趣的邮件。可以在message_post_*方法中传递额外的参数subtype_id,根据子类型发送邮件。通常,用户会通过Follow按钮的下拉选项管理它们的子类型。我们假定用户设置他们的子类型如下:
根据用户的首选项,该用户仅会收到讨论消息的邮件。
管理邮件别名(待手动验证)
邮件别名是Odoo中用于通过接收邮件创建记录的一种功能。邮件别名的最简单示例是销售团队。只需要发送一封邮件到sale@yourdomain.com,Odoo会在销售团队中针对crm.lead 新建一条记录。本节中,我们将创建一个邮件别名来创建一本图书的借阅记录。
准备工作
本节我们将使用前一节使用QWeb模板发送邮件中的my_library模块。我们会使用rent@yourdomain.com邮箱地址创建自己的邮件别名。如果向这个邮箱发送一封标题中带有图书名称的邮件,在 library.book.rent模型中就会创建一条记录。
如何实现…
按照如下步骤来为library.book.rent模型添加邮件别名:
- 在my_library/data/mail_template.xml文件中添加邮件别名数据:
123456<record id="mail_alias_rent" model="mail.alias"><field name="alias_name">rent</field><field name="alias_model_id" ref="model_library_book_rent"/><field name="alias_user_id" ref="base.user_admin"/><field name="alias_contact">partners</field></record> - 在my_library/models/library_book_rent.py文件中添加如下导入:
12import refrom odoo.tools import email_split, email_escape_char - 在library.book.rent模型中重载message_new()方法:
1234567891011121314@api.modeldef message_new(self, msg_dict, custom_values=None):self = self.with_context(default_user_id=False)if custom_values is None:custom_values = {}regex = re.compile("^\[(.*)\]")match = regex.match(msg_dict.get('subject')).group(1)book_id = self.env['library.book'].search([('name', '=', match),('state', '=', 'available')], limit=1)custom_values['book_id'] = book_id.idemail_from = email_escape_char(email_split(msg_dict.get('from'))[0])custom_values['borrower_id'] = self._search_on_partner(email_from)return super(LibraryBookRent, self).message_new(msg_dict, custom_values)
更新my_library模块来应用修改。然后发送邮件到rent@yourdomain.com。确保在邮件标题中包含了图书名称,如[Odoo 14 Development Cookbook] Request to borrow this book。这会创建一条新的library.book.rent记录并且它会显示如下:
图23.10 – 通过邮件生成的记录
在向rent@yourdomain.com发送带有图书名邮件标题的邮件时,Odoo会生成一条新借阅记录。注意在仅对图书在图书馆中可借阅时才会生效。
运行原理…
第1步中,我们创建了mail.alias记录。这个别名会处理rent@yourdomain.com邮箱地址。在向这个地址发送邮件时,Odoo会在library.book.rent 模型中新建一条记录。如果想要查看系统中活跃的别名列表,可打开Setting > Technical > Email > Aliases。以下为配置别名的可用字段列表:
- alias_name:该字段保存邮件地址的前缀部分,例如,rent@yourdomain.com中的rent是邮箱地址的前缀部分。
- alias_model_id:对接收邮件应创建记录的模型的引用。
- alias_user_id:在收到邮件时,会通过该字段中的用户环境来创建记录。
- alias_contact:这个字段保存该别名的权限首选项。可用的选项包含所有人, 成员, 关注者和雇员。
- alias_defaults:在收到邮件时,它的记录会在针对具体别名的模型中创建。如果想要在记录中设置默认值,在这个字段中以字典的形式提供值。
第2步中,我们添加了所需的导入。第3步中,我们重载了message_new()方法。该方法在别名邮箱上接收到新邮件时自动被调用。这个方法会接收两个参数:
- msg_dict:这个参数是包含有关接收邮件信息的字典。它包含邮件信息如发件人邮箱地址、收件人邮箱地址、邮件标题和邮件内容。
- custom_values:这是一个用于新建记录的自定义值。与在别名记录中使用alias_defaults字段设置的值相同。
本节中我们重载了message_new()方法并从邮件标题中通过一个正则表达式获取到图书的标题。然后借助在第2步中导入的工具获取到发件人的邮箱。我们使用发件邮箱地址来查找借阅者记录。然后,我们通过这两个值来更新custom_values:books_id和borrower_id。我们将更新后的custom_values数据传递给super()方法,它会通过给定的books_id和borrower_id新建一条library.book.rent记录。这就是在发送邮件到别名时创建记录的方法。
注意本节在没有发送正确的邮件标题时会产生报错,如[book name] remaining subject。读者可以根据自己的业务逻辑来更新程序以避免报错。
扩展知识…
一些业务模型要求你需要对每条记录使用单独的别名。例如,销售团队模块对每个团队有独立的别名,如对印度团队使用sale-in@example.com,对比利时团队使用sale-be@example.com。如果想要在自己的模型中管理这种别名,可以使用mail.alias.mixin。为了能在自己的模型中使用它,需要继承这个mixin:
1 2 3 |
class Team(models.Model): _name = 'crm.team' _inherit = ['mail.alias.mixin', 'mail.thread'] |
在继承该mixin后,你将需要向表单视图添加alias_name字段,以便终端用户可以自己添加别名。
在聊天器中记录用户修改
Odoo框架提供了一种内置工具在聊天器中记录字段修改。本节中,我们将对其中的一些字段启用登记,因此如果对它们做出修改,Odoo会在聊天器中添加登记。
准备工作
本节我们使用前一节管理邮件别名中的my_library模块。本节中我们将记录 library.book 模型中一些字段的修改。
如何实现…
修改这些字段的定义,在修改它们时启用对这些字段的记录。如以下代码片断所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class LibraryBookRent(models.Model): _name = 'library.book.rent' _inherit = ['mail.thread', 'mail.activity.mixin'] book_id = fields.Many2one('library.book', 'Book', required=True) borrower_id = fields.Many2one('res.partner', 'Borrower', required=True) state = fields.Selection([('ongoing', 'Ongoing'), ('returned', 'Returned')], 'State', default='ongoing', required=True, tracking=True) rent_date = fields.Date(default=fields.Date.today, tracking=True) return_date = fields.Date(tracking=True) |
更新my_library模块来应用修改。在library.book.rent模型中新建一条记录,在这些字段中做一些修改,然后归还图书。如果查看聊天器,会看到如下日志:
在对state, rent_date或return_date作出修改时,都会在聊天器中看到新的日志。这会有助于我们查看该记录的完整历史信息。
运行原理…
通过对这个字段添加tracking=True属性,可以对该字段启用登记。在设置tracking=True属性时,Odoo会在聊天器中添加一条更新字段值时的修改记录。如果对多对记录启用追踪,又希望对追踪记录进行排序,可以在追踪参数中这样传递数值:tracking=20。在传递tracking=True时,使用的是默认排序值,即100.
本节中,我们对state, rent_date和return_date字段添加了tracking=True,这表示Odoo会在更新rent_date, return_date或state 字段的值时记录这些修改。查看如何实现小节中的截图,我们仅修改了rent_date和return_date字段。
注意tracking功能仅用于继承了 mail.thread模型的模型,因为代码相关的聊天器和日志是mail.thread 模型的一部分。
定期发送摘要邮件
Odoo框架支持定期发送摘要邮件。通过摘要邮件,可以发送KPI业务信息的邮件。本节中,我们向图书管理员发送借书相关的数据。
准备工作
本节我们使用前一节在聊天器中记录用户修改中的my_library模块。
如何实现…
按照如下步骤生成借书记录的摘要邮件:
- 继承digest.digest模型,添加用于KPI的字段:
12345678910111213class Digest(models.Model):_inherit = 'digest.digest'kpi_book_rent = fields.Boolean('Book Rent')kpi_book_rent_value = fields.Integer(compute='_compute_kpi_book_rent_value')def _compute_kpi_book_rent_value(self):for record in self:start, end, company = record._get_kpi_compute_parameters()record.kpi_book_rent_value = self.env['library.book.rent'].search_count([('create_date', '>=', start),('create_date', '<', end)]) - 继承digest.digest模型的表单视图并添加KPI字段:
123456789101112131415<?xml version='1.0' encoding='utf-8'?><odoo><record id="digest_digest_view_form" model="ir.ui.view"><field name="name">digest.digest.view.form.inherit.library</field><field name="model">digest.digest</field><field name="inherit_id" ref="digest.digest_digest_view_form"/><field name="arch" type="xml"><xpath expr="//group[@name='kpi_general']" position="after"><group name="kpi_library" string="Library"><field name="kpi_book_rent"/></group></xpath></field></record></odoo>
更新模块应用修改。在更新模块后,打开Settings > Technical > Emails > Digest Emails,如下图所示:
图23.12 – 开启借书数据的摘要邮件
在开启之后,如果进行了订阅,就会开始接收到这些摘要邮件。
运行原理…
需要两个字段来构建自定义摘要邮件。第一个字段为布尔字段,用于启用及禁用KPI,第二个字段为计算字段,在请求KPI值时进行调用。第1步中我们创建了这两个字段。如果查看compute字段的字义,会发现使用了_get_kpi_compute_parameters方法。这一方法返回三个参数:开始日期、结束日期和公司记录。可以使用这些参数来生成KPI的值。如们返回指定日期范围内借书的数量。如果KPI兼容了多站点,那么就可以使用公司参数。
第2步中,我们在摘要表单视图中添加了一个字段。该字段用于启用/禁用摘要邮件。启用后会开始收到如下的摘要邮件:
开启开发者模式,然后打开Settings > Technical > Emails > Digest Emails。此外可以配置摘要邮件的接收人以及设置摘要邮件的发送频率。也可以在这里启用/禁用摘要邮件。
译者注:以上通过设置公司的邮箱进行的发送,根据配置的不同所使用的邮箱也会不同。受限于国内企业邮箱的限制,可能需要添加一个postmaster-odoo@yourdomain.com 的邮箱。