You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

398 lines
18 KiB

# -*- coding: utf-8 -*-
###################################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2022-TODAY Cybrosys Technologies (<https://www.cybrosys.com>).
# Author: Neeraj Krishnan V M (<https://www.cybrosys.com>)
#
# This program is free software: you can modify
# it under the terms of the GNU Affero General Public License (AGPL) as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
###################################################################################
from werkzeug.exceptions import NotFound
from odoo.addons.http_routing.models.ir_http import slug
from odoo.addons.website.controllers.main import QueryURL
from odoo.addons.website_sale.controllers.main import TableCompute
from odoo import http
from ast import literal_eval
from odoo.http import request
from odoo.addons.website.models.ir_http import sitemap_qs2dom
from odoo.addons.website_sale.controllers.main import WebsiteSale
from odoo.osv import expression
from datetime import datetime
from odoo.tools import lazy
class ProductVisibilityCon(WebsiteSale):
def sitemap_shop(env, rule, qs):
if not qs or qs.lower() in '/shop':
yield {'loc': '/shop'}
category = env['product.public.category']
dom = sitemap_qs2dom(qs, '/shop/category', category._rec_name)
dom += env['website'].get_current_website().website_domain()
for cat in category.search(dom):
loc = '/shop/category/%s' % slug(cat)
if not qs or qs.lower() in loc:
yield {'loc': loc}
def reset_domain(self, search, categories, available_products,
attrib_values, search_in_description=True):
'''
Function returns a domain consist of filter conditions
:param search: search variable
:param categories: list of category available
:param available_products: list of available product ids from product.template
:param attrib_values:product attiribute values
:param search_in_description: boolean filed showing there is search variable exist or not'''
domains = [request.website.sale_product_domain()]
if search:
for srch in search.split(" "):
subdomains = [
[('name', 'ilike', srch)],
[('product_variant_ids.default_code', 'ilike', srch)]
]
if search_in_description:
subdomains.append([('description', 'ilike', srch)])
subdomains.append([('description_sale', 'ilike', srch)])
domains.append(expression.OR(subdomains))
if available_products:
domains.append([('id', 'in', available_products.ids)])
if categories:
domains.append([('public_categ_ids', 'child_of', categories.ids)])
if attrib_values:
print("hello world....")
# attrib = None
# ids = []
# print("hello...", ids)
# for value in attrib_values:
# if not attrib:
# attrib = value[0]
# ids.append(value[1])
# elif value[0] == attrib:
# ids.append(value[1])
# else:
# domains.append([('attribute_line_ids.value_ids', 'in', ids)])
# attrib = value[0]
# ids = [value[1]]
# if attrib:
# domains.append([('attribute_line_ids.value_ids', 'in', ids)])
return expression.AND(domains)
@http.route([
'''/shop''',
'''/shop/page/<int:page>''',
'''/shop/category/<model("product.public.category"):category>''',
'''/shop/category/<model("product.public.category"):category>/page/<int:page>'''
], type='http', auth="public", website=True, sitemap=sitemap_shop)
def shop(self, page=0, category=None, search='', ppg=False, **post):
''''Override shop function.'''
available_categ = available_products = ''
user = request.env['res.users'].sudo().search(
[('id', '=', request.env.user.id)])
if not user:
mode = request.env['ir.config_parameter'].sudo().get_param(
'filter_mode')
products = literal_eval(
request.env['ir.config_parameter'].sudo().get_param(
'website_product_visibility.available_product_ids',
'False'))
if mode == 'product_only':
available_products = request.env['product.template'].search(
[('id', 'in', products)])
cat = literal_eval(
request.env['ir.config_parameter'].sudo().get_param(
'website_product_visibility.available_cat_ids', 'False'))
available_categ = request.env['product.public.category'].search(
[('id', 'in', cat)])
else:
partner = request.env['res.partner'].sudo().search(
[('id', '=', user.partner_id.id)])
mode = partner.filter_mode
if mode == 'product_only':
available_products = self.availavle_products()
available_categ = partner.website_available_cat_ids
Category_avail = []
Category = request.env['product.public.category']
for ids in available_categ:
if not ids.parent_id.id in available_categ.ids:
Category_avail.append(ids.id)
categ = request.env['product.public.category'].search(
[('id', 'in', Category_avail)])
if mode == 'product_only':
categ = Category.search([('parent_id', '=', False), (
'product_tmpl_ids', 'in', available_products.ids)])
# supering shop***
if not available_categ and not available_products:
return super(ProductVisibilityCon, self).shop(page, category,
search, ppg, **post)
add_qty = int(post.get('add_qty', 1))
if category:
category = Category.search([('id', '=', int(category))], limit=1)
if not category or not category.can_access_from_current_website():
raise NotFound()
else:
category = Category
website = request.env['website'].get_current_website()
if ppg:
try:
ppg = int(ppg)
post['ppg'] = ppg
except ValueError:
ppg = False
if not ppg:
ppg = request.env['website'].get_current_website().shop_ppg or 20
ppr = request.env['website'].get_current_website().shop_ppr or 4
attrib_list = request.httprequest.args.getlist('attrib')
attrib_values = [[int(x) for x in v.split("-")] for v in attrib_list if
v]
attributes_ids = {v[0] for v in attrib_values}
attrib_set = {v[1] for v in attrib_values}
domain = self._get_search_domain(search, category, attrib_values)
Product = request.env['product.template'].with_context(bin_size=True)
if available_products:
domain_pro = self.reset_domain(search, category, available_products,
attrib_values)
Product = Product.search(domain_pro)
keep = QueryURL('/shop', category=category and int(category),
search=search, attrib=attrib_list,
order=post.get('order'))
# pricelist_context, pricelist = self._get_pricelist_context()
# request.context = dict(request.context, pricelist=pricelist.id, partner=request.env.user.partner_id)
now = datetime.timestamp(datetime.now())
pricelist = request.env['product.pricelist'].browse(
request.session.get('website_sale_current_pl'))
if not pricelist or request.session.get('website_sale_pricelist_time',
0) < now - 60 * 60: # test: 1 hour in session
pricelist = website.get_current_pricelist()
request.session['website_sale_pricelist_time'] = now
request.session['website_sale_current_pl'] = pricelist.id
request.update_context(pricelist=pricelist.id,
partner=request.env.user.partner_id)
url = "/shop"
if search:
post["search"] = search
if attrib_list:
post['attrib'] = attrib_list
if not category:
domain = self.reset_domain(search, available_categ,
available_products, attrib_values)
search_product = Product.search(domain)
website_domain = request.website.website_domain()
categs_domain = [('parent_id', '=', False), (
'product_tmpl_ids', 'in', search_product.ids)] + website_domain
if search:
search_categories = Category.search(
[('product_tmpl_ids', 'in',
search_product.ids)] + website_domain).parents_and_self
categs_domain.append(('id', 'in', search_categories.ids))
else:
search_categories = available_categ
if category:
url = "/shop/category/%s" % slug(category)
product_count = len(search_product)
pager = request.website.pager(url=url, total=product_count, page=page,
step=ppg, scope=7, url_args=post)
products = Product.search(domain, limit=ppg, offset=pager['offset'],
order=self._get_search_order(post))
if not category:
if available_products:
products = Product.search(domain_pro, limit=ppg,
offset=pager['offset'],
order=self._get_search_order(post))
else:
products = Product.search(domain, limit=ppg,
offset=pager['offset'],
order=self._get_search_order(post))
else:
if available_products:
products = Product.search(domain_pro, limit=ppg,
offset=pager['offset'],
order=self._get_search_order(post))
else:
products = Product.search(domain, limit=ppg,
offset=pager['offset'],
order=self._get_search_order(post))
ProductAttribute = request.env['product.attribute']
if products:
# get all products without limit
attributes = ProductAttribute.search(
[('product_tmpl_ids', 'in', search_product.ids)])
else:
attributes = ProductAttribute.browse(attributes_ids)
layout_mode = request.session.get('website_sale_shop_layout_mode')
if not layout_mode:
if request.website.viewref(
'website_sale.products_list_view').active:
layout_mode = 'list'
else:
layout_mode = 'grid'
request.session['website_sale_shop_layout_mode'] = layout_mode
products_prices = lazy(lambda: products._get_sales_prices(pricelist))
values = {
'search': search,
'category': category,
'attrib_values': attrib_values,
'attrib_set': attrib_set,
'pager': pager,
'pricelist': pricelist,
'add_qty': add_qty,
'products': products,
'search_count': product_count, # common for all searchbox
'bins': TableCompute().process(products, ppg, ppr),
'ppg': ppg,
'ppr': ppr,
'categories': categ,
'attributes': attributes,
'keep': keep,
'search_categories_ids': categ.ids,
'layout_mode': layout_mode,
'products_prices': products_prices,
'get_product_prices': lambda product: lazy(
lambda: products_prices[product.id]),
}
if category:
values['main_object'] = category
return request.render("website_sale.products", values)
def availavle_products(self):
''''Returns the available product (product.template) ids'''
user = request.env['res.users'].sudo().search(
[('id', '=', request.env.user.id)])
partner = request.env['res.partner'].sudo().search(
[('id', '=', user.partner_id.id)])
return partner.website_available_product_ids
# --------------------------------------------------------------------------
# Products Search Bar
# --------------------------------------------------------------------------
@http.route('/shop/products/autocomplete', type='json', auth='public',
website=True)
def products_autocomplete(self, term, options={}, **kwargs):
"""
Returns list of products according to the term and product options
Params:
term (str): search term written by the user
options (dict)
- 'limit' (int), default to 5: number of products to consider
- 'display_description' (bool), default to True
- 'display_price' (bool), default to True
- 'order' (str)
- 'max_nb_chars' (int): max number of characters for the
description if returned
Returns:
dict (or False if no result)
- 'products' (list): products (only their needed field values)
note: the prices will be strings properly formatted and
already containing the currency
- 'products_count' (int): the number of products in the database
that matched the search query
"""
user = request.env['res.users'].sudo().search(
[('id', '=', request.env.user.id)])
available_categ = available_products = ''
if not user:
mode = request.env['ir.config_parameter'].sudo().get_param(
'filter_mode')
products = literal_eval(
request.env['ir.config_parameter'].sudo().get_param(
'website_product_visibility.available_product_ids',
'False'))
if mode == 'product_only':
available_products = request.env['product.template'].search(
[('id', 'in', products)])
cat = literal_eval(
request.env['ir.config_parameter'].sudo().get_param(
'website_product_visibility.available_cat_ids',
'False'))
available_categ = request.env['product.public.category'].search(
[('id', 'in', cat)])
else:
partner = request.env['res.partner'].sudo().search(
[('id', '=', user.partner_id.id)])
mode = partner.filter_mode
if mode != 'categ_only':
available_products = self.availavle_products()
available_categ = partner.website_available_cat_ids
ProductTemplate = request.env['product.template']
display_description = options.get('display_description', True)
display_price = options.get('display_price', True)
order = self._get_search_order(options)
max_nb_chars = options.get('max_nb_chars', 999)
category = options.get('category')
attrib_values = options.get('attrib_values')
if not available_products and not available_categ:
domain = self._get_search_domain(term, category, attrib_values,
display_description)
else:
domain = self.reset_domain(term, available_categ,
available_products, attrib_values,
display_description)
products = ProductTemplate.search(
domain,
limit=min(20, options.get('limit', 5)),
order=order
)
fields = ['id', 'name', 'website_url']
if display_description:
fields.append('description_sale')
res = {
'products': products.read(fields),
'products_count': ProductTemplate.search_count(domain),
}
if display_description:
for res_product in res['products']:
desc = res_product['description_sale']
if desc and len(desc) > max_nb_chars:
res_product['description_sale'] = "%s..." % desc[:(
max_nb_chars - 3)]
if display_price:
FieldMonetary = request.env['ir.qweb.field.monetary']
monetary_options = {
'display_currency': request.website.get_current_pricelist().currency_id,
}
for res_product, product in zip(res['products'], products):
combination_info = product._get_combination_info(
only_template=True)
res_product.update(combination_info)
res_product['list_price'] = FieldMonetary.value_to_html(
res_product['list_price'], monetary_options)
res_product['price'] = FieldMonetary.value_to_html(
res_product['price'], monetary_options)
return res