[FIX] website_sale: find abandoned cart using specific delay per website
Before this commit the search for abandoned carts was always using a delay of one hour if no ebsite in the context. After this commit the search for abandoned carts uses the specific cart abandoned delay configured for each website and the related public partner_id. This commit closes #59709, #54932 closes odoo/odoo#61671 Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
This commit is contained in:
committed by
Jeremy Kersten
parent
42965b16cb
commit
a5fc632682
@@ -55,15 +55,19 @@ class SaleOrder(models.Model):
|
||||
order.is_abandoned_cart = False
|
||||
|
||||
def _search_abandoned_cart(self, operator, value):
|
||||
abandoned_delay = self.website_id and self.website_id.cart_abandoned_delay or 1.0
|
||||
abandoned_datetime = fields.Datetime.to_string(datetime.utcnow() - relativedelta(hours=abandoned_delay))
|
||||
abandoned_domain = expression.normalize_domain([
|
||||
('date_order', '<=', abandoned_datetime),
|
||||
('website_id', '!=', False),
|
||||
website_ids = self.env['website'].search_read(fields=['id', 'cart_abandoned_delay', 'partner_id'])
|
||||
deadlines = [[
|
||||
'&', '&',
|
||||
('website_id', '=', website_id['id']),
|
||||
('date_order', '<=', fields.Datetime.to_string(datetime.utcnow() - relativedelta(hours=website_id['cart_abandoned_delay'] or 1.0))),
|
||||
('partner_id', '!=', website_id['partner_id'][0])
|
||||
] for website_id in website_ids]
|
||||
abandoned_domain = [
|
||||
('state', '=', 'draft'),
|
||||
('partner_id', '!=', self.env.ref('base.public_partner').id),
|
||||
('order_line', '!=', False)
|
||||
])
|
||||
]
|
||||
abandoned_domain.extend(expression.OR(deadlines))
|
||||
abandoned_domain = expression.normalize_domain(abandoned_domain)
|
||||
# is_abandoned domain possibilities
|
||||
if (operator not in expression.NEGATIVE_TERM_OPERATORS and value) or (operator in expression.NEGATIVE_TERM_OPERATORS and not value):
|
||||
return abandoned_domain
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
from . import test_customize
|
||||
from . import test_sale_process
|
||||
from . import test_sitemap
|
||||
from . import test_website_sale_cart_abandoned
|
||||
from . import test_website_sale_cart_recovery
|
||||
from . import test_website_sale_mail
|
||||
from . import test_website_sale_pricelist
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from odoo.tests import tagged
|
||||
from odoo.addons.base.tests.common import HttpCaseWithUserPortal
|
||||
|
||||
@tagged('post_install', '-at_install', 'bso')
|
||||
class TestWebsiteSaleCartAbandoned(HttpCaseWithUserPortal):
|
||||
def setUp(self):
|
||||
res = super(TestWebsiteSaleCartAbandoned, self).setUp()
|
||||
now = datetime.utcnow()
|
||||
self.customer = self.env['res.partner'].create({
|
||||
'name': 'a',
|
||||
'email': 'a@example.com',
|
||||
})
|
||||
self.public_partner = self.env['res.partner'].create({
|
||||
'name': 'public',
|
||||
'email': 'public@example.com',
|
||||
})
|
||||
self.public_user = self.env['res.users'].create({
|
||||
'name': 'Foo', 'login': 'foo',
|
||||
'partner_id': self.public_partner.id,
|
||||
})
|
||||
self.website0 = self.env['website'].create({
|
||||
'name': 'web0',
|
||||
'cart_abandoned_delay': 1.0, # 1 hour
|
||||
})
|
||||
self.website1 = self.env['website'].create({
|
||||
'name': 'web1',
|
||||
'cart_abandoned_delay': 0.5, # 30 minutes
|
||||
})
|
||||
self.website2 = self.env['website'].create({
|
||||
'name': 'web2',
|
||||
'cart_abandoned_delay': 24.0, # 1 day
|
||||
'user_id': self.public_user.id, # specific public user
|
||||
})
|
||||
product = self.env['product.product'].create({
|
||||
'name': 'The Product'
|
||||
})
|
||||
add_order_line = [[0, 0, {
|
||||
'name': 'The Product',
|
||||
'product_id': product.id,
|
||||
'product_uom_qty': 1,
|
||||
}]]
|
||||
self.so0before = self.env['sale.order'].create({
|
||||
'partner_id': self.customer.id,
|
||||
'website_id': self.website0.id,
|
||||
'state': 'draft',
|
||||
'date_order': (now - relativedelta(hours=1)) - relativedelta(minutes=1),
|
||||
'order_line': add_order_line,
|
||||
})
|
||||
self.so0after = self.env['sale.order'].create({
|
||||
'partner_id': self.customer.id,
|
||||
'website_id': self.website0.id,
|
||||
'state': 'draft',
|
||||
'date_order': (now - relativedelta(hours=1)) + relativedelta(minutes=1),
|
||||
'order_line': add_order_line,
|
||||
})
|
||||
self.so1before = self.env['sale.order'].create({
|
||||
'partner_id': self.customer.id,
|
||||
'website_id': self.website1.id,
|
||||
'state': 'draft',
|
||||
'date_order': (now - relativedelta(minutes=30)) - relativedelta(minutes=1),
|
||||
'order_line': add_order_line,
|
||||
})
|
||||
self.so1after = self.env['sale.order'].create({
|
||||
'partner_id': self.customer.id,
|
||||
'website_id': self.website1.id,
|
||||
'state': 'draft',
|
||||
'date_order': (now - relativedelta(minutes=30)) + relativedelta(minutes=1),
|
||||
'order_line': add_order_line,
|
||||
})
|
||||
self.so2before = self.env['sale.order'].create({
|
||||
'partner_id': self.customer.id,
|
||||
'website_id': self.website2.id,
|
||||
'state': 'draft',
|
||||
'date_order': (now - relativedelta(hours=24)) - relativedelta(minutes=1),
|
||||
'order_line': add_order_line,
|
||||
})
|
||||
self.so2after = self.env['sale.order'].create({
|
||||
'partner_id': self.customer.id,
|
||||
'website_id': self.website2.id,
|
||||
'state': 'draft',
|
||||
'date_order': (now - relativedelta(hours=24)) + relativedelta(minutes=1),
|
||||
'order_line': add_order_line,
|
||||
})
|
||||
self.so2before_but_public = self.env['sale.order'].create({
|
||||
'partner_id': self.public_partner.id,
|
||||
'website_id': self.website2.id,
|
||||
'state': 'draft',
|
||||
'date_order': (now - relativedelta(hours=24)) - relativedelta(minutes=1),
|
||||
'order_line': add_order_line,
|
||||
})
|
||||
|
||||
# Must behave like so1before because public partner is not the one of website1
|
||||
self.so1before_but_other_public = self.env['sale.order'].create({
|
||||
'partner_id': self.public_partner.id,
|
||||
'website_id': self.website1.id,
|
||||
'state': 'draft',
|
||||
'date_order': (now - relativedelta(minutes=30)) - relativedelta(minutes=1),
|
||||
'order_line': add_order_line,
|
||||
})
|
||||
|
||||
return res
|
||||
|
||||
def test_search_abandoned_cart(self):
|
||||
"""Make sure the search for abandoned carts uses the delay and public partner specified in each website."""
|
||||
SaleOrder = self.env['sale.order']
|
||||
abandoned = SaleOrder.search([('is_abandoned_cart', '=', True)]).ids
|
||||
self.assertTrue(self.so0before.id in abandoned)
|
||||
self.assertTrue(self.so1before.id in abandoned)
|
||||
self.assertTrue(self.so1before_but_other_public.id in abandoned)
|
||||
self.assertTrue(self.so2before.id in abandoned)
|
||||
self.assertFalse(self.so0after.id in abandoned)
|
||||
self.assertFalse(self.so1after.id in abandoned)
|
||||
self.assertFalse(self.so2after.id in abandoned)
|
||||
self.assertFalse(self.so2before_but_public.id in abandoned)
|
||||
|
||||
non_abandoned = SaleOrder.search([('is_abandoned_cart', '=', False)]).ids
|
||||
self.assertFalse(self.so0before.id in non_abandoned)
|
||||
self.assertFalse(self.so1before.id in non_abandoned)
|
||||
self.assertFalse(self.so1before_but_other_public.id in non_abandoned)
|
||||
self.assertFalse(self.so2before.id in non_abandoned)
|
||||
self.assertTrue(self.so0after.id in non_abandoned)
|
||||
self.assertTrue(self.so1after.id in non_abandoned)
|
||||
self.assertTrue(self.so2after.id in non_abandoned)
|
||||
self.assertFalse(self.so2before_but_public.id in abandoned)
|
||||
Reference in New Issue
Block a user