[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:
committed by
Jeremy Kersten
parent
4bd8e3e2ed
commit
88b75f150d
@@ -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
|
||||
|
||||
|
@@ -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), "&", ("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 & 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 & 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>
|
||||
|
||||
Reference in New Issue
Block a user