diff --git a/product_brand_ecommerce/README.rst b/product_brand_ecommerce/README.rst new file mode 100644 index 000000000..66aed28a1 --- /dev/null +++ b/product_brand_ecommerce/README.rst @@ -0,0 +1,47 @@ +.. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg + :target: https://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +Product Brand In Ecommerce +========================== +* This module allows you to manage the Product brands easily. + +Installation +============ +- www.odoo.com/documentation/17.0/setup/install.html +- Install our custom addon + +License +------- +GNU AFFERO GENERAL PUBLIC LICENSE, Version 3 (AGPLv3) +(https://www.gnu.org/licenses/agpl-3.0-standalone.html) + +Company +------- +* `Cybrosys Techno Solutions `__ + +Credits +------- +* Developers: Afras Habis, + (V15) Midilaj V K, + (V16) Neenu Merlin Jose, + (V17) Akhil Ashok, Contact : odoo@cybrosys.com + +Contacts +-------- +* Mail Contact : odoo@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 + +For support and more information, please visit https://www.cybrosys.com + +Further information +=================== +HTML Description: ``__ diff --git a/product_brand_ecommerce/__init__.py b/product_brand_ecommerce/__init__.py new file mode 100644 index 000000000..296983a93 --- /dev/null +++ b/product_brand_ecommerce/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Akhil Ashok (odoo@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 . +# +############################################################################### +from . import controllers diff --git a/product_brand_ecommerce/__manifest__.py b/product_brand_ecommerce/__manifest__.py new file mode 100644 index 000000000..931cab9d2 --- /dev/null +++ b/product_brand_ecommerce/__manifest__.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Akhil Ashok (odoo@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 . +# +############################################################################### +{ + 'name': 'Product Brand In Ecommerce', + 'version': '17.0.1.0.0', + 'category': 'eCommerce', + 'summary': 'Manage Product brand in eCommerce', + 'description': 'This module allows you to manage the Product brands ' + 'easily.', + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'website': 'https://www.cybrosys.com', + 'depends': ['product_brand_sale', 'website_sale'], + 'data': [ + 'views/product_brand_templates.xml', + 'views/sale_report_views.xml' + ], + 'images': ['static/description/banner.png'], + 'license': 'AGPL-3', + 'installable': True, + 'auto_install': False, + 'application': False, +} diff --git a/product_brand_ecommerce/controllers/__init__.py b/product_brand_ecommerce/controllers/__init__.py new file mode 100644 index 000000000..09c64b328 --- /dev/null +++ b/product_brand_ecommerce/controllers/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Akhil Ashok (odoo@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 . +# +############################################################################### +from . import main diff --git a/product_brand_ecommerce/controllers/main.py b/product_brand_ecommerce/controllers/main.py new file mode 100644 index 000000000..dbd909fa1 --- /dev/null +++ b/product_brand_ecommerce/controllers/main.py @@ -0,0 +1,468 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Akhil Ashok () +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +import logging +from datetime import datetime +from werkzeug.exceptions import NotFound +from odoo import fields, http, tools +from odoo.http import request +from odoo.addons.http_routing.models.ir_http import slug +from odoo.addons.payment.controllers import portal as payment_portal +from odoo.addons.website.controllers.main import QueryURL +from odoo.addons.website.models.ir_http import sitemap_qs2dom +from odoo.tools import lazy + +_logger = logging.getLogger(__name__) + + +class TableCompute(object): + """ + Class for computing the arrangement of products on a grid. + """ + def __init__(self): + self.table = {} + + def _check_place(self, posx, posy, sizex, sizey, ppr): + """ + Check if a specified rectangular area is available in the table. + + Parameters: + - posx (int): The starting x-coordinate of the area. + - posy (int): The starting y-coordinate of the area. + - sizex (int): The width of the area. + - sizey (int): The height of the area. + - ppr (int): Maximum allowed x-coordinate in the table. + + Returns: + bool: True if the area is available, False otherwise. + + The function iterates over the specified area and checks if each cell is + within the bounds of the table and if the cell is unoccupied. It returns + True if the entire area is available; otherwise, it returns False. + """ + res = True + for y in range(sizey): + for x in range(sizex): + if posx + x >= ppr: + res = False + break + row = self.table.setdefault(posy + y, {}) + if row.setdefault(posx + x) is not None: + res = False + break + for x in range(ppr): + self.table[posy + y].setdefault(x, None) + return res + + def process(self, products, ppg=20, ppr=4): + """ + Arrange a list of products on a grid and format the result for HTML + representation. + + Parameters: + - products (list): A list of product objects to be arranged on the + grid. + - ppg (int): The maximum number of products per grid page + (default is 20). + - ppr (int): The maximum number of products per row in the grid + (default is 4). + + Returns: + list: A formatted representation of the arranged products suitable + for HTML rendering.The result is a list of rows, where each row is + a list of dictionaries representing products and their positions on + the grid. + + The function iterates over the list of products and computes their + positions on the grid.It uses a heuristic algorithm to determine the + position of each product, taking into account the dimensions of the + products, the maximum products per page, and the maximum products per + row.The result is formatted as a list of rows, each containing + dictionaries representing the products and their positions on the grid. + """ + # Compute products positions on the grid + minpos = 0 + index = 0 + maxy = 0 + x = 0 + for p in products: + x = min(max(p.website_size_x, 1), ppr) + y = min(max(p.website_size_y, 1), ppr) + if index >= ppg: + x = y = 1 + pos = minpos + while not self._check_place(pos % ppr, pos // ppr, x, y, ppr): + pos += 1 + # if 21st products (index 20) and the last line is full (ppr products in it), break + # (pos + 1.0) / ppr is the line where the product would be inserted + # maxy is the number of existing lines + # + 1.0 is because pos begins at 0, thus pos 20 is actually the 21st block + # and to force python to not round the division operation + if index >= ppg and ((pos + 1.0) // ppr) > maxy: + break + if x == 1 and y == 1: # simple heuristic for CPU optimization + minpos = pos // ppr + + for y2 in range(y): + for x2 in range(x): + self.table[(pos // ppr) + y2][(pos % ppr) + x2] = False + self.table[pos // ppr][pos % ppr] = { + 'product': p, 'x': x, 'y': y, + 'ribbon': p.sudo().website_ribbon_id, + } + if index <= ppg: + maxy = max(maxy, y + (pos // ppr)) + index += 1 + # Format table according to HTML needs + rows = sorted(self.table.items()) + rows = [r[1] for r in rows] + for col in range(len(rows)): + cols = sorted(rows[col].items()) + x += len(cols) + rows[col] = [r[1] for r in cols if r[1]] + return rows + + +class WebsiteSale(payment_portal.PaymentPortal): + + def sitemap_shop(env, rule, qs): + """ + Generate sitemap entries for the Odoo eCommerce 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' % slug(cat) + if not qs or qs.lower() in loc: + yield {'loc': loc} + + @http.route([ + '/shop', + '/shop/page/', + '/shop/category/', + '/shop/category//' + 'page/', + '''/shop/brand/''', + ], type='http', auth="public", website=True, sitemap=sitemap_shop) + def shop(self, page=0, category=None, search='', min_price=0.0, + max_price=0.0, + ppg=False, brand=None, **post): + """ + Render the eCommerce shop page. + + This function handles the rendering of the eCommerce shop page based on + the provided parameters. + It retrieves and filters products, applies pricing rules, and prepares + the data for rendering. + """ + 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 + compute_brand = brand + 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 + product_brand = request.env['product.brand'] + if not brand: + brand = product_brand + 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 + + request_args = request.httprequest.args + attrib_list = request_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} + + 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.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 attrib_list: + post['attrib'] = attrib_list + + 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') + from_clause, where_clause, where_params = query.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 + + if filter_by_tags_enabled: + if ( + search_product.product_tag_ids + or search_product.product_variant_ids.additional_product_tag_ids + ): + ProductTag = request.env['product.tag'] + all_tags = ProductTag.search( + [('product_ids.is_published', '=', True), + ('visible_on_ecommerce', '=', True)] + + website_domain + ) + else: + all_tags = [] + 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" % slug(category) + + pager = website.pager(url=url, total=product_count, page=page, step=ppg, + scope=7, 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 + + # Try to fetch geoip based fpos or fallback on partner one + fiscal_position_sudo = website.fiscal_position_id.sudo() + products_prices = lazy( + lambda: products._get_sales_prices(pricelist, fiscal_position_sudo)) + products_prices_brand = lazy( + lambda: search_product._get_sales_prices(pricelist, fiscal_position_sudo)) + product_brand = request.env['product.brand'].search([]) + if compute_brand: + products_brand = request.env['product.template'].search( + ['&', '&', ('brand_id', '=', brand.id), ('sale_ok', '=', True), + ('is_published', '=', True)]) + product_brand_count = len(products_brand) + pager_brand = request.website.pager(url=url, + total=product_brand_count, + page=page, step=ppg, scope=7, + url_args=post) + values = { + 'search': fuzzy_search_term or search, + 'original_search': fuzzy_search_term and search, + 'order': post.get('order', ''), + 'category': category, + 'brand': brand, + 'attrib_values': attrib_values, + 'attrib_set': attrib_set, + 'pager': pager_brand, + 'pricelist': pricelist, + 'fiscal_position': fiscal_position_sudo, + 'add_qty': add_qty, + 'products': products_brand, + 'search_product': search_product, + 'search_count': product_brand_count, # common for all searchbox + 'bins': lazy( + lambda: TableCompute().process(products_brand, ppg, ppr)), + 'ppg': ppg, + 'ppr': ppr, + 'categories': categs, + 'attributes': attributes, + 'keep': keep, + 'search_categories_ids': search_categories.ids, + 'layout_mode': layout_mode, + 'brands':product_brand, + 'products_prices': products_prices, + 'get_product_prices': lambda product: lazy( + lambda: products_prices_brand[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 filter_by_tags_enabled: + values.update({'all_tags': all_tags, 'tags': tags}) + if category: + values['main_object'] = category + values.update(self._get_additional_shop_values(values)) + return request.render("website_sale.products", values) + else: + values = { + 'brand': brand, + 'search': search, + 'category': category, + 'original_search': fuzzy_search_term and search, + 'order': post.get('order', ''), + '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': lazy( + lambda: TableCompute().process(products, ppg, ppr)), + 'ppg': ppg, + 'ppr': ppr, + 'categories': categs, + 'attributes': attributes, + 'keep': keep, + 'search_categories_ids': search_categories.ids, + 'layout_mode': layout_mode, + 'brands': product_brand, + 'products_prices': products_prices, + 'get_product_prices': lambda product: lazy( + 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 filter_by_tags_enabled: + values.update({'all_tags': all_tags, 'tags': tags}) + if category: + values['main_object'] = category + values.update(self._get_additional_shop_values(values)) + return request.render("website_sale.products", values) diff --git a/product_brand_ecommerce/doc/RELEASE_NOTES.md b/product_brand_ecommerce/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..256239e2f --- /dev/null +++ b/product_brand_ecommerce/doc/RELEASE_NOTES.md @@ -0,0 +1,6 @@ +## Module + +#### 23.04.2024 +#### Version 17.0.1.0.0 +#### ADD +- Initial commit for Product Brand In Ecommerce diff --git a/product_brand_ecommerce/static/description/assets/icons/capture (1).png b/product_brand_ecommerce/static/description/assets/icons/capture (1).png new file mode 100644 index 000000000..8824deafc Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/capture (1).png differ diff --git a/product_brand_ecommerce/static/description/assets/icons/check.png b/product_brand_ecommerce/static/description/assets/icons/check.png new file mode 100644 index 000000000..c8e85f51d Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/check.png differ diff --git a/product_brand_ecommerce/static/description/assets/icons/chevron.png b/product_brand_ecommerce/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..2089293d6 Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/chevron.png differ diff --git a/product_brand_ecommerce/static/description/assets/icons/cogs.png b/product_brand_ecommerce/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/cogs.png differ diff --git a/product_brand_ecommerce/static/description/assets/icons/consultation.png b/product_brand_ecommerce/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/consultation.png differ diff --git a/product_brand_ecommerce/static/description/assets/icons/ecom-black.png b/product_brand_ecommerce/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/ecom-black.png differ diff --git a/product_brand_ecommerce/static/description/assets/icons/education-black.png b/product_brand_ecommerce/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/education-black.png differ diff --git a/product_brand_ecommerce/static/description/assets/icons/hotel-black.png b/product_brand_ecommerce/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/hotel-black.png differ diff --git a/product_brand_ecommerce/static/description/assets/icons/img.png b/product_brand_ecommerce/static/description/assets/icons/img.png new file mode 100644 index 000000000..70197f477 Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/img.png differ diff --git a/product_brand_ecommerce/static/description/assets/icons/license.png b/product_brand_ecommerce/static/description/assets/icons/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/license.png differ diff --git a/product_brand_ecommerce/static/description/assets/icons/lifebuoy.png b/product_brand_ecommerce/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/lifebuoy.png differ diff --git a/product_brand_ecommerce/static/description/assets/icons/manufacturing-black.png b/product_brand_ecommerce/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/manufacturing-black.png differ diff --git a/product_brand_ecommerce/static/description/assets/icons/photo-capture.png b/product_brand_ecommerce/static/description/assets/icons/photo-capture.png new file mode 100644 index 000000000..06c111758 Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/photo-capture.png differ diff --git a/product_brand_ecommerce/static/description/assets/icons/pos-black.png b/product_brand_ecommerce/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/pos-black.png differ diff --git a/product_brand_ecommerce/static/description/assets/icons/puzzle.png b/product_brand_ecommerce/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/puzzle.png differ diff --git a/product_brand_ecommerce/static/description/assets/icons/restaurant-black.png b/product_brand_ecommerce/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/restaurant-black.png differ diff --git a/product_brand_ecommerce/static/description/assets/icons/service-black.png b/product_brand_ecommerce/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/service-black.png differ diff --git a/product_brand_ecommerce/static/description/assets/icons/trading-black.png b/product_brand_ecommerce/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/trading-black.png differ diff --git a/product_brand_ecommerce/static/description/assets/icons/training.png b/product_brand_ecommerce/static/description/assets/icons/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/training.png differ diff --git a/product_brand_ecommerce/static/description/assets/icons/update.png b/product_brand_ecommerce/static/description/assets/icons/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/update.png differ diff --git a/product_brand_ecommerce/static/description/assets/icons/user.png b/product_brand_ecommerce/static/description/assets/icons/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/user.png differ diff --git a/product_brand_ecommerce/static/description/assets/icons/wrench.png b/product_brand_ecommerce/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/icons/wrench.png differ diff --git a/product_brand_ecommerce/static/description/assets/misc/Cybrosys R.png b/product_brand_ecommerce/static/description/assets/misc/Cybrosys R.png new file mode 100644 index 000000000..da4058087 Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/misc/Cybrosys R.png differ diff --git a/product_brand_ecommerce/static/description/assets/misc/email.svg b/product_brand_ecommerce/static/description/assets/misc/email.svg new file mode 100644 index 000000000..15291cdc3 --- /dev/null +++ b/product_brand_ecommerce/static/description/assets/misc/email.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/product_brand_ecommerce/static/description/assets/misc/phone.svg b/product_brand_ecommerce/static/description/assets/misc/phone.svg new file mode 100644 index 000000000..b7bd7f251 --- /dev/null +++ b/product_brand_ecommerce/static/description/assets/misc/phone.svg @@ -0,0 +1,3 @@ + + + diff --git a/product_brand_ecommerce/static/description/assets/misc/star (1) 2.svg b/product_brand_ecommerce/static/description/assets/misc/star (1) 2.svg new file mode 100644 index 000000000..5ae9f507a --- /dev/null +++ b/product_brand_ecommerce/static/description/assets/misc/star (1) 2.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/product_brand_ecommerce/static/description/assets/misc/support (1) 1.svg b/product_brand_ecommerce/static/description/assets/misc/support (1) 1.svg new file mode 100644 index 000000000..7d37a8f30 --- /dev/null +++ b/product_brand_ecommerce/static/description/assets/misc/support (1) 1.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/product_brand_ecommerce/static/description/assets/misc/support-email.svg b/product_brand_ecommerce/static/description/assets/misc/support-email.svg new file mode 100644 index 000000000..eb70370d6 --- /dev/null +++ b/product_brand_ecommerce/static/description/assets/misc/support-email.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/product_brand_ecommerce/static/description/assets/misc/tick-mark.svg b/product_brand_ecommerce/static/description/assets/misc/tick-mark.svg new file mode 100644 index 000000000..2dbb40187 --- /dev/null +++ b/product_brand_ecommerce/static/description/assets/misc/tick-mark.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/product_brand_ecommerce/static/description/assets/misc/whatsapp 1.svg b/product_brand_ecommerce/static/description/assets/misc/whatsapp 1.svg new file mode 100644 index 000000000..0bfaf8fc6 --- /dev/null +++ b/product_brand_ecommerce/static/description/assets/misc/whatsapp 1.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/product_brand_ecommerce/static/description/assets/misc/whatsapp.svg b/product_brand_ecommerce/static/description/assets/misc/whatsapp.svg new file mode 100644 index 000000000..b618aea1d --- /dev/null +++ b/product_brand_ecommerce/static/description/assets/misc/whatsapp.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/product_brand_ecommerce/static/description/assets/modules/1.jpg b/product_brand_ecommerce/static/description/assets/modules/1.jpg new file mode 100644 index 000000000..0edf328e5 Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/modules/1.jpg differ diff --git a/product_brand_ecommerce/static/description/assets/modules/2.gif b/product_brand_ecommerce/static/description/assets/modules/2.gif new file mode 100644 index 000000000..8ac32db03 Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/modules/2.gif differ diff --git a/product_brand_ecommerce/static/description/assets/modules/3.jpg b/product_brand_ecommerce/static/description/assets/modules/3.jpg new file mode 100644 index 000000000..67c7f7062 Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/modules/3.jpg differ diff --git a/product_brand_ecommerce/static/description/assets/modules/4.jpg b/product_brand_ecommerce/static/description/assets/modules/4.jpg new file mode 100644 index 000000000..5141a7802 Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/modules/4.jpg differ diff --git a/product_brand_ecommerce/static/description/assets/modules/5.png b/product_brand_ecommerce/static/description/assets/modules/5.png new file mode 100644 index 000000000..3bedf7981 Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/modules/5.png differ diff --git a/product_brand_ecommerce/static/description/assets/modules/6.jpg b/product_brand_ecommerce/static/description/assets/modules/6.jpg new file mode 100644 index 000000000..482309000 Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/modules/6.jpg differ diff --git a/product_brand_ecommerce/static/description/assets/screenshots/1.png b/product_brand_ecommerce/static/description/assets/screenshots/1.png new file mode 100644 index 000000000..291778ed1 Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/screenshots/1.png differ diff --git a/product_brand_ecommerce/static/description/assets/screenshots/2.png b/product_brand_ecommerce/static/description/assets/screenshots/2.png new file mode 100644 index 000000000..0b339fd57 Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/screenshots/2.png differ diff --git a/product_brand_ecommerce/static/description/assets/screenshots/3.png b/product_brand_ecommerce/static/description/assets/screenshots/3.png new file mode 100644 index 000000000..ddcfb1181 Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/screenshots/3.png differ diff --git a/product_brand_ecommerce/static/description/assets/screenshots/4.png b/product_brand_ecommerce/static/description/assets/screenshots/4.png new file mode 100644 index 000000000..2ccd52748 Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/screenshots/4.png differ diff --git a/product_brand_ecommerce/static/description/assets/screenshots/hero.gif b/product_brand_ecommerce/static/description/assets/screenshots/hero.gif new file mode 100644 index 000000000..09144600b Binary files /dev/null and b/product_brand_ecommerce/static/description/assets/screenshots/hero.gif differ diff --git a/product_brand_ecommerce/static/description/banner.png b/product_brand_ecommerce/static/description/banner.png new file mode 100644 index 000000000..dfcf74a58 Binary files /dev/null and b/product_brand_ecommerce/static/description/banner.png differ diff --git a/product_brand_ecommerce/static/description/icon.png b/product_brand_ecommerce/static/description/icon.png new file mode 100644 index 000000000..1ecc3e8d9 Binary files /dev/null and b/product_brand_ecommerce/static/description/icon.png differ diff --git a/product_brand_ecommerce/static/description/index.html b/product_brand_ecommerce/static/description/index.html new file mode 100644 index 000000000..e363c1807 --- /dev/null +++ b/product_brand_ecommerce/static/description/index.html @@ -0,0 +1,606 @@ + + + + + + Product Brand In Ecommerce + + + + + + + + +
+
+
+
+
+ +
+
+
+ Community +
+
+ Enterprise +
+
+ Odoo.sh +
+
+
+
+
+
+

+ Product Brand In Ecommerce

+

+ Easily Manage Product Brands. +

+
+ +
+
+
+
+
+

Key Highlights +

+
+
+
+
+
+ +
+
+

Activate Product Brand Filter.

+

+ The product brand filter will be displayed on the e-commerce website. +

+
+
+
+
+
+
+ +
+
+

Product Brand in Pivot View.

+

+ User can Filter by product brand in pivot view. +

+
+
+
+
+
+
+ +
+
+

Community & Enterprise Support

+

+ Support in Enterprise and Community versions. +

+
+
+
+
+
+
+ +
+
+
+
+
+ +
+
+

+ The product brand filter will be displayed on the e-commerce website.

+
+
+
+
+
+
+ +
+
+

+ Products in the selected brand.

+
+
+
+
+
+
+ +
+
+

+ Brand filter available in pivot view.

+
+
+
+
+
+
+ +
+
+

+ User can filter by product brand in pivot view.

+
+
+
+
+
+
+
    +
  • + Product Brand Filter will be displayed in the eCommerce website. +
  • +
  • + View of products available under each brand. +
  • +
  • + Brand filter available in pivot view. +
  • +
  • + User can Filter by product brand in pivot view. +
  • +
+
+
+
+
+
+
Version + 17.0.1.0.0|Released on:23rd April 2024 +
+

+ Initial Commit for PRODUCT BRAND IN ECOMMERCE.

+
+
+
+
+
+
+

Related Products

+
+
+ +
+
+

Our Services

+ +
+
+
+
+
+
+
+
+ service-icon +
+
+

Odoo Customization

+
+
+
+
+
+
+ service-icon +
+
+

Odoo Implementation

+
+
+
+
+
+
+ service-icon +
+
+

Odoo Support

+
+
+
+
+
+
+ service-icon +
+
+

Hire Odoo Developer

+
+
+
+
+ +
+
+ service-icon +
+
+

Odoo Integration

+
+
+
+
+
+
+ service-icon +
+
+

Odoo Migration

+
+
+
+
+
+
+ service-icon +
+
+

Odoo Consultancy

+
+
+
+
+
+
+ service-icon +
+
+

Odoo Implementation

+
+
+
+
+
+
+ service-icon +
+
+

Odoo Licensing Consultancy

+
+
+
+
+
+
+

Our Industries

+
+
+
+
+
+
+ +

Trading

+

Easily procure and sell your products

+
+
+
+
+ +

POS

+

Easy configuration and convivial experience

+
+
+
+
+ +

Education

+

A platform for educational management

+
+
+
+
+ +

Manufacturing

+

Plan, track and schedule your operations

+
+
+
+
+ +

E-commerce & Website

+

Mobile friendly, awe-inspiring product pages

+
+
+
+
+ +

Service Management

+

Keep track of services and invoice

+
+
+
+
+ +

Restaurant

+

Run your bar or restaurant methodically

+
+
+
+
+ +

Hotel Management

+

An all-inclusive hotel management application

+
+
+
+
+
+
+

Support

+
+
+
+
+
+
+
+ +
+ Need + Help? +

Got questions or need help? Get in touch.

+
odoo@cybrosys.com +
+
+
+
+
+
+
+
+ +
+ WhatsApp +

Say hi to us on WhatsApp!

+
+91 + 99456767686
+
+
+
+
+
+
+
+
+
+ + + + + + diff --git a/product_brand_ecommerce/views/product_brand_templates.xml b/product_brand_ecommerce/views/product_brand_templates.xml new file mode 100644 index 000000000..a08b1a8ad --- /dev/null +++ b/product_brand_ecommerce/views/product_brand_templates.xml @@ -0,0 +1,28 @@ + + + + + + + diff --git a/product_brand_ecommerce/views/sale_report_views.xml b/product_brand_ecommerce/views/sale_report_views.xml new file mode 100644 index 000000000..7c72b7070 --- /dev/null +++ b/product_brand_ecommerce/views/sale_report_views.xml @@ -0,0 +1,14 @@ + + + + + sale.report.view.search.inherit.product.brand.ecommerce + sale.report + + + + + + + +