diff --git a/addons/website_sale_wishlist/__manifest__.py b/addons/website_sale_wishlist/__manifest__.py
index 6c346f73150..7cf9ecf125b 100644
--- a/addons/website_sale_wishlist/__manifest__.py
+++ b/addons/website_sale_wishlist/__manifest__.py
@@ -9,6 +9,7 @@
'version': '1.0',
'depends': ['website_sale'],
'data': [
+ 'data/ir_cron.xml',
'security/website_sale_wishlist_security.xml',
'security/ir.model.access.csv',
'views/website_sale_wishlist_template.xml',
diff --git a/addons/website_sale_wishlist/controllers/main.py b/addons/website_sale_wishlist/controllers/main.py
index bf2d0014e59..5c8024dc650 100644
--- a/addons/website_sale_wishlist/controllers/main.py
+++ b/addons/website_sale_wishlist/controllers/main.py
@@ -7,26 +7,32 @@ import json
class WebsiteSaleWishlist(WebsiteSale):
- @http.route(['/shop/wishlist/add'], type='json', auth="user", website=True)
+ @http.route(['/shop/wishlist/add'], type='json', auth="public", website=True)
def add_to_wishlist(self, product_id, price=False, **kw):
if not price:
compute_currency, pricelist_context, pl = self._get_compute_currency_and_context()
p = request.env['product.product'].with_context(pricelist_context, display_default_code=False).browse(product_id)
price = p.website_price
+ partner_id = session = False
+ if request.env.user != request.website.user_id:
+ partner_id = request.env.user.partner_id.id
+ else:
+ session = request.session.sid
request.env['product.wishlist']._add_to_wishlist(
- request.env.user.partner_id.id,
pl.id,
pl.currency_id.id,
request.website.id,
price,
- product_id
+ product_id,
+ partner_id,
+ session
)
return True
- @http.route(['/shop/wishlist'], type='http', auth="user", website=True)
+ @http.route(['/shop/wishlist'], type='http', auth="public", website=True)
def get_wishlist(self, count=False, **kw):
- values = request.env['product.wishlist'].with_context(display_default_code=False).search([('partner_id', '=', request.env.user.partner_id.id)])
+ values = request.env['product.wishlist'].with_context(display_default_code=False).current()
if count:
return request.make_response(json.dumps(values.mapped('product_id').ids))
diff --git a/addons/website_sale_wishlist/data/ir_cron.xml b/addons/website_sale_wishlist/data/ir_cron.xml
new file mode 100644
index 00000000000..8d41e39fed1
--- /dev/null
+++ b/addons/website_sale_wishlist/data/ir_cron.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ Wishlisted products garbage collector
+ weeks
+ -1
+
+ _garbage_collector
+ ()
+
+
+
+
diff --git a/addons/website_sale_wishlist/models/__init__.py b/addons/website_sale_wishlist/models/__init__.py
index 634ff473a36..474c0adee9e 100644
--- a/addons/website_sale_wishlist/models/__init__.py
+++ b/addons/website_sale_wishlist/models/__init__.py
@@ -1,2 +1,3 @@
# -*- coding: utf-8 -*-
-from . import product_wishlist
\ No newline at end of file
+from . import product_wishlist
+from . import res_users
diff --git a/addons/website_sale_wishlist/models/product_wishlist.py b/addons/website_sale_wishlist/models/product_wishlist.py
index 4d90d79e076..774b62313d2 100644
--- a/addons/website_sale_wishlist/models/product_wishlist.py
+++ b/addons/website_sale_wishlist/models/product_wishlist.py
@@ -1,18 +1,28 @@
# -*- coding: utf-8 -*-
-
-from odoo import api, fields, models
-
+from odoo import api, fields, http, models
class ProductWishlist(models.Model):
_name = 'product.wishlist'
+ _sql_constrains = [
+ ("session_or_partner_id",
+ "CHECK(session IS NULL != partner_id IS NULL)",
+ "Need a session or partner, but never both."),
+ ("product_unique_session",
+ "UNIQUE(product_id, session)",
+ "Duplicated wishlisted product for this session."),
+ ("product_unique_partner_id",
+ "UNIQUE(product_id, partner_id)",
+ "Duplicated wishlisted product for this partner."),
+ ]
- partner_id = fields.Many2one('res.partner', string='Owner', required=True)
+ partner_id = fields.Many2one('res.partner', string='Owner')
pricelist_id = fields.Many2one('product.pricelist', string='Pricelist', help='Pricelist when added')
currency_id = fields.Many2one('res.currency', related='pricelist_id.currency_id', readonly=True)
website_id = fields.Many2one('website', required=True)
price = fields.Monetary(digits=0, currency_field='currency_id', string='Price', help='Price of the product when it has been added in the wishlist')
price_new = fields.Float(compute='compute_new_price', string='Current price', help='Current price of this product, using same pricelist, ...')
product_id = fields.Many2one('product.product', string='Product', required=True)
+ session = fields.Char(help="Website session identifier where this product was wishlisted.")
active = fields.Boolean(default=True, required=True)
create_date = fields.Datetime('Added Date', readonly=True, required=True)
@@ -23,7 +33,18 @@ class ProductWishlist(models.Model):
wish.price_new = wish.product_id.with_context(pricelist=wish.pricelist_id.id).website_price
@api.model
- def _add_to_wishlist(self, partner_id, pricelist_id, currency_id, website_id, price, product_id):
+ def current(self):
+ """Get all wishlist items that belong to current user or session."""
+ return self.search([
+ "|",
+ ("partner_id", "=", self.env.user.partner_id.id),
+ "&",
+ ("partner_id", "=", False),
+ ("session", "=", self.env.user.current_session),
+ ])
+
+ @api.model
+ def _add_to_wishlist(self, pricelist_id, currency_id, website_id, price, product_id, partner_id=False, session=False):
wish = self.env['product.wishlist'].create({
'partner_id': partner_id,
'pricelist_id': pricelist_id,
@@ -31,9 +52,39 @@ class ProductWishlist(models.Model):
'website_id': website_id,
'price': price,
'product_id': product_id,
+ 'session': session,
})
return wish
+ @api.model
+ def _join_current_user_and_session(self):
+ """Assign all dangling session wishlisted products to user."""
+ session_wishes = self.search([
+ ("session", "=", self.env.user.current_session),
+ ("partner_id", "=", False),
+ ])
+ partner_wishes = self.search([
+ ("partner_id", "=", self.env.user.partner_id.id),
+ ])
+ partner_products = partner_wishes.mapped("product_id")
+ # Remove session products already present for the user
+ duplicated_wishes = session_wishes.filtered(lambda wish: wish.product_id <= partner_products)
+ session_wishes -= duplicated_wishes
+ duplicated_wishes.unlink()
+ # Assign the rest to the user
+ session_wishes.write({
+ "partner_id": self.env.user.partner_id.id,
+ "session": False,
+ })
+
+ @api.model
+ def _garbage_collector(self):
+ """Remove wishlists for unexisting sessions."""
+ self.search([
+ ("session", "not in", http.root.session_store.list()),
+ ("partner_id", "=", False),
+ ]).unlink()
+
class ResPartner(models.Model):
_inherit = 'res.partner'
diff --git a/addons/website_sale_wishlist/models/res_users.py b/addons/website_sale_wishlist/models/res_users.py
new file mode 100644
index 00000000000..489ede52090
--- /dev/null
+++ b/addons/website_sale_wishlist/models/res_users.py
@@ -0,0 +1,24 @@
+from odoo import api, fields, models
+from odoo.http import request
+
+
+class ResUsers(models.Model):
+ _inherit = "res.users"
+
+ current_session = fields.Char(compute="_compute_current_session")
+
+ @api.multi
+ def _compute_current_session(self):
+ """Know current session for this user."""
+ for one in self:
+ try:
+ one.current_session = request.session.sid
+ except (AttributeError, RuntimeError):
+ pass # Unbound session, value is already False, nothing to do
+
+ @api.model
+ def check_credentials(self, password):
+ """Make all this session's wishlists belong to its owner user."""
+ result = super(ResUsers, self).check_credentials(password)
+ self.env["product.wishlist"]._join_current_user_and_session()
+ return result
diff --git a/addons/website_sale_wishlist/security/ir.model.access.csv b/addons/website_sale_wishlist/security/ir.model.access.csv
index f8486a0afcd..f1a57e6ce5a 100644
--- a/addons/website_sale_wishlist/security/ir.model.access.csv
+++ b/addons/website_sale_wishlist/security/ir.model.access.csv
@@ -1,5 +1,5 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_product_wishlist_default,access_product_wishlist_default,model_product_wishlist,,0,0,0,0
-access_product_wishlist_public,access_product_wishlist_public,model_product_wishlist,base.group_public,1,0,0,0
+access_product_wishlist_public,access_product_wishlist_public,model_product_wishlist,base.group_public,1,1,1,1
access_product_wishlist_portal,access_product_wishlist_portal,model_product_wishlist,base.group_portal,1,1,1,1
-access_product_wishlist_user,access_product_wishlist_user,model_product_wishlist,base.group_user,1,1,1,1
\ No newline at end of file
+access_product_wishlist_user,access_product_wishlist_user,model_product_wishlist,base.group_user,1,1,1,1
diff --git a/addons/website_sale_wishlist/security/website_sale_wishlist_security.xml b/addons/website_sale_wishlist/security/website_sale_wishlist_security.xml
index cdca47c4f55..2449c2e4069 100644
--- a/addons/website_sale_wishlist/security/website_sale_wishlist_security.xml
+++ b/addons/website_sale_wishlist/security/website_sale_wishlist_security.xml
@@ -5,7 +5,7 @@
See own Wishlist
- [('partner_id','=', user.partner_id.id)]
+ ["|", ('partner_id','=', user.partner_id.id), "&", ("partner_id", "=", False), ("session", "=", user.current_session)]
diff --git a/addons/website_sale_wishlist/views/website_sale_wishlist_template.xml b/addons/website_sale_wishlist/views/website_sale_wishlist_template.xml
index 19c0dfc1e96..52f691878e5 100644
--- a/addons/website_sale_wishlist/views/website_sale_wishlist_template.xml
+++ b/addons/website_sale_wishlist/views/website_sale_wishlist_template.xml
@@ -10,7 +10,7 @@
-
+
@@ -18,7 +18,7 @@
-
+
@@ -26,9 +26,9 @@