[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
This commit is contained in:
Jairo Llopis
2017-09-30 12:21:27 +02:00
committed by Jeremy Kersten
parent 4bd8e3e2ed
commit 88b75f150d
9 changed files with 117 additions and 19 deletions
@@ -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',
@@ -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))
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="garbage_collector" model="ir.cron">
<field name="name">Wishlisted products garbage collector</field>
<field name="interval_type">weeks</field>
<field name="numbercall">-1</field>
<field name="model_id" ref="model_product_wishlist"/>
<field name="function">_garbage_collector</field>
<field name="args">()</field>
</record>
</data>
</odoo>
@@ -1,2 +1,3 @@
# -*- coding: utf-8 -*-
from . import product_wishlist
from . import product_wishlist
from . import res_users
@@ -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'
@@ -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
@@ -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
access_product_wishlist_user,access_product_wishlist_user,model_product_wishlist,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_product_wishlist_default access_product_wishlist_default model_product_wishlist 0 0 0 0
3 access_product_wishlist_public access_product_wishlist_public model_product_wishlist base.group_public 1 0 1 0 1 0 1
4 access_product_wishlist_portal access_product_wishlist_portal model_product_wishlist base.group_portal 1 1 1 1
5 access_product_wishlist_user access_product_wishlist_user model_product_wishlist base.group_user 1 1 1 1
@@ -5,7 +5,7 @@
<record id="product_wishlist_rule" model="ir.rule">
<field name="name">See own Wishlist</field>
<field name="model_id" ref="model_product_wishlist"/>
<field name="domain_force">[('partner_id','=', user.partner_id.id)]</field>
<field name="domain_force">["|", ('partner_id','=', user.partner_id.id), "&amp;", ("partner_id", "=", False), ("session", "=", user.current_session)]</field>
<field name="groups" eval="[(4, ref('base.group_portal')),(4, ref('base.group_public')), (4, ref('base.group_user'))]"/>
</record>
@@ -10,7 +10,7 @@
<template id="add_to_wishlist" inherit_id="website_sale.products_item" active="True" customize_show="True" name="Wishlist" priority="20">
<xpath expr="//div[hasclass('product_price')]" position="inside">
<t t-set="in_wish" t-value="product.product_variant_ids[0] in request.env.user.partner_id.wishlist_ids.mapped('product_id')"/>
<t t-set="in_wish" t-value="product.product_variant_ids &amp; request.env['product.wishlist'].current().mapped('product_id')"/>
<a class="btn btn-default btn-xs o_add_wishlist" t-att-disabled='in_wish or None' title="Add to Wishlist" t-att-data-product-product-id="product.product_variant_ids[0].id" data-action="o_wishlist"><span class="fa fa-heart"></span></a>
</xpath>
</template>
@@ -18,7 +18,7 @@
<template id="product_add_to_wishlist" name='Add to wishlist in product page' inherit_id="website_sale.product" priority="20">
<xpath expr="//a[@id='add_to_cart']" position="after">
<t t-if="product.env.ref('website_sale_wishlist.add_to_wishlist').active">
<t t-set="in_wish" t-value="product.product_variant_ids[0] in request.env.user.partner_id.wishlist_ids.mapped('product_id')"/>
<t t-set="in_wish" t-value="product.product_variant_ids &amp; request.env['product.wishlist'].current().mapped('product_id')"/>
<a class="btn btn-default btn-lg mt8 o_add_wishlist_dyn" t-att-disabled='in_wish or None' title="Add to Wishlist" t-att-data-product-product-id="product.product_variant_ids[0].id" data-action="o_wishlist"><span class="fa fa-heart"></span></a>
</t>
</xpath>
@@ -26,9 +26,9 @@
<template id="header" inherit_id="website.layout" name="Header Shop Wishlist Link">
<xpath expr="//header//ul[@id='top_menu']/li[@id='my_cart']" position="after">
<t t-if="(request.env.user.id != request.website.user_id.id) and request.env.ref('website_sale_wishlist.add_to_wishlist').active">
<t t-set='wishcount' t-value="request.env['product.wishlist'].search_count([('partner_id', '=', request.env.user.partner_id.id)])"/>
<li id="my_wish" t-att-style="not wishcount and 'display:none'">
<t t-if="request.env.ref('website_sale_wishlist.add_to_wishlist').active">
<t t-set='wishcount' t-value="len(request.env['product.wishlist'].current())"/>
<li id="my_wish" t-att-class="not wishcount and 'hidden'">
<a href="/shop/wishlist">
<i class="fa fa-heart"></i>
Wishlist <sup t-attf-class="my_wish_quantity o_animate_blink label label-primary"><t t-esc='wishcount'/></sup>