Ioan Galan (Studio73) 2025-03-26 20:43:35 +00:00 committed by GitHub
commit e6b20daffd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 126 additions and 12 deletions

View File

@ -31,6 +31,10 @@ Mail Message Reply
This addon allow to reply on messages from odoo directly. It is useful
when replying to a message from a customer.
Additionally, it is possible to separate the reply body from the mail
body. This separation is only for the composer and the sent mail will
contain both parts.
**Table of contents**
.. contents::
@ -42,6 +46,12 @@ Usage
On the messages from threads, a reply button is shown. Once it has been
pressed, a composer with the reply is shown.
To activate the separation of the reply body add the system parameter
"mail_quoted_reply.separate_reply_body". After opening a composer with
the reply button the reply body will be shown below the mail body as
readonly. To write into the reply body uncheck "Reply Readonly". For
longer replies this can take some time.
Bug Tracker
===========

View File

@ -10,7 +10,9 @@
"author": "Creu Blanca,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/social",
"depends": ["mail"],
"data": [],
"data": [
"views/mail_compose_message_views.xml",
],
"assets": {
"web.assets_backend": [
"/mail_quoted_reply/static/src/*.js",

View File

@ -1,11 +1,15 @@
from markupsafe import Markup
from odoo import api, models, tools
from odoo import api, fields, models, tools
class MailComposeMessage(models.TransientModel):
_inherit = "mail.compose.message"
is_reply_readonly = fields.Boolean(default=True, string="Reply Readonly")
reply_body = fields.Html(default="", string="Reply body")
is_separate_body = fields.Boolean(compute="_compute_is_separate_body")
@api.depends("composition_mode", "model", "res_domain", "res_ids", "template_id")
@api.depends_context("is_quoted_reply")
def _compute_body(self):
@ -13,10 +17,13 @@ class MailComposeMessage(models.TransientModel):
for composer in self:
context = composer._context
if context.get("is_quoted_reply"):
if composer.body:
composer.body += Markup(context["quote_body"])
if self.is_separate_body:
self.reply_body = context["quote_body"]
else:
composer.body = Markup(context["quote_body"])
if self.body:
self.body += Markup(context["quote_body"])
else:
self.body = Markup(context["quote_body"])
return res
@api.depends(
@ -36,3 +43,29 @@ class MailComposeMessage(models.TransientModel):
if subj:
composer.subject = tools.ustr(subj)
return res
@api.onchange("is_reply_readonly")
def _onchange_is_reply_readonly(self):
if self.reply_body:
self.reply_body = Markup(self.reply_body)
@api.depends("reply_body")
def _compute_is_separate_body(self):
if self._context.get("is_quoted_reply", False):
parameter_string = (
self.env["ir.config_parameter"]
.sudo()
.get_param("mail_quoted_reply.separate_reply_body", "")
)
self.is_separate_body = parameter_string.lower() not in ["", "false", "0"]
else:
self.is_separate_body = False
def _prepare_mail_values(self, res_ids):
results = super()._prepare_mail_values(res_ids)
if self.is_separate_body and self.reply_body:
for res_id in res_ids:
values = results.get(res_id)
reply_body = Markup(self.reply_body)
values.update({"body": values.get("body") + reply_body})
return results

View File

@ -1,2 +1,6 @@
This addon allow to reply on messages from odoo directly. It is useful
when replying to a message from a customer.
Additionally, it is possible to separate the reply body from the mail
body. This separation is only for the composer and the sent mail will
contain both parts.

View File

@ -1,2 +1,6 @@
On the messages from threads, a reply button is shown. Once it has been
pressed, a composer with the reply is shown.
To activate the separation of the reply body add the system parameter "mail_quoted_reply.separate_reply_body".
After opening a composer with the reply button the reply body will be shown below the mail body as readonly.
To write into the reply body uncheck "Reply Readonly". For longer replies this can take some time.

View File

@ -372,6 +372,9 @@ ul.auto-toc {
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/social/tree/17.0/mail_quoted_reply"><img alt="OCA/social" src="https://img.shields.io/badge/github-OCA%2Fsocial-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/social-17-0/social-17-0-mail_quoted_reply"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/social&amp;target_branch=17.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This addon allow to reply on messages from odoo directly. It is useful
when replying to a message from a customer.</p>
<p>Additionally, it is possible to separate the reply body from the mail
body. This separation is only for the composer and the sent mail will
contain both parts.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
@ -390,6 +393,11 @@ when replying to a message from a customer.</p>
<h1><a class="toc-backref" href="#toc-entry-1">Usage</a></h1>
<p>On the messages from threads, a reply button is shown. Once it has been
pressed, a composer with the reply is shown.</p>
<p>To activate the separation of the reply body add the system parameter
“mail_quoted_reply.separate_reply_body”. After opening a composer with
the reply button the reply body will be shown below the mail body as
readonly. To write into the reply body uncheck “Reply Readonly”. For
longer replies this can take some time.</p>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h1>

View File

@ -44,3 +44,32 @@ class TestMessageReply(TransactionCase):
)
self.assertTrue(new_message)
self.assertEqual(1, len(new_message))
def test_reply_separate_body(self):
self.env["ir.config_parameter"].sudo().create(
{
"key": "mail_quoted_reply.separate_reply_body",
"value": "True",
}
)
partner = self.env["res.partner"].create({"name": "demo partner"})
message = partner.message_post(
body="demo message",
message_type="email",
partner_ids=self.env.ref("base.partner_demo").ids,
)
partner.invalidate_recordset()
action = message.reply_message()
wizard = (
self.env[action["res_model"]].with_context(**action["context"]).create({})
)
wizard._compute_body()
self.assertTrue("<p>demo message</p>" in wizard.reply_body)
wizard.action_send_mail()
new_message = partner.message_ids.filtered(
lambda r: r.message_type != "notification" and r != message
)
self.assertTrue(new_message)
self.assertEqual(1, len(new_message))
new_message = new_message[0]
self.assertTrue("<p>demo message</p>" in new_message.body)

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="mail_quoted_reply_composer_view_form" model="ir.ui.view">
<field name="model">mail.compose.message</field>
<field name="inherit_id" ref="mail.email_compose_message_wizard_form" />
<field name="arch" type="xml">
<xpath expr="//field[@name='body']" position="after">
<field name="is_separate_body" invisible="1" />
<field
name="reply_body"
readonly="is_reply_readonly"
invisible="not is_separate_body"
force_save="1"
/>
<label for="is_reply_readonly" invisible="not is_separate_body" />
<field
name="is_reply_readonly"
widget="boolean_toggle"
invisible="not is_separate_body"
/>
</xpath>
</field>
</record>
</odoo>