@ -0,0 +1,46 @@ |
|||||
|
.. 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 |
||||
|
|
||||
|
Theme Boec |
||||
|
========================= |
||||
|
* Attractive and modern eCommerce Website theme for Odoo 18 |
||||
|
|
||||
|
Configuration |
||||
|
============= |
||||
|
* No need of additional configuration. |
||||
|
|
||||
|
License |
||||
|
------- |
||||
|
Affero General Public License, Version 3 (AGPL-3). |
||||
|
(https://www.gnu.org/licenses/agpl-3.0.en.html) |
||||
|
|
||||
|
Company |
||||
|
------- |
||||
|
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ |
||||
|
|
||||
|
Credits |
||||
|
======= |
||||
|
* Developer: (V18) Fouzan M, Contact: odoo@cybrosys.com |
||||
|
|
||||
|
Contacts |
||||
|
-------- |
||||
|
* Mail Contact : odoo@cybrosys.com |
||||
|
* Website : https://cybrosys.com |
||||
|
|
||||
|
Bug Tracker |
||||
|
----------- |
||||
|
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. |
||||
|
|
||||
|
Maintainer |
||||
|
========== |
||||
|
.. image:: https://cybrosys.com/images/logo.png |
||||
|
:target: https://cybrosys.com |
||||
|
|
||||
|
This module is maintained by Cybrosys Technologies. |
||||
|
|
||||
|
For support and more information, please visit `Our Website <https://cybrosys.com/>`__ |
||||
|
|
||||
|
Further information |
||||
|
=================== |
||||
|
HTML Description: `<static/description/index.html>`__ |
@ -0,0 +1,23 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
from . import models |
||||
|
from . import controllers |
@ -0,0 +1,89 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
{ |
||||
|
'name': 'Theme Boec', |
||||
|
'version': '18.0.1.0.0', |
||||
|
'category': 'Theme/eCommerce', |
||||
|
'summary': "Theme Boec is an attractive and modern eCommerce Website theme", |
||||
|
'description': "Theme Boec is new kind of Theme.The theme is very " |
||||
|
"user-friendly and suitable for your eCommerce website " |
||||
|
"with blog", |
||||
|
'author': 'Cybrosys Techno Solutions', |
||||
|
'company': 'Cybrosys Techno Solutions', |
||||
|
'maintainer': 'Cybrosys Techno Solutions', |
||||
|
'website': "https://www.cybrosys.com", |
||||
|
'depends': ['website_blog', 'website_sale_wishlist', 'website_sale', |
||||
|
'website_sale_comparison'], |
||||
|
'data': [ |
||||
|
'security/ir.model.access.csv', |
||||
|
'data/boec_config_data.xml', |
||||
|
'views/about.xml', |
||||
|
'views/blog_templates.xml', |
||||
|
'views/blog_preview_templates.xml', |
||||
|
'views/boec_config_views.xml', |
||||
|
'views/cart_templates.xml', |
||||
|
'views/contact_us_templates.xml', |
||||
|
'views/footer_templates.xml', |
||||
|
'views/header_templates.xml', |
||||
|
'views/layout_templates.xml', |
||||
|
'views/page_top_templates.xml', |
||||
|
'views/product_brand_views.xml', |
||||
|
'views/product_template_views.xml', |
||||
|
'views/product_view_templates.xml', |
||||
|
'views/shop_templates.xml', |
||||
|
'views/sidebar_shop_templates.xml', |
||||
|
'views/snippets/banner.xml', |
||||
|
'views/snippets/blog_latest.xml', |
||||
|
'views/snippets/deal_week.xml', |
||||
|
'views/snippets/demo_product.xml', |
||||
|
'views/snippets/insta_feed.xml', |
||||
|
'views/snippets/product_tab.xml', |
||||
|
'views/snippets/product_tab_demo.xml', |
||||
|
], |
||||
|
'assets': { |
||||
|
'web.assets_frontend': [ |
||||
|
'theme_boec/static/src/js/sale_utils.js', |
||||
|
"/theme_boec/static/src/css/style.css", |
||||
|
"/theme_boec/static/src/css/style.css.map", |
||||
|
"/theme_boec/static/src/css/style.scss", |
||||
|
"/theme_boec/static/src/css/owl_carousel_min.css", |
||||
|
"/theme_boec/static/src/css/owl_theme_default_min.css", |
||||
|
"/theme_boec/static/src/js/owl.carousel.js", |
||||
|
"/theme_boec/static/src/js/owl.carousel.min.js", |
||||
|
"/theme_boec/static/src/js/jquery.countdown.min.js", |
||||
|
'/theme_boec/static/src/xml/deal_week_content.xml', |
||||
|
'/theme_boec/static/src/xml/product_tab_content.xml', |
||||
|
"/theme_boec/static/src/js/deal_week.js", |
||||
|
"/theme_boec/static/src/js/product_tab.js", |
||||
|
"/theme_boec/static/src/js/custom.js", |
||||
|
'https://cdn.jsdelivr.net/npm/material-icons@1.13.12/iconfont/material-icons.min.css', |
||||
|
], |
||||
|
}, |
||||
|
'images': [ |
||||
|
'static/description/banner.png', |
||||
|
'static/description/theme_screenshot.jpg', |
||||
|
], |
||||
|
'license': 'AGPL-3', |
||||
|
'installable': True, |
||||
|
'auto_install': False, |
||||
|
'application': False, |
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
from . import brand_filter_controller |
||||
|
from . import product_snippets |
@ -0,0 +1,298 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
from datetime import datetime |
||||
|
from werkzeug.exceptions import NotFound |
||||
|
from odoo import fields, http |
||||
|
from odoo.http import request |
||||
|
from odoo.addons.website.models.ir_http import sitemap_qs2dom |
||||
|
from odoo.addons.website.controllers.main import QueryURL |
||||
|
from odoo.addons.website_sale.controllers.main import TableCompute, WebsiteSale |
||||
|
from odoo.tools import float_round, groupby, lazy, SQL |
||||
|
from odoo.osv import expression |
||||
|
|
||||
|
class ProductBrand(WebsiteSale): |
||||
|
|
||||
|
def sitemap_shop(env, rule, qs): |
||||
|
"""Required function for shop""" |
||||
|
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' % request.env['ir.http']._slug(cat) |
||||
|
if not qs or qs.lower() in loc: |
||||
|
yield {'loc': loc} |
||||
|
|
||||
|
@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, brand=None, category=None, search='', min_price=0.0, |
||||
|
max_price=0.0, ppg=False, **post): |
||||
|
if not request.website.has_ecommerce_access(): |
||||
|
return request.redirect('/web/login') |
||||
|
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: |
||||
|
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() |
||||
|
website_domain = website.website_domain() |
||||
|
if ppg: |
||||
|
try: |
||||
|
ppg = int(ppg) |
||||
|
post['ppg'] = ppg |
||||
|
except ValueError: |
||||
|
ppg = False |
||||
|
if not ppg: |
||||
|
ppg = website.shop_ppg or 20 |
||||
|
|
||||
|
ppr = website.shop_ppr or 4 |
||||
|
gap = website.shop_gap or "16px" |
||||
|
request_args = request.httprequest.args |
||||
|
attrib_list = request_args.getlist('attribute_value') |
||||
|
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} |
||||
|
|
||||
|
brand_list = request_args.getlist('brand') |
||||
|
brand_ids = [int(brand) for brand in brand_list] |
||||
|
filter_by_tags_enabled = website.is_view_active( |
||||
|
'website_sale.filter_products_tags') |
||||
|
if filter_by_tags_enabled: |
||||
|
tags = request_args.getlist('tags') |
||||
|
# Allow only numeric tag values to avoid internal error. |
||||
|
if tags and all(tag.isnumeric() for tag in tags): |
||||
|
post['tags'] = tags |
||||
|
tags = {int(tag) for tag in tags} |
||||
|
else: |
||||
|
post['tags'] = None |
||||
|
tags = {} |
||||
|
|
||||
|
keep = QueryURL('/shop', **self._shop_get_query_url_kwargs( |
||||
|
category and int(category), search, min_price, max_price, **post)) |
||||
|
|
||||
|
now = datetime.timestamp(datetime.now()) |
||||
|
pricelist = website.pricelist_id |
||||
|
|
||||
|
if 'website_sale_pricelist_time' in request.session: |
||||
|
# Check if we need to refresh the cached pricelist |
||||
|
pricelist_save_time = request.session['website_sale_pricelist_time'] |
||||
|
if pricelist_save_time < now - 60 * 60: |
||||
|
request.session.pop('website_sale_current_pl', None) |
||||
|
website.invalidate_recordset(['pricelist_id']) |
||||
|
pricelist = website.pricelist_id |
||||
|
request.session['website_sale_pricelist_time'] = now |
||||
|
request.session['website_sale_current_pl'] = pricelist.id |
||||
|
else: |
||||
|
request.session['website_sale_pricelist_time'] = now |
||||
|
request.session['website_sale_current_pl'] = pricelist.id |
||||
|
|
||||
|
filter_by_price_enabled = website.is_view_active( |
||||
|
'website_sale.filter_products_price') |
||||
|
if filter_by_price_enabled: |
||||
|
company_currency = website.company_id.sudo().currency_id |
||||
|
conversion_rate = request.env['res.currency']._get_conversion_rate( |
||||
|
company_currency, website.currency_id, |
||||
|
request.website.company_id, fields.Date.today()) |
||||
|
else: |
||||
|
conversion_rate = 1 |
||||
|
|
||||
|
url = '/shop' |
||||
|
if search: |
||||
|
post['search'] = search |
||||
|
if brand_ids: |
||||
|
post['brand_ids'] = brand_ids |
||||
|
options = self._get_search_options( |
||||
|
category=category, |
||||
|
attrib_values=attrib_values, |
||||
|
min_price=min_price, |
||||
|
max_price=max_price, |
||||
|
conversion_rate=conversion_rate, |
||||
|
display_currency=website.currency_id, |
||||
|
**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_shop_domain(search, category, attrib_values) |
||||
|
|
||||
|
# This is ~4 times more efficient than a search for the cheapest and most expensive products |
||||
|
query = Product._where_calc(domain) |
||||
|
Product._apply_ir_rules(query, 'read') |
||||
|
sql = query.select( |
||||
|
SQL( |
||||
|
"COALESCE(MIN(list_price), 0) * %(conversion_rate)s, COALESCE(MAX(list_price), 0) * %(conversion_rate)s", |
||||
|
conversion_rate=conversion_rate, |
||||
|
) |
||||
|
) |
||||
|
available_min_price, available_max_price = \ |
||||
|
request.env.execute_query(sql)[0] |
||||
|
|
||||
|
if min_price or max_price: |
||||
|
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 |
||||
|
|
||||
|
ProductTag = request.env['product.tag'] |
||||
|
if filter_by_tags_enabled and search_product: |
||||
|
all_tags = ProductTag.search( |
||||
|
expression.AND([ |
||||
|
[('product_ids.is_published', '=', True), |
||||
|
('visible_on_ecommerce', '=', True)], |
||||
|
website_domain |
||||
|
]) |
||||
|
) |
||||
|
else: |
||||
|
all_tags = ProductTag |
||||
|
|
||||
|
categs_domain = [('parent_id', '=', False)] + 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 = Category |
||||
|
categs = lazy(lambda: Category.search(categs_domain)) |
||||
|
|
||||
|
if category: |
||||
|
url = "/shop/category/%s" % request.env['ir.http']._slug(category) |
||||
|
|
||||
|
pager = website.pager(url=url, total=product_count, page=page, step=ppg, |
||||
|
scope=5, url_args=post) |
||||
|
offset = pager['offset'] |
||||
|
products = search_product[offset:offset + ppg] |
||||
|
|
||||
|
ProductAttribute = request.env['product.attribute'] |
||||
|
if products: |
||||
|
# get all products without limit |
||||
|
attributes = lazy(lambda: ProductAttribute.search([ |
||||
|
('product_tmpl_ids', 'in', search_product.ids), |
||||
|
('visibility', '=', 'visible'), |
||||
|
])) |
||||
|
else: |
||||
|
attributes = lazy(lambda: ProductAttribute.browse(attributes_ids)) |
||||
|
|
||||
|
layout_mode = request.session.get('website_sale_shop_layout_mode') |
||||
|
if not layout_mode: |
||||
|
if 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(website)) |
||||
|
|
||||
|
attributes_values = request.env['product.attribute.value'].browse( |
||||
|
attrib_set) |
||||
|
sorted_attributes_values = attributes_values.sorted('sequence') |
||||
|
multi_attributes_values = sorted_attributes_values.filtered( |
||||
|
lambda av: av.display_type == 'multi') |
||||
|
single_attributes_values = sorted_attributes_values - multi_attributes_values |
||||
|
grouped_attributes_values = list( |
||||
|
groupby(single_attributes_values, lambda av: av.attribute_id.id)) |
||||
|
grouped_attributes_values.extend( |
||||
|
[(av.attribute_id.id, [av]) for av in multi_attributes_values]) |
||||
|
|
||||
|
selected_attributes_hash = grouped_attributes_values and "#attribute_values=%s" % ( |
||||
|
','.join(str(v[0].id) for k, v in grouped_attributes_values) |
||||
|
) or '' |
||||
|
|
||||
|
values = { |
||||
|
'search': fuzzy_search_term or search, |
||||
|
'original_search': fuzzy_search_term and search, |
||||
|
'order': post.get('order', ''), |
||||
|
'category': category, |
||||
|
'attrib_values': attrib_values, |
||||
|
'attrib_set': attrib_set, |
||||
|
'pager': pager, |
||||
|
'products': products, |
||||
|
'search_product': search_product, |
||||
|
'search_count': product_count, # common for all searchbox |
||||
|
'bins': lazy(lambda: TableCompute().process(products, ppg, ppr)), |
||||
|
'ppg': ppg, |
||||
|
'ppr': ppr, |
||||
|
'gap': gap, |
||||
|
'categories': categs, |
||||
|
'attributes': attributes, |
||||
|
'keep': keep, |
||||
|
'selected_attributes_hash': selected_attributes_hash, |
||||
|
'search_categories_ids': search_categories.ids, |
||||
|
'layout_mode': layout_mode, |
||||
|
'products_prices': products_prices, |
||||
|
'get_product_prices': lambda product: lazy( |
||||
|
lambda: products_prices[product.id]), |
||||
|
'float_round': float_round, |
||||
|
'brand_ids': brand_ids, |
||||
|
} |
||||
|
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'] = float_round(available_min_price, 2) |
||||
|
values['available_max_price'] = float_round(available_max_price, 2) |
||||
|
if filter_by_tags_enabled: |
||||
|
values.update({'all_tags': all_tags, 'tags': tags}) |
||||
|
if category: |
||||
|
values['main_object'] = category |
||||
|
values.update(self._get_additional_extra_shop_values(values, **post)) |
||||
|
return request.render("website_sale.products", values) |
||||
|
|
||||
|
def _get_search_options( |
||||
|
self, category=None, attrib_values=None, tags=None, min_price=0.0, |
||||
|
max_price=0.0, |
||||
|
conversion_rate=1, **post |
||||
|
): |
||||
|
res = super()._get_search_options(category=category, |
||||
|
attrib_values=attrib_values, |
||||
|
tags=tags, min_price=min_price, |
||||
|
max_price=max_price, |
||||
|
conversion_rate=conversion_rate, |
||||
|
**post) |
||||
|
res['brand_ids'] = post.get('brand_ids', None) |
||||
|
return res |
@ -0,0 +1,60 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
from odoo import http |
||||
|
from odoo.http import request |
||||
|
|
||||
|
|
||||
|
class WebsiteProduct(http.Controller): |
||||
|
|
||||
|
@http.route('/get_product_tab', auth="public", type='json', website=True) |
||||
|
def get_product_tab(self): |
||||
|
print('REACHED') |
||||
|
"""Get the website published products for snippet""" |
||||
|
new_arrivals = request.env['product.template'].sudo().search_read( |
||||
|
[('website_published', '=', True)], |
||||
|
order='create_date desc', limit=12) |
||||
|
hot_deals = request.env['product.template'].sudo().search_read( |
||||
|
[('website_published', '=', True), |
||||
|
('hot_deals', '=', True)], limit=12) |
||||
|
return { |
||||
|
'new_arrivals': new_arrivals, |
||||
|
'hot_deals': hot_deals, |
||||
|
'symbol': request.env.user.company_id.currency_id.symbol |
||||
|
} |
||||
|
|
||||
|
@http.route('/get_products', auth='public', type='json', website=True) |
||||
|
def get_products(self, **kwargs): |
||||
|
"""Allows to get deal of the week product.""" |
||||
|
boec_configuration = request.env.ref('theme_boec.boec_config_data') |
||||
|
product = boec_configuration.deal_week_product_id |
||||
|
return { |
||||
|
'id': product.id, |
||||
|
'name': product.name, |
||||
|
'lst_price': product.lst_price, |
||||
|
'product_tmpl_id': product.product_tmpl_id.id, |
||||
|
'symbol': request.env.user.company_id.currency_id.symbol |
||||
|
} |
||||
|
|
||||
|
@http.route('/get_countdown', auth='public', type='json', website=True) |
||||
|
def get_countdown(self, **kwargs): |
||||
|
"""End date for the deal""" |
||||
|
return request.env.ref('theme_boec.boec_config_data').date_end |
@ -0,0 +1,9 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8" ?> |
||||
|
<odoo> |
||||
|
<data noupdate="1"> |
||||
|
<!--created a record in model boec.config--> |
||||
|
<record id="boec_config_data" model="boec.config"> |
||||
|
<field name="name">Boec Config</field> |
||||
|
</record> |
||||
|
</data> |
||||
|
</odoo> |
@ -0,0 +1,6 @@ |
|||||
|
## Module <theme_boec> |
||||
|
|
||||
|
#### 29.10.2024 |
||||
|
#### Version 18.0.1.0.0 |
||||
|
#### ADD |
||||
|
- Initial commit for Theme Boec |
@ -0,0 +1,26 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
from . import boec_config |
||||
|
from . import product_brand |
||||
|
from . import product_template |
||||
|
from . import theme_utils |
||||
|
from . import website |
@ -0,0 +1,37 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class BoecConfig(models.Model): |
||||
|
"""Allows to set a product that will deal of the week. It is a snippet""" |
||||
|
_name = 'boec.config' |
||||
|
_description = 'Boec Config' |
||||
|
|
||||
|
name = fields.Char(string='Name', help='Name of the Deal') |
||||
|
deal_week_product_id = fields.Many2one('product.product', |
||||
|
domain=[('is_published', '=', True)], |
||||
|
string='Deal of the Week Product', |
||||
|
help='This product will be the deal' |
||||
|
'of the week') |
||||
|
date_end = fields.Datetime(string='Counter End Date', help='End date of' |
||||
|
'this offer') |
@ -0,0 +1,37 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class ProductBrand(models.Model): |
||||
|
"""Model for creating Brands for products.""" |
||||
|
_name = 'product.brand' |
||||
|
_description = "Product Brand" |
||||
|
_rec_name = 'brand_name' |
||||
|
|
||||
|
brand_name = fields.Char(required=True, string='Name', help='Name of the' |
||||
|
'brand.') |
||||
|
sequence_no = fields.Integer(string="Sequence no", help='Sequence number of' |
||||
|
'brand.') |
||||
|
parent_id = fields.Many2one('product.brand', string='Parent Brand', |
||||
|
index=True, help='Select the parent brand of' |
||||
|
'the brand.') |
@ -0,0 +1,44 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class ProductTemplate(models.Model): |
||||
|
"""Inherited product template for adding the field Hot Sale and Product |
||||
|
Brand. While using the snippet 'Product Tab', the product with enabled |
||||
|
Hot Sale will be display.""" |
||||
|
_inherit = "product.template" |
||||
|
|
||||
|
hot_deals = fields.Boolean(string="Hot Sale", help='The product or services' |
||||
|
'which are high in' |
||||
|
'demand at a particular' |
||||
|
'time or period') |
||||
|
brand_id = fields.Many2one('product.brand', string="Product Brand", |
||||
|
help='Enabled product can filter from website' |
||||
|
'by brand.') |
||||
|
|
||||
|
def _search_get_detail(self, website, order, options): |
||||
|
res = super()._search_get_detail(website, order, options) |
||||
|
if options.get('brand_ids', None): |
||||
|
res['base_domain'].append( |
||||
|
[('brand_id.id', 'in', options['brand_ids'])]) |
||||
|
return res |
@ -0,0 +1,54 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
from odoo import models |
||||
|
|
||||
|
|
||||
|
class ThemeUtils(models.AbstractModel): |
||||
|
_inherit = 'theme.utils' |
||||
|
|
||||
|
def _theme_boec_post_copy(self, mod): |
||||
|
self.enable_view('theme_boec.boec_header') |
||||
|
self.disable_view('website_sale.products_add_to_cart') |
||||
|
self.disable_view('website_sale_comparison.add_to_compare') |
||||
|
self.disable_view('website_sale.product_buy_now') |
||||
|
self.disable_view('website_sale_wishlist.add_to_wishlist') |
||||
|
self.disable_view('website_sale.add_grid_or_list_option') |
||||
|
self.disable_view('website_sale.products_list_view') |
||||
|
self.disable_view('website_sale.alternative_products') |
||||
|
self.disable_view('website_sale.product_buy_now') |
||||
|
self.disable_view('website_sale.product_comment') |
||||
|
self.disable_view('website_sale.product_picture_magnify_both') |
||||
|
self.disable_view('website_sale.product_variants') |
||||
|
self.disable_view('website_sale_comparison.product_attributes_body') |
||||
|
self.disable_view('website_sale.ecom_show_extra_fields') |
||||
|
self.disable_view('website_sale.product_custom_text') |
||||
|
self.disable_view('website_sale.products_add_to_cart') |
||||
|
self.disable_view('website_sale_wishlist.product_add_to_wishlist') |
||||
|
self.disable_view('website_blog.opt_posts_loop_show_author') |
||||
|
self.disable_view('website_blog.opt_posts_loop_show_stats') |
||||
|
self.disable_view('website_blog.opt_posts_loop_show_stats') |
||||
|
self.disable_view('website_blog.opt_blog_list_view') |
||||
|
self.disable_view('website_blog.opt_blog_cards_design') |
||||
|
self.disable_view('website_blog.opt_blog_cover_post') |
||||
|
self.disable_view('website_blog.opt_blog_cover_post_fullwidth_design') |
||||
|
self.disable_view('website_blog.opt_blog_post_breadcrumb') |
||||
|
self.disable_view('website_blog.opt_blog_post_sidebar') |
@ -0,0 +1,31 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
from odoo import models |
||||
|
|
||||
|
|
||||
|
class Website(models.Model): |
||||
|
"""Inherited website fo apply brand feature.""" |
||||
|
_inherit = "website" |
||||
|
|
||||
|
def get_brands(self): |
||||
|
"""Returning all brands""" |
||||
|
return self.env['product.brand'].search([]) |
|
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 733 B |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 673 B |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 905 B |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 627 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 988 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 589 B |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 967 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 1.8 MiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 204 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 323 KiB |
After Width: | Height: | Size: 277 KiB |
After Width: | Height: | Size: 2.0 MiB |
After Width: | Height: | Size: 146 KiB |
After Width: | Height: | Size: 272 KiB |
After Width: | Height: | Size: 236 KiB |
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 204 KiB |
After Width: | Height: | Size: 361 KiB |
After Width: | Height: | Size: 596 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 348 KiB |
After Width: | Height: | Size: 231 KiB |
After Width: | Height: | Size: 386 KiB |
After Width: | Height: | Size: 360 KiB |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 733 B |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 380 KiB |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 542 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 673 B |
After Width: | Height: | Size: 323 KiB |
After Width: | Height: | Size: 632 KiB |
After Width: | Height: | Size: 565 B |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 905 B |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 26 KiB |