From 88b75f150de28eb03dd364bffa1473cc808eef75 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Thu, 28 Sep 2017 14:17:38 +0200 Subject: [PATCH] [IMP] website_sale_wishlist: Allow public users to wishlist Current behavior before this patch: - Only authenticated users were able to set items as wishlisted. - A product template is displayed as wishlisted if the first variant is so. Desired behavior after this patch: - All users are able to wishlist items. - When a user logs in, his dangling wishlists join him. - A product template is displayed as wishlisted when any of its variants is so. This commit closes #19777 --- addons/website_sale_wishlist/__manifest__.py | 1 + .../website_sale_wishlist/controllers/main.py | 16 +++-- addons/website_sale_wishlist/data/ir_cron.xml | 15 +++++ .../website_sale_wishlist/models/__init__.py | 3 +- .../models/product_wishlist.py | 61 +++++++++++++++++-- .../website_sale_wishlist/models/res_users.py | 24 ++++++++ .../security/ir.model.access.csv | 4 +- .../website_sale_wishlist_security.xml | 2 +- .../views/website_sale_wishlist_template.xml | 10 +-- 9 files changed, 117 insertions(+), 19 deletions(-) create mode 100644 addons/website_sale_wishlist/data/ir_cron.xml create mode 100644 addons/website_sale_wishlist/models/res_users.py 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 @@