Browse Source

Aug 25 [FIX] : Bug Fixed 'product_visibility_website'

pull/277/head
AjmalCybro 2 years ago
parent
commit
3f7ed8b388
  1. 56
      product_visibility_website/README.rst
  2. 9
      product_visibility_website/__init__.py
  3. 17
      product_visibility_website/__manifest__.py
  4. 9
      product_visibility_website/controllers/__init__.py
  5. 189
      product_visibility_website/controllers/main.py
  6. 7
      product_visibility_website/doc/RELEASE_NOTES.md
  7. 9
      product_visibility_website/models/__init__.py
  8. 70
      product_visibility_website/models/website_product_visibility.py
  9. 5
      product_visibility_website/static/description/index.html
  10. 9
      product_visibility_website/views/website_product_visibility.xml

56
product_visibility_website/README.rst

@ -1,36 +1,52 @@
============================ .. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
Website Product Visibility Website Product Visibility
============================ ============================
This module helps you to make visible only the filtered products and This module helps you to make visible only the filtered products and
product categories for a logged in and logged out users/visitors.Also, product categories for a logged in and logged out users/visitors.Also,
it enables the user to search products and product categories only from it enables the user to search products and product categories only from
those available products and categories. . those available products and categories.
Tech
==== Configuration
* [Python] - Models =============
* [XML] - Odoo views No additional configurations needed.
Installation Company
============ -------
- www.odoo.com/documentation/16.0/setup/install.html * `Cybrosys Techno Solutions <https://cybrosys.com/>`__
- Install our custom addon
License
Developer: Shijin V @Cybrosys -------
General Public License, Version 3 (AGPL v3).
(https://www.gnu.org/licenses/agpl-3.0-standalone.html)
Credits
-------
Developers: Version 16 - Shijin V @Cybrosys
V14: Muhammed Nafih @Cybrosys V14: Muhammed Nafih @Cybrosys
V15: Neeraj @Cybrosys V15: Neeraj @Cybrosys
V16: Saneen K @cybrosys
Contacts
--------
* Mail Contact : odoo@cybrosys.com
* Website : https://cybrosys.com
Bug Tracker Bug Tracker
=========== -----------
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported.
Credits
=======
* Cybrosys Techno Solutions <https://www.cybrosys.com>
Maintainer Maintainer
---------- ==========
.. image:: https://cybrosys.com/images/logo.png
:target: https://cybrosys.com
This module is maintained by Cybrosys Technologies. This module is maintained by Cybrosys Technologies.
For support and more information, please visit https://www.cybrosys.com. For support and more information, please visit `Our Website <https://cybrosys.com/>`__
Further information
===================
HTML Description: `<static/description/index.html>`__

9
product_visibility_website/__init__.py

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################### ################################################################################
# #
# Cybrosys Technologies Pvt. Ltd. # Cybrosys Technologies Pvt. Ltd.
# #
# Copyright (C) 2019-TODAY Cybrosys Technologies (<https://www.cybrosys.com>). # Copyright (C) 2022-TODAY Cybrosys Technologies (<https://www.cybrosys.com>)
# Author: Shijin V (<https://www.cybrosys.com>) # Author: Neeraj Krishnan V M, Saneen K (<https://www.cybrosys.com>)
# #
# This program is free software: you can modify # This program is free software: you can modify
# it under the terms of the GNU Affero General Public License (AGPL) as # it under the terms of the GNU Affero General Public License (AGPL) as
@ -19,7 +19,6 @@
# You should have received a copy of the GNU Affero General Public License # 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/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
# #
################################################################################### ################################################################################
from . import controllers from . import controllers
from . import models from . import models

17
product_visibility_website/__manifest__.py

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################### ################################################################################
# #
# Cybrosys Technologies Pvt. Ltd. # Cybrosys Technologies Pvt. Ltd.
# #
# Copyright (C) 2022-TODAY Cybrosys Technologies (<https://www.cybrosys.com>). # Copyright (C) 2022-TODAY Cybrosys Technologies (<https://www.cybrosys.com>)
# Author: Neeraj Krishnan V M (<https://www.cybrosys.com>) # Author: Neeraj Krishnan V M, Saneen K (<https://www.cybrosys.com>)
# #
# This program is free software: you can modify # This program is free software: you can modify
# it under the terms of the GNU Affero General Public License (AGPL) as # it under the terms of the GNU Affero General Public License (AGPL) as
@ -19,18 +19,17 @@
# You should have received a copy of the GNU Affero General Public License # 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/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
# #
################################################################################### ################################################################################
{ {
'name': 'Website Product Visibility', 'name': 'Website Product Visibility',
'version': '16.0.1.1.0',
'category': 'Website',
'summary': 'Website Product visibility for Users', 'summary': 'Website Product visibility for Users',
'version': '16.0.1.0.0',
'description': """Website Product visibility for Users""", 'description': """Website Product visibility for Users""",
'author': 'Cybrosys Techno Solution', 'author': 'Cybrosys Techno Solution',
'maintainer': 'Cybrosys Techno Solutions',
'company': 'Cybrosys Techno Solutions', 'company': 'Cybrosys Techno Solutions',
'maintainer': 'Cybrosys Techno Solutions',
'website': 'https://www.cybrosys.com', 'website': 'https://www.cybrosys.com',
'category': 'Website',
'depends': ['contacts', 'website_sale','website'], 'depends': ['contacts', 'website_sale','website'],
'data': [ 'data': [
'views/website_product_visibility.xml', 'views/website_product_visibility.xml',
@ -38,6 +37,6 @@
'images': ['static/description/banner.png'], 'images': ['static/description/banner.png'],
'license': 'AGPL-3', 'license': 'AGPL-3',
'installable': True, 'installable': True,
'application': False,
'auto_install': False, 'auto_install': False,
'application': False,
} }

9
product_visibility_website/controllers/__init__.py

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################### ################################################################################
# #
# Cybrosys Technologies Pvt. Ltd. # Cybrosys Technologies Pvt. Ltd.
# #
# Copyright (C) 2022-TODAY Cybrosys Technologies (<https://www.cybrosys.com>). # Copyright (C) 2022-TODAY Cybrosys Technologies (<https://www.cybrosys.com>)
# Author: Neeraj Krishnan V M (<https://www.cybrosys.com>) # Author: Neeraj Krishnan V M, Saneen K (<https://www.cybrosys.com>)
# #
# This program is free software: you can modify # This program is free software: you can modify
# it under the terms of the GNU Affero General Public License (AGPL) as # it under the terms of the GNU Affero General Public License (AGPL) as
@ -19,6 +19,5 @@
# You should have received a copy of the GNU Affero General Public License # 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/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
# #
################################################################################### ###############################################################################
from . import main from . import main

189
product_visibility_website/controllers/main.py

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################### ################################################################################
# #
# Cybrosys Technologies Pvt. Ltd. # Cybrosys Technologies Pvt. Ltd.
# #
# Copyright (C) 2022-TODAY Cybrosys Technologies (<https://www.cybrosys.com>). # Copyright (C) 2022-TODAY Cybrosys Technologies (<https://www.cybrosys.com>)
# Author: Neeraj Krishnan V M (<https://www.cybrosys.com>) # Author: Neeraj Krishnan V M , Saneen K(<https://www.cybrosys.com>)
# #
# This program is free software: you can modify # This program is free software: you can modify
# it under the terms of the GNU Affero General Public License (AGPL) as # it under the terms of the GNU Affero General Public License (AGPL) as
@ -19,18 +19,16 @@
# You should have received a copy of the GNU Affero General Public License # 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/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
# #
################################################################################### ###############################################################################
from werkzeug.exceptions import NotFound from werkzeug.exceptions import NotFound
from odoo.addons.http_routing.models.ir_http import slug from odoo.addons.http_routing.models.ir_http import slug
from odoo.addons.website.controllers.main import QueryURL from odoo.addons.website.controllers.main import QueryURL
from odoo.addons.website_sale.controllers.main import TableCompute from odoo.addons.website_sale.controllers.main import TableCompute
from odoo import http from odoo import fields, http, tools
from ast import literal_eval from ast import literal_eval
from odoo.http import request from odoo.http import request
from odoo.addons.website.models.ir_http import sitemap_qs2dom from odoo.addons.website.models.ir_http import sitemap_qs2dom
from odoo.addons.website_sale.controllers.main import WebsiteSale from odoo.addons.website_sale.controllers.main import WebsiteSale
from odoo.osv import expression from odoo.osv import expression
from datetime import datetime from datetime import datetime
from odoo.tools import lazy from odoo.tools import lazy
@ -51,21 +49,22 @@ class ProductVisibilityCon(WebsiteSale):
def reset_domain(self, search, categories, available_products, def reset_domain(self, search, categories, available_products,
attrib_values, search_in_description=True): attrib_values, search_in_description=True):
''' """
Function returns a domain consist of filter conditions Function returns a domain consist of filter conditions
:param search: search variable :param search: search variable
:param categories: list of category available :param categories: list of category available
:param available_products: list of available product ids from product.template :param available_products: list of available product ids from
product.template
:param attrib_values:product attiribute values :param attrib_values:product attiribute values
:param search_in_description: boolean filed showing there is search variable exist or not''' :param search_in_description: boolean filed showing there is search
variable exist or not"""
domains = [request.website.sale_product_domain()] domains = [request.website.sale_product_domain()]
if search: if search:
for srch in search.split(" "): for srch in search.split(" "):
subdomains = [ subdomains = [
[('name', 'ilike', srch)], [('name', 'ilike', srch)],
[('product_variant_ids.default_code', 'ilike', srch)] [('product_variant_ids.default_code', 'ilike', srch)]]
]
if search_in_description: if search_in_description:
subdomains.append([('description', 'ilike', srch)]) subdomains.append([('description', 'ilike', srch)])
subdomains.append([('description_sale', 'ilike', srch)]) subdomains.append([('description_sale', 'ilike', srch)])
@ -74,34 +73,16 @@ class ProductVisibilityCon(WebsiteSale):
domains.append([('id', 'in', available_products.ids)]) domains.append([('id', 'in', available_products.ids)])
if categories: if categories:
domains.append([('public_categ_ids', 'child_of', categories.ids)]) 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) return expression.AND(domains)
@http.route([ @http.route([
'''/shop''', '/shop',
'''/shop/page/<int:page>''', '/shop/page/<int:page>',
'''/shop/category/<model("product.public.category"):category>''', '/shop/category/<model("product.public.category"):category>',
'''/shop/category/<model("product.public.category"):category>/page/<int:page>''' '/shop/category/<model("product.public.category"):category>/page/<int:page>',
], type='http', auth="public", website=True, sitemap=sitemap_shop) ], type='http', auth="public", website=True, sitemap=sitemap_shop)
def shop(self, page=0, category=None, search='', ppg=False, **post): def shop(self, page=0, category=None, search='', min_price=0.0,
''''Override shop function.''' max_price=0.0, ppg=False, **post):
available_categ = available_products = '' available_categ = available_products = ''
user = request.env['res.users'].sudo().search( user = request.env['res.users'].sudo().search(
[('id', '=', request.env.user.id)]) [('id', '=', request.env.user.id)])
@ -125,12 +106,10 @@ class ProductVisibilityCon(WebsiteSale):
[('id', '=', user.partner_id.id)]) [('id', '=', user.partner_id.id)])
mode = partner.filter_mode mode = partner.filter_mode
if mode == 'product_only': if mode == 'product_only':
available_products = self.availavle_products() available_products = self.available_products()
available_categ = partner.website_available_cat_ids available_categ = partner.website_available_cat_ids
Category_avail = [] Category_avail = []
Category = request.env['product.public.category'] Category = request.env['product.public.category']
for ids in available_categ: for ids in available_categ:
if not ids.parent_id.id in available_categ.ids: if not ids.parent_id.id in available_categ.ids:
Category_avail.append(ids.id) Category_avail.append(ids.id)
@ -139,14 +118,20 @@ class ProductVisibilityCon(WebsiteSale):
if mode == 'product_only': if mode == 'product_only':
categ = Category.search([('parent_id', '=', False), ( categ = Category.search([('parent_id', '=', False), (
'product_tmpl_ids', 'in', available_products.ids)]) 'product_tmpl_ids', 'in', available_products.ids)])
# supering shop*** # supering shop***
if not available_categ and not available_products: if not available_categ and not available_products:
return super(ProductVisibilityCon, self).shop(page, category, return super(ProductVisibilityCon, self).shop(page, category,
search, ppg, **post) search, ppg, **post)
add_qty = int(post.get('add_qty', 1)) add_qty = int(post.get('add_qty', 1))
try:
min_price = float(min_price)
except ValueError:
min_price = 0
try:
max_price = float(max_price)
except ValueError:
max_price = 0
Category = request.env['product.public.category']
if category: if category:
category = Category.search([('id', '=', int(category))], limit=1) category = Category.search([('id', '=', int(category))], limit=1)
if not category or not category.can_access_from_current_website(): if not category or not category.can_access_from_current_website():
@ -174,30 +159,76 @@ class ProductVisibilityCon(WebsiteSale):
domain_pro = self.reset_domain(search, category, available_products, domain_pro = self.reset_domain(search, category, available_products,
attrib_values) attrib_values)
Product = Product.search(domain_pro) Product = Product.search(domain_pro)
keep = QueryURL('/shop', category=category and int(category), keep = QueryURL('/shop', **self._shop_get_query_url_kwargs(
search=search, attrib=attrib_list, category and int(category), search, min_price, max_price, **post))
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()) now = datetime.timestamp(datetime.now())
pricelist = request.env['product.pricelist'].browse( pricelist = request.env['product.pricelist'].browse(
request.session.get('website_sale_current_pl')) request.session.get('website_sale_current_pl'))
if not pricelist or request.session.get('website_sale_pricelist_time', if not pricelist or request.session.get('website_sale_pricelist_time',
0) < now - 60 * 60: # test: 1 hour in session 0) < now - 60 * 60:
# test: 1 hour in session
pricelist = website.get_current_pricelist() pricelist = website.get_current_pricelist()
request.session['website_sale_pricelist_time'] = now request.session['website_sale_pricelist_time'] = now
request.session['website_sale_current_pl'] = pricelist.id request.session['website_sale_current_pl'] = pricelist.id
request.update_context(pricelist=pricelist.id, request.update_context(pricelist=pricelist.id,
partner=request.env.user.partner_id) partner=request.env.user.partner_id)
filter_by_price_enabled = website.is_view_active(
'website_sale.filter_products_price')
if filter_by_price_enabled:
company_currency = website.company_id.currency_id
conversion_rate = request.env['res.currency']._get_conversion_rate(
company_currency, pricelist.currency_id,
request.website.company_id, fields.Date.today())
else:
conversion_rate = 1
url = "/shop" url = "/shop"
if search: if search:
post["search"] = search post["search"] = search
if attrib_list: if attrib_list:
post['attrib'] = attrib_list post['attrib'] = attrib_list
options = self._get_search_options(
category=category,
attrib_values=attrib_values,
pricelist=pricelist,
min_price=min_price,
max_price=max_price,
conversion_rate=conversion_rate,
**post
)
fuzzy_search_term, product_count, search_product = self._shop_lookup_products(
attrib_set, options, post, search, website)
filter_by_price_enabled = website.is_view_active(
'website_sale.filter_products_price')
if filter_by_price_enabled:
# TODO Find an alternative way to obtain the domain through the search metadata.
Product = request.env['product.template'].with_context(
bin_size=True)
domain = self._get_search_domain(search, category, attrib_values)
# This is ~4 times more efficient than a search for the cheapest and most expensive products
from_clause, where_clause, where_params = Product._where_calc(
domain).get_sql()
query = f"""
SELECT COALESCE(MIN(list_price), 0) * {conversion_rate}, COALESCE(MAX(list_price), 0) * {conversion_rate}
FROM {from_clause}
WHERE {where_clause}
"""
request.env.cr.execute(query, where_params)
available_min_price, available_max_price = request.env.cr.fetchone()
if min_price or max_price:
# The if/else condition in the min_price / max_price value assignment
# tackles the case where we switch to a list of products with different
# available min / max prices than the ones set in the previous page.
# In order to have logical results and not yield empty product lists, the
# price filter is set to their respective available prices when the specified
# min exceeds the max, and / or the specified max is lower than the available min.
if min_price:
min_price = min_price if min_price <= available_max_price else available_min_price
post['min_price'] = min_price
if max_price:
max_price = max_price if max_price >= available_min_price else available_max_price
post['max_price'] = max_price
website_domain = website.website_domain()
categs_domain = [('parent_id', '=', False)] + website_domain
if not category: if not category:
domain = self.reset_domain(search, available_categ, domain = self.reset_domain(search, available_categ,
available_products, attrib_values) available_products, attrib_values)
@ -207,16 +238,20 @@ class ProductVisibilityCon(WebsiteSale):
'product_tmpl_ids', 'in', search_product.ids)] + website_domain 'product_tmpl_ids', 'in', search_product.ids)] + website_domain
if search: if search:
search_categories = Category.search( search_categories = Category.search(
[('product_tmpl_ids', 'in', [(
search_product.ids)] + website_domain).parents_and_self 'product_tmpl_ids', 'in',
search_product.ids)] + website_domain
).parents_and_self
categs_domain.append(('id', 'in', search_categories.ids)) categs_domain.append(('id', 'in', search_categories.ids))
else: else:
search_categories = available_categ search_categories = available_categ
categs = lazy(lambda: Category.search(categs_domain))
if category: if category:
url = "/shop/category/%s" % slug(category) url = "/shop/category/%s" % slug(category)
product_count = len(search_product) product_count = len(search_product)
pager = request.website.pager(url=url, total=product_count, page=page, pager = website.pager(url=url, total=product_count, page=page, step=ppg,
step=ppg, scope=7, url_args=post) scope=7, url_args=post)
offset = pager['offset']
products = Product.search(domain, limit=ppg, offset=pager['offset'], products = Product.search(domain, limit=ppg, offset=pager['offset'],
order=self._get_search_order(post)) order=self._get_search_order(post))
if not category: if not category:
@ -240,23 +275,24 @@ class ProductVisibilityCon(WebsiteSale):
ProductAttribute = request.env['product.attribute'] ProductAttribute = request.env['product.attribute']
if products: if products:
# get all products without limit # get all products without limit
attributes = ProductAttribute.search( attributes = lazy(lambda: ProductAttribute.search([
[('product_tmpl_ids', 'in', search_product.ids)]) ('product_tmpl_ids', 'in', search_product.ids),
('visibility', '=', 'visible'),
]))
else: else:
attributes = ProductAttribute.browse(attributes_ids) attributes = lazy(lambda: ProductAttribute.browse(attributes_ids))
layout_mode = request.session.get('website_sale_shop_layout_mode') layout_mode = request.session.get('website_sale_shop_layout_mode')
if not layout_mode: if not layout_mode:
if request.website.viewref( if website.viewref('website_sale.products_list_view').active:
'website_sale.products_list_view').active:
layout_mode = 'list' layout_mode = 'list'
else: else:
layout_mode = 'grid' layout_mode = 'grid'
request.session['website_sale_shop_layout_mode'] = layout_mode request.session['website_sale_shop_layout_mode'] = layout_mode
products_prices = lazy(lambda: products._get_sales_prices(pricelist)) products_prices = lazy(lambda: products._get_sales_prices(pricelist))
values = { values = {
'search': search, 'search': fuzzy_search_term or search,
'original_search': fuzzy_search_term and search,
'order': post.get('order', ''),
'category': category, 'category': category,
'attrib_values': attrib_values, 'attrib_values': attrib_values,
'attrib_set': attrib_set, 'attrib_set': attrib_set,
@ -264,6 +300,7 @@ class ProductVisibilityCon(WebsiteSale):
'pricelist': pricelist, 'pricelist': pricelist,
'add_qty': add_qty, 'add_qty': add_qty,
'products': products, 'products': products,
'search_product': search_product,
'search_count': product_count, # common for all searchbox 'search_count': product_count, # common for all searchbox
'bins': TableCompute().process(products, ppg, ppr), 'bins': TableCompute().process(products, ppg, ppr),
'ppg': ppg, 'ppg': ppg,
@ -276,14 +313,22 @@ class ProductVisibilityCon(WebsiteSale):
'products_prices': products_prices, 'products_prices': products_prices,
'get_product_prices': lambda product: lazy( 'get_product_prices': lambda product: lazy(
lambda: products_prices[product.id]), lambda: products_prices[product.id]),
'float_round': tools.float_round,
} }
if filter_by_price_enabled:
values['min_price'] = min_price or available_min_price
values['max_price'] = max_price or available_max_price
values['available_min_price'] = tools.float_round(
available_min_price, 2)
values['available_max_price'] = tools.float_round(
available_max_price, 2)
if category: if category:
values['main_object'] = category values['main_object'] = category
values.update(self._get_additional_shop_values(values))
return request.render("website_sale.products", values) return request.render("website_sale.products", values)
def availavle_products(self): def available_products(self):
''''Returns the available product (product.template) ids''' """Returns the available product (product.template) ids"""
user = request.env['res.users'].sudo().search( user = request.env['res.users'].sudo().search(
[('id', '=', request.env.user.id)]) [('id', '=', request.env.user.id)])
partner = request.env['res.partner'].sudo().search( partner = request.env['res.partner'].sudo().search(
@ -299,7 +344,6 @@ class ProductVisibilityCon(WebsiteSale):
def products_autocomplete(self, term, options={}, **kwargs): def products_autocomplete(self, term, options={}, **kwargs):
""" """
Returns list of products according to the term and product options Returns list of products according to the term and product options
Params: Params:
term (str): search term written by the user term (str): search term written by the user
options (dict) options (dict)
@ -309,7 +353,6 @@ class ProductVisibilityCon(WebsiteSale):
- 'order' (str) - 'order' (str)
- 'max_nb_chars' (int): max number of characters for the - 'max_nb_chars' (int): max number of characters for the
description if returned description if returned
Returns: Returns:
dict (or False if no result) dict (or False if no result)
- 'products' (list): products (only their needed field values) - 'products' (list): products (only their needed field values)
@ -318,7 +361,6 @@ class ProductVisibilityCon(WebsiteSale):
- 'products_count' (int): the number of products in the database - 'products_count' (int): the number of products in the database
that matched the search query that matched the search query
""" """
user = request.env['res.users'].sudo().search( user = request.env['res.users'].sudo().search(
[('id', '=', request.env.user.id)]) [('id', '=', request.env.user.id)])
available_categ = available_products = '' available_categ = available_products = ''
@ -343,7 +385,7 @@ class ProductVisibilityCon(WebsiteSale):
[('id', '=', user.partner_id.id)]) [('id', '=', user.partner_id.id)])
mode = partner.filter_mode mode = partner.filter_mode
if mode != 'categ_only': if mode != 'categ_only':
available_products = self.availavle_products() available_products = self.available_products()
available_categ = partner.website_available_cat_ids available_categ = partner.website_available_cat_ids
ProductTemplate = request.env['product.template'] ProductTemplate = request.env['product.template']
display_description = options.get('display_description', True) display_description = options.get('display_description', True)
@ -352,7 +394,6 @@ class ProductVisibilityCon(WebsiteSale):
max_nb_chars = options.get('max_nb_chars', 999) max_nb_chars = options.get('max_nb_chars', 999)
category = options.get('category') category = options.get('category')
attrib_values = options.get('attrib_values') attrib_values = options.get('attrib_values')
if not available_products and not available_categ: if not available_products and not available_categ:
domain = self._get_search_domain(term, category, attrib_values, domain = self._get_search_domain(term, category, attrib_values,
display_description) display_description)
@ -368,19 +409,16 @@ class ProductVisibilityCon(WebsiteSale):
fields = ['id', 'name', 'website_url'] fields = ['id', 'name', 'website_url']
if display_description: if display_description:
fields.append('description_sale') fields.append('description_sale')
res = { res = {
'products': products.read(fields), 'products': products.read(fields),
'products_count': ProductTemplate.search_count(domain), 'products_count': ProductTemplate.search_count(domain),
} }
if display_description: if display_description:
for res_product in res['products']: for res_product in res['products']:
desc = res_product['description_sale'] desc = res_product['description_sale']
if desc and len(desc) > max_nb_chars: if desc and len(desc) > max_nb_chars:
res_product['description_sale'] = "%s..." % desc[:( res_product['description_sale'] = "%s..." % desc[:(
max_nb_chars - 3)] max_nb_chars - 3)]
if display_price: if display_price:
FieldMonetary = request.env['ir.qweb.field.monetary'] FieldMonetary = request.env['ir.qweb.field.monetary']
monetary_options = { monetary_options = {
@ -394,5 +432,4 @@ class ProductVisibilityCon(WebsiteSale):
res_product['list_price'], monetary_options) res_product['list_price'], monetary_options)
res_product['price'] = FieldMonetary.value_to_html( res_product['price'] = FieldMonetary.value_to_html(
res_product['price'], monetary_options) res_product['price'], monetary_options)
return res return res

7
product_visibility_website/doc/RELEASE_NOTES.md

@ -4,6 +4,7 @@
#### Version 16.0.1.0.0 #### Version 16.0.1.0.0
##### ADD ##### ADD
#### 22.08.2023
#### Version 16.0.1.0.0
##### FIX
- Bug Fixed

9
product_visibility_website/models/__init__.py

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################### ################################################################################
# #
# Cybrosys Technologies Pvt. Ltd. # Cybrosys Technologies Pvt. Ltd.
# #
# Copyright (C) 2022-TODAY Cybrosys Technologies (<https://www.cybrosys.com>). # Copyright (C) 2022-TODAY Cybrosys Technologies (<https://www.cybrosys.com>)
# Author: Neeraj Krishnan V M (<https://www.cybrosys.com>) # Author: Neeraj Krishnan V M, Saneen K (<https://www.cybrosys.com>)
# #
# This program is free software: you can modify # This program is free software: you can modify
# it under the terms of the GNU Affero General Public License (AGPL) as # it under the terms of the GNU Affero General Public License (AGPL) as
@ -19,6 +19,5 @@
# You should have received a copy of the GNU Affero General Public License # 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/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
# #
################################################################################### ################################################################################
from . import website_product_visibility from . import website_product_visibility

70
product_visibility_website/models/website_product_visibility.py

@ -1,11 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################### ################################################################################
# #
# Cybrosys Technologies Pvt. Ltd. # Cybrosys Technologies Pvt. Ltd.
# #
# Copyright (C) 2022-TODAY Cybrosys Technologies ( # Copyright (C) 2022-TODAY Cybrosys Technologies (<https://www.cybrosys.com>)
# <https://www.cybrosys.com>). Author: Neeraj Krishnan V M( # Author: Neeraj Krishnan V M, Saneen K (<https://www.cybrosys.com>)
# <https://www.cybrosys.com>)
# #
# This program is free software: you can modify # This program is free software: you can modify
# it under the terms of the GNU Affero General Public License (AGPL) as # it under the terms of the GNU Affero General Public License (AGPL) as
@ -20,57 +19,81 @@
# You should have received a copy of the GNU Affero General Public License # 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/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
# #
################################################################################### ################################################################################
from odoo import fields, models, api from odoo import fields, models, api
from ast import literal_eval from ast import literal_eval
class ProductVisibility(models.Model): class ProductVisibility(models.Model):
"""Inherit res.partner for adding the fields for selecting the products"""
_inherit = 'res.partner' _inherit = 'res.partner'
filter_mode = fields.Selection( filter_mode = fields.Selection(
[('null', 'No Filter'), ('product_only', 'Product Wise'), [('null', 'No Filter'), ('product_only', 'Product Wise'),
('categ_only', 'Category Wise')], string='Filter Mode', default='null') ('categ_only', 'Category Wise')], string='Filter Mode', default='null',
help="Select any mode")
website_available_product_ids = fields.Many2many('product.template', website_available_product_ids = fields.Many2many('product.template',
string='Available Product', string='Available Product',
domain="[('is_published', '=', True)]", domain="[('is_published"
help='The website will only display products which are within one ' "', '=', True)]",
'of the selected category trees. If no category is specified,' help='The website will '
' all available products will be shown') 'only display '
'products which are '
'within one'
'of the selected '
'category trees. If '
'no category is '
'specified,'
'all available '
'products will be '
'shown')
website_available_cat_ids = fields.Many2many('product.public.category', website_available_cat_ids = fields.Many2many('product.public.category',
string='Available Product Categories', string='Available Product '
help='The website will only display products which are selected.' 'Categories',
' If no product is specified,' help='The website will only '
' all available products will be shown') 'display products which '
'are selected.'
'If no product is '
'specified,'
'all available products '
'will be shown')
@api.onchange("filter_mode") @api.onchange("filter_mode")
def onchange_filter_mod(self): def onchange_filter_mod(self):
"""Function for viewing the modes and product/category"""
if self.filter_mode == 'null': if self.filter_mode == 'null':
self.website_available_cat_ids = None self.website_available_cat_ids = None
self.website_available_product_ids = None self.website_available_product_ids = None
class WebsiteGuestVisibility(models.TransientModel): class WebsiteGuestVisibility(models.TransientModel):
"""Inherit the model res.config.settings for adding the fields for
selecting the product for visitors"""
_inherit = 'res.config.settings' _inherit = 'res.config.settings'
product_visibility_guest_user = fields.Boolean( product_visibility_guest_user = fields.Boolean(
string="Product visibility Guest User") string="Product visibility Guest User", help="Product Visibility")
filter_mode = fields.Selection([('product_only', 'Product Wise'), filter_mode = fields.Selection([('product_only', 'Product Wise'),
('categ_only', 'Category Wise')], ('categ_only', 'Category Wise')],
string='Filter Mode', default='product_only') string='Filter Mode', default='product_only')
available_product_ids = fields.Many2many('product.template', available_product_ids = fields.Many2many('product.template',
string='Available Product', string='Available Product',
domain="[('is_published', '=', True)]", domain="[('is_published', '=', "
help='The website will only display products which are within one ' "True)]",
'of the selected category trees. If no category is specified,' help='The website will only '
' all available products will be shown') 'display products which are '
'within one of the selected'
' category trees. If no'
' category is specified,'
'all available products '
'will be shown')
available_cat_ids = fields.Many2many('product.public.category', available_cat_ids = fields.Many2many('product.public.category',
string='Available Product Categories', string='Available Product Categories',
help='The website will only display products which are selected.' help='The website will only display '
'products which are selected.'
' If no product is specified,' ' If no product is specified,'
' all available products will be shown') 'all available products will be '
'shown')
@api.model @api.model
def set_values(self): def set_values(self):
@ -89,7 +112,6 @@ class WebsiteGuestVisibility(models.TransientModel):
self.available_cat_ids = None self.available_cat_ids = None
elif self.filter_mode == 'categ_only': elif self.filter_mode == 'categ_only':
self.available_product_ids = None self.available_product_ids = None
self.env['ir.config_parameter'].sudo().set_param( self.env['ir.config_parameter'].sudo().set_param(
'website_product_visibility.available_product_ids', 'website_product_visibility.available_product_ids',
self.available_product_ids.ids) self.available_product_ids.ids)

5
product_visibility_website/static/description/index.html

@ -135,7 +135,6 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<!-- END OF FEATURES SECTION --> <!-- END OF FEATURES SECTION -->
<!-- SCREENSHOTS SECTION --> <!-- SCREENSHOTS SECTION -->
@ -399,7 +398,7 @@
</div> </div>
<!-- END OF END OF OUR SERVICES --> <!--END OF OUR SERVICES -->
<!-- OUR INDUSTRIES --> <!-- OUR INDUSTRIES -->
@ -526,7 +525,7 @@
</div> </div>
</div> </div>
<!-- END OF END OF OUR INDUSTRIES --> <!-- END OF OUR INDUSTRIES -->
<!-- SUPPORT --> <!-- SUPPORT -->
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> <div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px;">

9
product_visibility_website/views/website_product_visibility.xml

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<data> <data>
<record id="base_view_partner_form_inherit" model="ir.ui.view"> <record id="view_partner_form" model="ir.ui.view">
<field name="name"> base.view.partner.form.inherit</field> <field name="name"> res.partner.view.form.inherit.product.visibility.website</field>
<field name="model">res.partner</field> <field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/> <field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
@ -22,9 +22,8 @@
</field> </field>
</record> </record>
<record id="res_config_settings_view_form" model="ir.ui.view">
<record id="website_config_view_inherit" model="ir.ui.view"> <field name="name">res.config.settings.view.form.inherit.product.visibility.website</field>
<field name="name">website.config.view.inherit</field>
<field name="model">res.config.settings</field> <field name="model">res.config.settings</field>
<field name="inherit_id" ref="website.res_config_settings_view_form"/> <field name="inherit_id" ref="website.res_config_settings_view_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">

Loading…
Cancel
Save