Skip to content

Commit 969f1b1

Browse files
committed
[IMP] website_sale: automatic rating request
Add a new rating email template and the _get_rating_request_template method to fetch it. Implement a scheduled cron _cron_send_order_rating_emails to automatically send feedback requests for orders confirmed a configurable number of days ago. Include settings to enable the feature, set the delay, and select the email template, integrating these with website configuration. The email sending logic respects user settings and prevents duplicate emails. task-5129654
1 parent b4b7704 commit 969f1b1

File tree

5 files changed

+131
-1
lines changed

5 files changed

+131
-1
lines changed

addons/website_sale/data/ir_cron_data.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,12 @@
1010
<field name="state">code</field>
1111
</record>
1212

13+
<record id="ir_cron_send_order_rating_emails" model="ir.cron">
14+
<field name="name">eCommerce: send order rating request emails</field>
15+
<field name="interval_number">1</field>
16+
<field name="interval_type">days</field>
17+
<field name="model_id" ref="sale.model_sale_order"/>
18+
<field name="code">model._cron_send_order_rating_emails()</field>
19+
<field name="state">code</field>
20+
</record>
1321
</odoo>

addons/website_sale/data/mail_template_data.xml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,5 +210,60 @@
210210
</field>
211211
<field name="auto_delete" eval="False"/>
212212
</record>
213+
<record id="mail_template_sale_order_rating" model="mail.template">
214+
<field name="name">Ecommerce: Order Rating Request</field>
215+
<field name="model_id" ref="sale.model_sale_order"/>
216+
<field name="subject">Review your recent order!</field>
217+
<field name="email_from">{{ (object.user_id.email_formatted or object.company_id.email_formatted or user.email_formatted) }}</field>
218+
<field name="partner_to" eval="False"/>
219+
<field name="use_default_to" eval="True"/>
220+
<field name="description">Sent to customers to request feedback on their order</field>
221+
<field name="email_layout_xmlid">mail.mail_notification_light</field>
222+
<field name="body_html" type="html">
223+
<div style="margin: 0px; padding: 0px;">
224+
<p style="margin: 0px; padding: 0px; font-size: 12px;">
225+
Hello <t t-out="object.partner_id.name"/>,
226+
<br/>
227+
Take a minute to rate your order!
228+
<br/>
229+
<t t-if="not is_html_empty(object.user_id.signature)">
230+
<div>--<br/><t t-out="object.user_id.signature"/></div>
231+
</t>
232+
<br/>
233+
<t t-foreach="object.order_line.filtered(lambda l: l._is_sellable())" t-as="line">
234+
<t t-set="product" t-value="line.product_id"/>
235+
<table width="35%" style="color: #454748; font-size: 12px; border-collapse: collapse; margin-bottom: 15px;">
236+
<tr>
237+
<td style="width: 100px; vertical-align: top;">
238+
<img
239+
t-attf-src="/web/image/product.product/{{ product.id }}/image_128"
240+
t-attf-style="width: 64px; height: {{object.website_id and object.website_id._get_product_image_ratio_height() or '64px'}}; object-fit: cover; object-position: center;"
241+
alt="Product image"
242+
/>
243+
</td>
244+
<td style="padding-left: 10px; vertical-align: top; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;">
245+
<div style="font-weight: bold; margin-bottom: 5px;">
246+
<t t-out="product.name"/>
247+
</div>
248+
<div style="font-size: 11px; color: #666;">
249+
<t t-out="product.description_sale or ''"/>
250+
</div>
251+
</td>
252+
<td style="width: 120px; padding-left: 10px; vertical-align: middle; text-align: center;">
253+
<a t-att-href="product.website_absolute_url + '#o_product_page_reviews'"
254+
style="background-color:#875A7B;color:white;padding:10px 15px;text-decoration:none;border-radius:4px;display:inline-block;font-weight:bold;"
255+
target="_blank">
256+
Review Now
257+
</a>
258+
</td>
259+
</tr>
260+
</table>
261+
</t>
262+
</p>
263+
</div>
264+
</field>
265+
<field name="report_template_ids" eval="[]"/>
266+
<field name="auto_delete" eval="True"/>
267+
</record>
213268
</data>
214269
</odoo>

addons/website_sale/models/res_config_settings.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,21 @@ class ResConfigSettings(models.TransientModel):
6767
confirmation_email_template_id = fields.Many2one(
6868
related='website_id.confirmation_email_template_id', readonly=False
6969
)
70+
send_order_rating_emails = fields.Boolean(
71+
string="Request ratings",
72+
config_parameter='website_sale.send_order_rating_emails',
73+
)
74+
rating_email_days = fields.Integer(
75+
string="Days After Order to Send Rating Email",
76+
default=5,
77+
config_parameter='website_sale.rating_email_days',
78+
)
79+
rating_email_template_id = fields.Many2one(
80+
string="Email",
81+
comodel_name='mail.template',
82+
default=lambda self: self.env.ref('website_sale.mail_template_sale_order_rating', raise_if_not_found=False),
83+
config_parameter='website_sale.rating_email_template_id',
84+
)
7085

7186
# Additional settings
7287
account_on_checkout = fields.Selection(
@@ -120,6 +135,9 @@ def set_values(self):
120135
)
121136
):
122137
website._populate_product_feeds()
138+
view = self.env['ir.ui.view'].search([('key', '=', 'website_sale.product_comment')], limit=1)
139+
if view and self.send_order_rating_emails:
140+
view.active = True
123141

124142
# === ACTION METHODS === #
125143

addons/website_sale/models/sale_order.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Part of Odoo. See LICENSE file for full copyright and licensing details.
22

33
import random
4-
from datetime import datetime
4+
from datetime import datetime, timedelta
55

66
from dateutil.relativedelta import relativedelta
77

@@ -46,6 +46,7 @@ class SaleOrder(models.Model):
4646
is_abandoned_cart = fields.Boolean(
4747
string="Abandoned Cart", compute='_compute_abandoned_cart', search='_search_abandoned_cart',
4848
)
49+
rating_email_sent = fields.Boolean(string="Rating email already sent")
4950

5051
#=== COMPUTE METHODS ===#
5152

@@ -846,6 +847,41 @@ def _get_delivery_methods(self):
846847
*self.env['delivery.carrier']._check_company_domain(self.company_id),
847848
]).filtered(lambda carrier: carrier._is_available_for_order(self))
848849

850+
@api.model
851+
def _cron_send_order_rating_emails(self):
852+
"""Send rating request emails to customers a few days after order."""
853+
send_order_rating_emails = self.env['ir.config_parameter'].sudo().get_bool('website_sale.send_order_rating_emails')
854+
if not send_order_rating_emails:
855+
return
856+
857+
days = max(0, self.env['ir.config_parameter'].sudo().get_int('website_sale.rating_email_days'))
858+
date_limit = fields.Datetime.now() - timedelta(days=days)
859+
rating_orders = self.search([
860+
('state', '=', 'sale'),
861+
('date_order', '>=', date_limit.replace(hour=0, minute=0, second=0)),
862+
('date_order', '<=', date_limit.replace(hour=23, minute=59, second=59)),
863+
('website_id', '!=', False),
864+
('rating_email_sent', '=', False),
865+
])
866+
867+
for order in rating_orders:
868+
mail_template = order._get_rating_request_template()
869+
if mail_template:
870+
mail_template.send_mail(order.id)
871+
order.rating_email_sent = True
872+
873+
def _get_rating_request_template(self):
874+
self.ensure_one()
875+
876+
rating_email_template_id = self.env['ir.config_parameter'].sudo().get_int(
877+
'website_sale.rating_email_template_id'
878+
)
879+
rating_email_template = self.env['mail.template'].browse(rating_email_template_id).exists()
880+
if rating_email_template:
881+
return rating_email_template
882+
883+
return self.env.ref('website_sale.mail_template_sale_order_rating', raise_if_not_found=False)
884+
849885
#=== TOOLING ===#
850886

851887
def _is_anonymous_cart(self):

addons/website_sale/views/res_config_settings_views.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,19 @@
216216
<button type="object" name="action_open_abandoned_cart_mail_template" string="Customize Abandoned Email Template" class="btn-link" icon="oi-arrow-right"/>
217217
</div>
218218
</setting>
219+
<setting
220+
id="send_order_rating_emails_setting"
221+
help="Send a rating request for each order"
222+
>
223+
<field name="send_order_rating_emails"/>
224+
<div invisible="not send_order_rating_emails" class="mt-1">
225+
Send <field name="rating_email_days" class="oe_inline" /> days after order confirmation
226+
</div>
227+
<div invisible="not send_order_rating_emails" class="mt-2">
228+
<label for="rating_email_template_id" class="o_light_label me-2"/>
229+
<field name="rating_email_template_id" class="oe_inline"/>
230+
</div>
231+
</setting>
219232
<setting string="Orders Assignment" help="Assignment of online orders">
220233
<div class="content-group">
221234
<div class="row mt16">

0 commit comments

Comments
 (0)