| @ -0,0 +1,44 @@ | |||
| .. image:: https://img.shields.io/badge/license-LGPL--3-green.svg | |||
|     :target: https://www.gnu.org/licenses/lgpl-3.0-standalone.html | |||
|     :alt: License: LGPL-3 | |||
| 
 | |||
| Product Bidding In ECommerce | |||
| ============================ | |||
| This module helps you to add auction in website sale. | |||
| 
 | |||
| Configuration | |||
| ============= | |||
| * No additional configurations needed | |||
| 
 | |||
| Company | |||
| ------- | |||
| * `Cybrosys Techno Solutions <https://cybrosys.com/>`__ | |||
| 
 | |||
| License | |||
| ------- | |||
| Lesser General Public License, Version 3 (LGPL v3). | |||
| (http://www.gnu.org/licenses/lgpl-3.0-standalone.html) | |||
| 
 | |||
| Credits | |||
| ------- | |||
| * Developers: (V17) Anfas Faisal K, 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: Anfas Faisal K (odoo@cybrosys.com) | |||
| # | |||
| #    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 <http://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################### | |||
| from . import controllers | |||
| from . import models | |||
| @ -0,0 +1,60 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Anfas Faisal K (odoo@cybrosys.com) | |||
| # | |||
| #    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 <http://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################### | |||
| { | |||
|     'name': 'Product Bidding In ECommerce', | |||
|     'version': '17.0.1.0.0', | |||
|     'category': 'Website', | |||
|     'summary': 'App To Add Bidding option In Website', | |||
|     'description': 'Website Bargain is an application where users can create ' | |||
|                    'and manage bargains on their website, enabling their ' | |||
|                    'customers to participate in bidding and negotiate prices ' | |||
|                    'for products or services', | |||
|     'author': 'Cybrosys Techno Solution', | |||
|     'company': 'Cybrosys Techno Solutions', | |||
|     'maintainer': 'Cybrosys Techno Solution', | |||
|     'website': 'https://www.cybrosys.com', | |||
|     'depends': ['website_sale', 'contacts'], | |||
|     'data': [ | |||
|         'security/ir.model.access.csv', | |||
|         'data/ir_cron_data.xml', | |||
|         'data/mail_template_data.xml', | |||
|         'views/website_bargain_views.xml', | |||
|         'views/bargain_template_views.xml', | |||
|         'views/bargain_information_views.xml', | |||
|         'views/bargain_subscribers_views.xml', | |||
|         'views/product_template_views.xml', | |||
|         'views/website_shop_auction_templates.xml', | |||
|         'views/website_product_views_templates.xml', | |||
|         'views/website_bargain_menus.xml', | |||
|         'views/bidders_information_templates.xml' | |||
|     ], | |||
|     'assets': { | |||
|         'web.assets_frontend': [ | |||
|             'website_bargain/static/src/js/website_bargain.js', | |||
|             'website_bargain/static/src/css/website_product_bargain.css', | |||
|         ]}, | |||
|     'images': ['static/description/banner.jpg'], | |||
|     'license': 'LGPL-3', | |||
|     'installable': True, | |||
|     'auto-install': False, | |||
|     'application': False, | |||
| } | |||
| @ -0,0 +1,22 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Anfas Faisal K (odoo@cybrosys.com) | |||
| # | |||
| #    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 <http://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################### | |||
| from . import website_bargain | |||
| @ -0,0 +1,353 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Anfas Faisal K (odoo@cybrosys.com) | |||
| # | |||
| #    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 <http://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################### | |||
| from odoo import fields, http | |||
| from odoo.addons.website_sale.controllers.main import WebsiteSale | |||
| from odoo.http import request | |||
| 
 | |||
| 
 | |||
| class WebsiteAuction(WebsiteSale): | |||
|     """This class enables is used to view the timer and related functions | |||
|         of bidding,buy now and other routes | |||
|         _prepare_product_values(self, product, category, search, **kwargs): | |||
|                 This function is inbuilt function in website sale and its | |||
|                 supered here and pass auction values in this function | |||
|         auction_timer(self, auction_id): | |||
|                 This function gets the auction id and pass auction timing | |||
|                 details to website | |||
|         buy_now(self, auction_id, product_id): | |||
|                 Its the function for button in buy now,in this function a new | |||
|                 sale order is created and send to the customer through email | |||
|         def auction_close(self, auction_id): | |||
|                 Function gets the auction id and move the auction stage to | |||
|                 finished and make the product unavailable from website | |||
|         winner_sale_order(self, auction_id, **post): | |||
|                 Makes a sale order to the winner and id notifications are | |||
|                 enabled it will send a email to the winners or losers | |||
|         subscribe(self, auction_id, **post): | |||
|                 Used to add subscribers from website to database | |||
|         place_bid(self, auction_id, **post): | |||
|                 When place bid button is triggered it will call this function | |||
|                  and the bidders details will be added to database and | |||
|                   if enabled it will send notification to subscribers | |||
|         bidders(self, product_id): | |||
|                 Route to pass bidders details to website | |||
|         bid_cancel(self, bidders): | |||
|                 Function to cancel the bid""" | |||
| 
 | |||
|     def _prepare_product_values(self, product, category, search, **kwargs): | |||
|         """Summary: | |||
|                 Function is used to pass auction details by supering | |||
|                 this function because its already defined it websitesale | |||
|             Args: | |||
|                 product:pass the object product | |||
|                 category:pass the category if enabled | |||
|                 kwargs:used to pass variable to function | |||
|             Return: | |||
|                 Values is updated with auction and current website and | |||
|                  passed to website sale""" | |||
|         values = super()._prepare_product_values(product, category, search, | |||
|                                                  **kwargs) | |||
|         current_website = request.website | |||
|         auction = request.env['website.bargain'].sudo().search_read([]) | |||
|         values.update({ | |||
|             'auction': auction, | |||
|             'website': current_website | |||
|         }) | |||
|         return values | |||
| 
 | |||
|     @http.route('/auction/timer', type='json', auth='user', csrf=False) | |||
|     def auction_timer(self, auction_id): | |||
|         """Summary: | |||
|                 Function to pass timer details from auction like start | |||
|                  time,end time,extended time | |||
|             Args: | |||
|                 auction_id:used to get auction id from website | |||
|             Return: | |||
|                 Values which include start_time,end time,extended | |||
|                  time and state id""" | |||
|         auction = request.env['website.bargain'].sudo().browse(int(auction_id)) | |||
|         values = { | |||
|             'start_time': auction.start_time, | |||
|             'end_time': fields.Datetime.context_timestamp(auction, | |||
|                                                           auction.end_time), | |||
|             'state': auction.state, | |||
|         } | |||
|         if auction.extend_time: | |||
|             values['extend_time'] = fields.Datetime.context_timestamp(auction, | |||
|                                                                       auction.extend_time) | |||
|         return values | |||
| 
 | |||
|     @http.route('/auction/close', type='json', auth='user', csrf=False) | |||
|     def auction_close(self, auction_id): | |||
|         """Summary: | |||
|             Function to close auction when a customer buys | |||
|             a product instantly or the auction is ended | |||
|         Args: | |||
|             auction_id: used to get auction id from website | |||
|         Return: | |||
|             a string auction ended to website""" | |||
|         auction = request.env['website.bargain'].sudo().browse(int(auction_id)) | |||
|         auction.product_id.is_auction = False | |||
|         auction.product_id.is_published = False | |||
|         auction.write({'state': 'finished'}) | |||
|         return "auction ended" | |||
| 
 | |||
|     @http.route('/place_bid', type='json', auth='user', csrf=False) | |||
|     def place_bid(self, auction_id, **post): | |||
|         """Summary: | |||
|                 When place bid button is clicked it will trigger this function | |||
|                  and will add bidders details to backend and will send | |||
|                  notification to the subscribers if its enabled | |||
|             Args: | |||
|                 auction_id:used to get auction id from website | |||
|                 post:used to get bid amount from frontend | |||
|             Return: | |||
|                 A message bid placed and suction details""" | |||
|         bid_amount = post.get('bid_amount') | |||
|         auction = request.env['website.bargain'].sudo().browse(int(auction_id)) | |||
|         bidder_total = auction.bargain_information_ids.search_count( | |||
|             [('bidder_id', '=', request.env.user.partner_id.id), | |||
|              ('bid_offer', '=', bid_amount)]) | |||
|         if bidder_total >= 1: | |||
|             return False | |||
|         else: | |||
|             auction.bargain_information_ids.sudo().create({ | |||
|                 'bidder_id': request.env.user.partner_id.id, | |||
|                 'auction_id': auction.id, | |||
|                 'bid_offer': bid_amount, | |||
|                 'status': 'Bid Placed' | |||
|             }) | |||
|             if auction.is_subscriber_start_notification and not auction.is_send_mail: | |||
|                 data = 'Bidding has started for ' + auction.name + '. Please check our website for more details.' | |||
|                 subscribers = "" | |||
|                 for record in auction.bargain_subscribers_ids: | |||
|                     subscribers += record.subscriber_id.email + ',' | |||
|                 email_values = {'email_from': auction.auction_manager_id.email, | |||
|                                 'subject': 'Bidding Started for ' + auction.name, | |||
|                                 'email_to': subscribers, 'body_html': data} | |||
|                 request.env['mail.mail'].sudo().create(email_values).send() | |||
|                 auction.is_send_mail = True | |||
|                 auction.write({'is_send_mail': True}) | |||
| 
 | |||
|             if auction.is_new_bid_notification: | |||
|                 data = 'A new bid has been placed with amount ' + str( | |||
|                     bid_amount) + ',on ' \ | |||
|                        + auction.name + ',by ' + request.env.user.partner_id.name \ | |||
|                        + 'please check into ' \ | |||
|                          'our website' | |||
|                 subscribers = " " | |||
|                 for record in auction.bargain_subscribers_ids: | |||
|                     subscribers += record.subscriber_id.email + ',' | |||
|                 email_values = {'email_from': auction.auction_manager_id.email, | |||
|                                 'subject': 'New Bid Placed on ' + auction.name, | |||
|                                 'email_to': subscribers, 'body_html': data} | |||
|                 request.env['mail.mail'].sudo().create(email_values).send() | |||
|             values = ({ | |||
|                 'bid_placed': 'Bid Placed', | |||
|                 'auction': auction | |||
|             }) | |||
| 
 | |||
|             return values | |||
| 
 | |||
|     @http.route('/bidders/<model("product.template"):product_id>', type='http', | |||
|                 auth='user', csrf=False, website=True) | |||
|     def bidders(self, product_id): | |||
|         """ | |||
|         This method is used to fetch the details of the bidders participating in | |||
|          an auction and render them on the website. | |||
|         Args: | |||
|             product_id: A product template model object. | |||
|         Returns: | |||
|             A rendered HTML template with information about the bidders in the | |||
|             auction.""" | |||
|         auction = request.env['website.bargain'].sudo().search( | |||
|             [('product_id', '=', product_id.id), ('state', '=', 'running')]) | |||
|         bidders_information = request.env['bargain.information'].sudo().search( | |||
|             [('auction_id', '=', auction.id)], | |||
|             order='bid_offer desc') | |||
|         values = ({ | |||
|             'bidders_information': bidders_information, | |||
|             'product_id': product_id, | |||
|         }) | |||
|         return request.render('website_bargain.bidders_information', values) | |||
| 
 | |||
|     @http.route('/bid/cancel/<model("bargain.information"):bidders>', | |||
|                 type='http', auth='user', csrf='false') | |||
|     def bid_cancel(self, bidders): | |||
|         """This function is for cancel the bid | |||
|             Args: | |||
|                 bidders:Bidders name will be getting here | |||
|             Returns:It returns previous page""" | |||
|         bidders.status = 'cancelled' | |||
|         previous_web_url = request.httprequest.headers.get('referer') | |||
|         return request.redirect(previous_web_url) | |||
| 
 | |||
|     @http.route('/shop/sale/order', type='json', auth='public', website=True, | |||
|                 csrf=False) | |||
|     def winner_sale_order(self, auction_id, **post): | |||
|         """ | |||
|             This route creates a draft sale order for the winner of an auction | |||
|             and sends notifications for winning and losing. | |||
|         Args: | |||
|             auction_id: the ID of the auction obtained from the frontend | |||
|             post: used to get data of product from frontend | |||
|         Returns: | |||
|             True""" | |||
|         # Get the ID of the product from the post data | |||
|         product_product_id = post.get('product_product_id') | |||
|         # Find the auction with the given ID | |||
|         auction = request.env['website.bargain'].sudo().browse(int(auction_id)) | |||
|         auction.write({'state': 'finished'}) | |||
|         if auction.is_bid_end_notification: | |||
|             data = 'Bidding has ended for ' + auction.name + '. Thank you for participating.' | |||
|             subscribers = "" | |||
|             for record in auction.bargain_subscribers_ids: | |||
|                 subscribers += record.subscriber_id.email + ',' | |||
|             email_values = {'email_from': auction.auction_manager_id.email, | |||
|                             'subject': 'Bidding Ended for ' + auction.name, | |||
|                             'email_to': subscribers, 'body_html': data} | |||
|             request.env['mail.mail'].sudo().create(email_values).send() | |||
|         # Find the highest bidder for the auction | |||
|         bid_record = auction.bargain_information_ids.filtered( | |||
|             lambda r: r.status == 'Bid Placed').sorted( | |||
|             key=lambda r: r.bid_offer)[-1] | |||
|         # Create a draft sale order for the winner | |||
|         sale_order = request.env['sale.order'].sudo().create({ | |||
|             'partner_id': bid_record.bidder_id.id, | |||
|             'state': 'draft', | |||
|         }) | |||
|         # Add the product to the sale order and set the price to the bid offer | |||
|         sale_order.sudo().write({ | |||
|             'order_line': [(0, 0, { | |||
|                 'product_id': int(product_product_id), | |||
|                 'product_uom_qty': 1, | |||
|                 'price_unit': bid_record.bid_offer, | |||
|                 'name': 'auction won', | |||
|             })] | |||
|         }) | |||
|         mail_compose_message = request.env['mail.compose.message'] | |||
|         so_mcm_vals = sale_order.sudo().action_quotation_send().get('context', | |||
|                                                                     {}) | |||
|         compose_msg = mail_compose_message.sudo().with_context( | |||
|             so_mcm_vals).create({}) | |||
|         compose_msg.sudo().action_send_mail() | |||
|         # Send a notification email to the winner and/or losers, if enabled | |||
|         if auction.is_winner_notification: | |||
|             data = "You have won in " + auction.name + " Kindly pay now and" \ | |||
|                                                        " collect the product " \ | |||
|                                                        "from our website" | |||
|             email_values = { | |||
|                 'email_from': auction.auction_manager_id.email, | |||
|                 'subject': 'Won ' + auction.name, | |||
|                 'email_to': bid_record.bidder_id.email, | |||
|                 'body_html': data | |||
|             } | |||
|             request.env['mail.mail'].sudo().create(email_values).send() | |||
|         if auction.is_loser_notification: | |||
|             data = "You have lost in " + auction.name + "Better luck next time"\ | |||
|                                                         " thank you for your " \ | |||
|                                                         "effort and time" | |||
|             email_to = '' | |||
|             for record in auction.bargain_information_ids: | |||
|                 if record.bidder_id.id != bid_record.bidder_id.id: | |||
|                     email_to += record.bidder_id.email + ',' | |||
|             email_values = { | |||
|                 'email_from': auction.auction_manager_id.email, | |||
|                 'subject': 'Lost ' + auction.name, | |||
|                 'email_to': email_to, | |||
|                 'body_html': data | |||
|             } | |||
|             request.env['mail.mail'].sudo().create(email_values).send() | |||
|         return True | |||
| 
 | |||
|     @http.route('/subscribe/bid', type='json', auth='user', csrf=False) | |||
|     def subscribe(self, auction_id, **post): | |||
|         """ | |||
|         Endpoint to manage subscription to an auction | |||
|          auction_id: integer ID of the auction being subscribed to/unsubscribed | |||
|          text: string indicating whether the user is subscribing or | |||
|          unsubscribing ('subscribe' or 'unsubscribe') | |||
|         return: string message indicating success or failure of | |||
|         subscription/unsubscription action | |||
|         """ | |||
|         text = post.get('text') | |||
|         auction = request.env['website.bargain'].sudo().browse(int(auction_id)) | |||
|         if text == 'subscribe': | |||
|             if request.env.user.partner_id in \ | |||
|                     auction.bargain_subscribers_ids.subscriber_id: | |||
|                 return 'You have already subscribed' | |||
|             auction.bargain_subscribers_ids.sudo().create({ | |||
|                 'subscriber_id': request.env.user.partner_id.id, | |||
|                 'auction_id': auction.id, | |||
|                 'is_subscribed': True | |||
|             }) | |||
|             return 'You have been successfully subscribed to this auction' | |||
|         elif text == 'unsubscribe': | |||
|             auction.bargain_subscribers_ids.sudo().search( | |||
|                 [('subscriber_id', '=', request.env.user.partner_id.id), | |||
|                  ('auction_id', '=', auction.id)]).unlink() | |||
|             return 'Unsubscribed successfully' | |||
| 
 | |||
|     @http.route('/subscribe/status', type='json', auth='user', csrf=False) | |||
|     def subscribe_status(self, auction_id,  **post): | |||
|         """ | |||
|         Controller method to handle subscription to an auction. | |||
|         """ | |||
|         auction = request.env['website.bargain'].sudo().browse(int(auction_id)) | |||
|         is_subscribed = False | |||
|         for subscriber in auction.bargain_subscribers_ids: | |||
|             if subscriber.subscriber_id == request.env.user.partner_id: | |||
|                 is_subscribed = subscriber.is_subscribed | |||
|                 break | |||
| 
 | |||
|         return is_subscribed | |||
| 
 | |||
|     @http.route('/buy/now', type='json', auth='public', website=True, | |||
|                 csrf=False) | |||
|     def buy_now(self, auction_id, product_id): | |||
|         """ | |||
|         Args: | |||
|             auction_id: the ID of the auction obtained from the frontend | |||
|             product_id: the ID of the product used to get data from the frontend | |||
|         """ | |||
|         # Find the auction with the given ID | |||
|         auction = request.env['website.bargain'].sudo().browse(int(auction_id)) | |||
|         # Create a draft sale order for the winner | |||
|         sale_order = request.env['sale.order'].sudo().create({ | |||
|             'partner_id': request.env.user.partner_id.id, | |||
|             'state': 'draft', | |||
|         }) | |||
|         sale_order.sudo().write({ | |||
|             'order_line': [(0, 0, { | |||
|                 'product_id': int(product_id), | |||
|                 'product_uom_qty': 1, | |||
|                 'name': '(auction won)' + auction.name, | |||
|                 'price_unit': auction.price_buy_now, | |||
|             })] | |||
|         }) | |||
|         # Send a notification email to the winner | |||
|         mail_compose_message = request.env['mail.compose.message'] | |||
|         so_mcm_vals = sale_order.sudo().action_quotation_send().get('context', | |||
|                                                                     {}) | |||
|         compose_msg = mail_compose_message.sudo().with_context( | |||
|             so_mcm_vals).create({}) | |||
|         compose_msg.sudo().action_send_mail() | |||
| @ -0,0 +1,25 @@ | |||
| <?xml version="1.0" encoding="UTF-8" ?> | |||
| <odoo> | |||
|     <!-- Cron action for automatic email notifications --> | |||
|     <record id="ir_cron_auto_send_email_admin" model="ir.cron"> | |||
|         <field name="name">Auction: Email Notification</field> | |||
|         <field name="model_id" ref="model_website_bargain"/> | |||
|         <field name="state">code</field> | |||
|         <field name="code">model.send_email_notification()</field> | |||
|         <field name="interval_number">1</field> | |||
|         <field name="interval_type">minutes</field> | |||
|         <field name="numbercall">-1</field> | |||
|         <field name="doall" eval="False"/> | |||
|     </record> | |||
|     <!-- Cron action for auction auto start --> | |||
|     <record id="ir_cron_auto_start_auction"  model="ir.cron"> | |||
|         <field name="name">Auction: Auto Start</field> | |||
|         <field name="model_id" ref="model_website_bargain"/> | |||
|         <field name="state">code</field> | |||
|         <field name="code">model.auction_auto_start()</field> | |||
|         <field name="interval_number">1</field> | |||
|         <field name="interval_type">minutes</field> | |||
|         <field name="numbercall">-1</field> | |||
|         <field name="doall" eval="False"/> | |||
|     </record> | |||
| </odoo> | |||
| @ -0,0 +1,104 @@ | |||
| <?xml version="1.0" encoding="UTF-8" ?> | |||
| <odoo> | |||
|     <!-- Email template for admin notification --> | |||
|     <record id="admin_email_template" model="mail.template"> | |||
|         <field name="name">Auction: Admin Notification Email</field> | |||
|         <field name="model_id" ref="website_bargain.model_website_bargain"/> | |||
|         <field name="email_from">{{ | |||
|             (object.auction_manager_id.partner_id.email) }} | |||
|         </field> | |||
|         <field name="email_to">{{ | |||
|             (object.auction_manager_id.partner_id.email) }} | |||
|         </field> | |||
|         <field name="subject">{{ (object.name) }} end time is near</field> | |||
|         <field name="body_html" type="html"> | |||
|             <div style="margin: 0px; padding: 0px;"> | |||
|                 <p style="margin: 0px; padding: 0px; font-size: 13px"> | |||
|                     Dear | |||
|                     <t t-if="object.auction_manager_id.name"> | |||
|                         <t t-out="object.auction_manager_id.name"/> | |||
|                     </t> | |||
|                     <br/> | |||
|                     <br/> | |||
|                     This mail is a reminder that | |||
|                     <t t-if="object.name"> | |||
|                         <span style="font-weight:bold;" t-out="object.name"> | |||
|                             Auction | |||
|                         </span> | |||
|                     </t> | |||
|                     will end at | |||
|                     <t t-if="object.end_time"> | |||
|                         <span style="font-weight:bold;" | |||
|                               t-out="object.end_time">End Time | |||
|                         </span> | |||
|                     </t> | |||
|                     .So if its need to be | |||
|                     extended kindly reminding you to extend it fast. | |||
|                 </p> | |||
|             </div> | |||
|         </field> | |||
|     </record> | |||
|     <!-- Email template for auction start notification --> | |||
|     <record id="email_template_auction_start" model="mail.template"> | |||
|         <field name="name">Auction: Auction Start Notification Email</field> | |||
|         <field name="model_id" ref="website_bargain.model_website_bargain"/> | |||
|         <field name="email_from">{{ | |||
|             (object.auction_manager_id.partner_id.email) }} | |||
|         </field> | |||
|         <field name="subject">{{ (object.name) }} has started</field> | |||
|         <field name="body_html" type="html"> | |||
|             <div style="margin: 0px; padding: 0px;"> | |||
|                 <p style="margin: 0px; padding: 0px; font-size: 13px"> | |||
|                     Dear Sir/Madam | |||
|                     <br/> | |||
|                     <br/> | |||
|                     This mail is a reminder that | |||
|                     <t t-if="object.name"> | |||
|                         <span style="font-weight:bold;" t-out="object.name"> | |||
|                             Auction | |||
|                         </span> | |||
|                     </t> | |||
|                     has started | |||
|                     <t t-if="object.start_time"> | |||
|                         <span style="font-weight:bold;" | |||
|                               t-out="object.end_time">Start Time Time | |||
|                         </span> | |||
|                     </t> | |||
|                     .Place your bids and win the auction. | |||
|                 </p> | |||
|             </div> | |||
|         </field> | |||
|     </record> | |||
|     <!-- Email template for auction extended notification --> | |||
|     <record id="email_template_auction_extended" model="mail.template"> | |||
|         <field name="name">Auction: Auction Extend Notification Email | |||
|         </field> | |||
|         <field name="model_id" ref="website_bargain.model_website_bargain"/> | |||
|         <field name="email_from">{{ | |||
|             (object.auction_manager_id.partner_id.email) }} | |||
|         </field> | |||
|         <field name="subject">{{ (object.name) }} has extended</field> | |||
|         <field name="body_html" type="html"> | |||
|             <div style="margin: 0px; padding: 0px;"> | |||
|                 <p style="margin: 0px; padding: 0px; font-size: 13px"> | |||
|                     Dear Sir/Madam | |||
|                     <br/> | |||
|                     <br/> | |||
|                     This mail is a reminder that | |||
|                     <t t-if="object.name"> | |||
|                         <span style="font-weight:bold;" t-out="object.name"> | |||
|                             Auction | |||
|                         </span> | |||
|                     </t> | |||
|                     has extended | |||
|                     <t t-if="object.extend_time"> | |||
|                         <span style="font-weight:bold;" | |||
|                               t-out="object.extend_time">Extended Time Time | |||
|                         </span> | |||
|                     </t> | |||
|                     .Place your bids and win the auction. | |||
|                 </p> | |||
|             </div> | |||
|         </field> | |||
|     </record> | |||
| </odoo> | |||
| @ -0,0 +1,7 @@ | |||
| ## Module <website_bargain> | |||
| 
 | |||
| #### 05.04.2024 | |||
| #### Version 17.0.1.0.0 | |||
| #### ADD | |||
| 
 | |||
| - Initial Commit for Product Bidding In ECommerce | |||
| @ -0,0 +1,26 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Anfas Faisal K (odoo@cybrosys.com) | |||
| # | |||
| #    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 <http://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################### | |||
| from . import bargain_information | |||
| from . import bargain_subscribers | |||
| from . import bargain_template | |||
| from . import product_template | |||
| from . import website_bargain | |||
| @ -0,0 +1,44 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Anfas Faisal K (odoo@cybrosys.com) | |||
| # | |||
| #    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 <http://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################### | |||
| from odoo import fields, models | |||
| 
 | |||
| 
 | |||
| class BargainInformation(models.Model): | |||
|     """Class for adding bidder details to the database""" | |||
|     _name = 'bargain.information' | |||
|     _rec_name = 'auction_id' | |||
|     _description = "Bidder Details" | |||
|     _inherit = ['mail.thread', 'mail.activity.mixin'] | |||
| 
 | |||
|     bidder_id = fields.Many2one('res.partner', string='Bidder', required=True, | |||
|                                 help="Bidders details") | |||
|     auction_id = fields.Many2one('website.bargain', string='Auction', | |||
|                                  required=True, help="Auction Details") | |||
|     currency_id = fields.Many2one(related="auction_id.currency_id", | |||
|                                   help="Currency Details") | |||
|     bid_offer = fields.Monetary(string="Bid Offer", | |||
|                                 currency_field='currency_id', | |||
|                                 help="Offered amount") | |||
|     status = fields.Char(string="Status", readonly=True, | |||
|                          help="Current Status of bid") | |||
|     product_id = fields.Many2one(related='auction_id.product_id', | |||
|                                  string='Product', help="Product details") | |||
| @ -0,0 +1,45 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Anfas Faisal K (odoo@cybrosys.com) | |||
| # | |||
| #    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 <http://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################### | |||
| from odoo import fields, models | |||
| 
 | |||
| 
 | |||
| class BargainSubscribers(models.Model): | |||
|     """Model for adding the subscriber details """ | |||
|     _name = 'bargain.subscribers' | |||
|     _inherit = ['mail.thread', 'mail.activity.mixin'] | |||
|     _description = "Subscriber details" | |||
| 
 | |||
|     subscriber_id = fields.Many2one('res.partner', required=True, | |||
|                                     help="Subscribers id will be here ") | |||
|     name = fields.Char(related='subscriber_id.name', string='Name', | |||
|                        readonly=False, help="Subscribers name", | |||
|                        required=True) | |||
|     email = fields.Char(related='subscriber_id.email', string='Email', | |||
|                         readonly=False, help="Subscribers email") | |||
|     auction_id = fields.Many2one('website.bargain', string='Auction', | |||
|                                  required=True, help="Auction details") | |||
|     subscribe_time = fields.Datetime(string='Subscribe On', | |||
|                                      default=fields.Datetime.today(), | |||
|                                      readonly=True, | |||
|                                      help="Time of subscription") | |||
|     is_subscribed = fields.Boolean(string="Is Subscribed", | |||
|                                    help="Check if Subscribed or not") | |||
| @ -0,0 +1,36 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Anfas Faisal K (odoo@cybrosys.com) | |||
| # | |||
| #    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 <http://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################### | |||
| from odoo import fields, models | |||
| 
 | |||
| 
 | |||
| class BargainTemplate(models.Model): | |||
|     """Model for auction template""" | |||
| 
 | |||
|     _name = 'bargain.template' | |||
|     _inherit = ['mail.thread', 'mail.activity.mixin'] | |||
|     _description = "Bargain Template" | |||
| 
 | |||
|     name = fields.Char(string='Template Name', help="Name of the template") | |||
|     product_id = fields.Many2one('product.template', | |||
|                                  domain=[('is_published', '=', True)], | |||
|                                  required=True, | |||
|                                  help="Choose the product from the list") | |||
| @ -0,0 +1,31 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Anfas Faisal K (odoo@cybrosys.com) | |||
| # | |||
| #    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 <http://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################### | |||
| from odoo import fields, models | |||
| 
 | |||
| 
 | |||
| class ProductTemplateInherit(models.Model): | |||
|     """Model to add a new boolean field to product template""" | |||
|     _inherit = 'product.template' | |||
| 
 | |||
|     is_auction = fields.Boolean(string='Auction On', readonly=True, | |||
|                                 help="If auction is on this field will be true" | |||
|                                 ) | |||
| @ -0,0 +1,301 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Anfas Faisal K (odoo@cybrosys.com) | |||
| # | |||
| #    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 <http://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################### | |||
| from datetime import timedelta | |||
| from odoo import api, fields, models, _ | |||
| from odoo.exceptions import ValidationError | |||
| 
 | |||
| 
 | |||
| class WebsiteBargain(models.Model): | |||
|     """This is the main class of website bargain where all the details are | |||
|         stored in this model | |||
|         _onchange_template_id: | |||
|             function for automatically add the auction name | |||
|         _check_end_date: | |||
|             function to validate the end date if it is higher than the start | |||
|             date | |||
|         _check_extend_time: | |||
|             function to validate extended time weather it is greater than end | |||
|             time and after saving will send notification to subscribers if | |||
|             enabled | |||
|         action_confirm: | |||
|             button function to confirm auction and will make product as | |||
|             published | |||
|         action_reset_to_draft: | |||
|             button function to reset the auction to draft | |||
|         action_run_auction: | |||
|             button function to start auction manually | |||
|         action_complete: | |||
|             button function to end auction manually | |||
|         action_close: | |||
|             button function to close auction | |||
|         send_email_notification: | |||
|                 Function for sending auction notification for admin | |||
|                  before ending if enabled | |||
|         auction_auto_start: | |||
|                 Cron function for auction auto start when its start | |||
|                 time and also will send notification to customers about auction | |||
|     """ | |||
|     _name = 'website.bargain' | |||
|     _description = "Website Bargain" | |||
|     _inherit = ['mail.thread', 'mail.activity.mixin'] | |||
| 
 | |||
|     website_id = fields.Many2one('website', string='Website', required=True, | |||
|                                  help="Add website here to put auction") | |||
|     template_id = fields.Many2one('bargain.template', string='Template', | |||
|                                   help="add already created templates of " | |||
|                                        "auction with products") | |||
|     auction_manager_id = fields.Many2one('res.users', string="Auction Manager", | |||
|                                          help="Set suction manager here", | |||
|                                          required=True) | |||
|     product_id = fields.Many2one(related='template_id.product_id', store=True, | |||
|                                  string='Product', readonly=False, | |||
|                                  help="Select the product", required=True) | |||
|     name = fields.Char(string='Auction Name', help="Auctions name") | |||
|     currency_id = fields.Many2one('res.currency', 'Currency', | |||
|                                   default=lambda | |||
|                                       self: self.env.user.company_id.currency_id.id, | |||
|                                   required=True, | |||
|                                   help="if you select this " | |||
|                                        "currency bidding will " | |||
|                                        "be on that currency itself") | |||
|     initial_price = fields.Monetary(string='Initial Price', | |||
|                                     currency_field='currency_id', | |||
|                                     required=True, | |||
|                                     help="Minimum amount required to bid") | |||
|     is_buy_now = fields.Boolean(string='Provide buy now button', | |||
|                                 help='Enable a button for buying instantly') | |||
|     price_buy_now = fields.Monetary(string='Buy Now Price', | |||
|                                     currency_field='currency_id', | |||
|                                     help="Price of the product if its" | |||
|                                          " immediately buying") | |||
|     start_time = fields.Datetime(string='Start Date Time', required=True, | |||
|                                  default=fields.Datetime.today(), | |||
|                                  help="Auction start time") | |||
|     end_time = fields.Datetime(string='End Date Time', required=True, | |||
|                                help="Auction start time") | |||
|     extend_time = fields.Datetime(string="Extended Time", | |||
|                                   help="By setting days you can " | |||
|                                        "extend the auction") | |||
|     state = fields.Selection( | |||
|         [('draft', "Draft"), ('confirmed', "Confirmed"), | |||
|          ('running', "Running"), | |||
|          ('closed', "Closed"), ('finished', "Finished")], default='draft') | |||
|     bargain_information_ids = fields.One2many('bargain.information', | |||
|                                               'auction_id', readonly=True) | |||
|     bargain_subscribers_ids = fields.One2many('bargain.subscribers', | |||
|                                               'auction_id') | |||
|     is_activate = fields.Boolean(string='Activate', | |||
|                                  help='this will activate ' | |||
|                                       'notification for the admins') | |||
|     notify_on = fields.Integer(string='Notify before', default='5', | |||
|                                help="Set notification time here") | |||
|     notify_selection = fields.Selection( | |||
|         [('days', "Days"), ('hours', "Hours"), ('minutes', "Minutes"), | |||
|          ('seconds', "Seconds")], default='minutes') | |||
|     is_notification_send = fields.Boolean(string='Notification Send', | |||
|                                           help='If notification send manually ' | |||
|                                                'you can enable this field ' | |||
|                                                'to restrict ' | |||
|                                                'sending notification before ' | |||
|                                                'the time added') | |||
|     is_winner_notification = fields.Boolean( | |||
|         string='Send Notification to Winner', | |||
|         help='Enable this option to send notification to the winner') | |||
|     is_loser_notification = fields.Boolean(string='Send Notification to Loser', | |||
|                                            help='Enable this option to send ' | |||
|                                                 'notification to the losers') | |||
|     is_subscriber_start_notification = fields.Boolean(string='Bidding Start', | |||
|                                                       help="Send subscribers " | |||
|                                                            "the bidding start " | |||
|                                                            "notification") | |||
|     is_send_mail = fields.Boolean(string='Bidding Started Mail Sent', | |||
|                                   help='If Bidding mail has been sent to customer') | |||
|     is_extend_auction_notification = fields.Boolean(string='Auction Extended', | |||
|                                                     help="Send subscribers the" | |||
|                                                          "bidding extended " | |||
|                                                          "notification") | |||
|     is_new_bid_notification = fields.Boolean(string='New Bid Placed', | |||
|                                              help="Send subscribers " | |||
|                                                   "notifications if new bids" | |||
|                                                   " are placed") | |||
|     is_bid_end_notification = fields.Boolean(string='Auction Finished', | |||
|                                              help="Send subscribers " | |||
|                                                   "notifications if bidding " | |||
|                                                   "is over") | |||
|     product_img = fields.Binary(related="product_id.image_1920") | |||
|     product_description = fields.Text(related="product_id.description_sale", | |||
|                                       string="Auction Product Description") | |||
| 
 | |||
|     @api.onchange('template_id', 'product_id') | |||
|     def _onchange_template_id(self): | |||
|         """summary: | |||
|             function to add name automatically""" | |||
|         if self.product_id: | |||
|             self.name = f"Auction for {self.product_id.name}" | |||
| 
 | |||
|     @api.constrains('end_time', 'start_time') | |||
|     def _check_end_date(self): | |||
|         """ | |||
|             Summary: | |||
|                 start and end date validation function | |||
|         """ | |||
|         if self.end_time <= self.start_time: | |||
|             raise ValidationError( | |||
|                 _('End time should be greater than start time')) | |||
| 
 | |||
|     @api.constrains('extend_time') | |||
|     def _check_extend_time(self): | |||
|         """Summary: | |||
|                 function to validate extended time weather it is greater than | |||
|                 end time and after saving will send notification to subscribers | |||
|                  if enabled""" | |||
|         if self.extend_time: | |||
|             if self.extend_time <= self.end_time: | |||
|                 raise ValidationError( | |||
|                     _('This time is not greater than the old time(' + str( | |||
|                         self.end_time) + ')')) | |||
|             if self.is_extend_auction_notification: | |||
|                 template_id = self.env.ref( | |||
|                     'website_bargain.email_template_auction_extended') | |||
|                 email_to = '' | |||
|                 for subscriber in self.bargain_subscribers_ids: | |||
|                     email_to += subscriber.email + ',' | |||
|                 template_id.email_to = email_to | |||
|                 template_id.send_mail(self.id, force_send=True) | |||
| 
 | |||
|     def action_confirm(self): | |||
|         """ | |||
|             Summary: | |||
|                    button function to confirm auction and will | |||
|                    make product as published | |||
|         """ | |||
|         if self.search([('product_id', '=', self.product_id.id), | |||
|                         ('state', '=', 'running')]): | |||
|             raise ValidationError( | |||
|                 _('Already an auction is running for this product please' | |||
|                   ' close it to continue')) | |||
|         if self.end_time <= fields.Datetime.today(): | |||
|             raise ValidationError(_('End time is already over')) | |||
|         self.product_id.is_published = True | |||
|         self.product_id.website_id = self.website_id | |||
|         self.write({'state': 'confirmed'}) | |||
| 
 | |||
|     def action_reset_to_draft(self): | |||
|         """ | |||
|             Summary: | |||
|                 button function to reset the auction to draft | |||
|         """ | |||
|         self.product_id.is_auction = False | |||
|         self.write({'state': 'draft'}) | |||
| 
 | |||
|     def action_run_auction(self): | |||
|         """ | |||
|             Summary: | |||
|                 button function to start auction manually | |||
|         """ | |||
|         if self.search([('product_id', '=', self.product_id.id), | |||
|                         ('state', '=', 'running')]): | |||
|             raise ValidationError( | |||
|                 _('Already an auction is running for this product ' | |||
|                   'please close it to continue')) | |||
|         self.product_id.is_auction = True | |||
|         self.write({'state': 'running'}) | |||
| 
 | |||
|     def action_complete(self): | |||
|         """ | |||
|             Summary: | |||
|                 button function to end auction manually | |||
|         """ | |||
|         self.product_id.is_auction = False | |||
|         self.product_id.is_published = False | |||
|         self.write({'state': 'finished'}) | |||
| 
 | |||
|     def action_close(self): | |||
|         """ | |||
|             Summary: | |||
|                 button function to close auction | |||
|         """ | |||
|         self.product_id.is_auction = False | |||
|         self.product_id.is_published = False | |||
|         self.write({'state': 'closed'}) | |||
| 
 | |||
|     def send_email_notification(self): | |||
|         """ | |||
|         Summary: | |||
|             Function for sending auction notification for admin e ending if | |||
|             enabled | |||
|         """ | |||
|         # Get the email template for the admin notification | |||
|         template_id = self.env.ref( | |||
|             'website_bargain.admin_email_template') | |||
|         # Find all running auctions that have notification enabled and have | |||
|         # not been sent yet | |||
|         auctions = self.search([('state', '=', 'running'), | |||
|                                 ('is_activate', '=', True), | |||
|                                 ('notify_on', '>', 0), | |||
|                                 ('is_notification_send', '=', False)]) | |||
|         # Loop through the auctions that need to be notified | |||
|         for auction in auctions: | |||
|             # Map the time unit to a string for timedelta | |||
|             time_unit_map = {'days': 'days', 'hours': 'hours', | |||
|                              'minutes': 'minutes', 'seconds': 'seconds'} | |||
|             time_unit = time_unit_map.get(auction.notify_selection) | |||
|             # Check if it's time to send the notification | |||
|             if time_unit: | |||
|                 next_notification = auction.end_time - timedelta( | |||
|                     **{time_unit: auction.notify_on}) | |||
|                 if next_notification <= fields.Datetime.today(): | |||
|                     # Send the notification email and set the flag to True | |||
|                     template_id.send_mail(auction.id, force_send=True) | |||
|                     auction.is_notification_send = True | |||
| 
 | |||
|     def auction_auto_start(self): | |||
|         """ | |||
|             Summary: | |||
|                 Cron function for auction auto start when its start | |||
|                 time and also will send notification to customers about auction | |||
|         """ | |||
|         # Get all confirmed auctions | |||
|         auctions = self.search([('state', '=', 'confirmed')]) | |||
|         # Get the email template for auction start notification | |||
|         template_id = self.env.ref( | |||
|             'website_bargain.email_template_auction_start') | |||
|         # Get the emails of all the bidders and sale order partners | |||
|         bidders = self.env['bargain.information'].search([]).mapped( | |||
|             'bidder_id.email') | |||
|         sale_orders_partner = self.env['sale.order'].search( | |||
|             [('state', '=', 'sale')]).mapped('partner_id.email') | |||
|         # Loop through the auctions and check if any auction's start time has arrived | |||
|         for auction in auctions: | |||
|             if auction.start_time <= fields.Datetime.today(): | |||
|                 # Set the product as an auction and update the website | |||
|                 auction.product_id.is_auction = True | |||
|                 auction.product.website_id = auction.website_id | |||
|                 auction.write({'state': 'running'}) | |||
|                 # Send email notifications to all the bidders and sale order partners | |||
|                 email_to = "" | |||
|                 for partner in sale_orders_partner: | |||
|                     email_to += partner + ',' | |||
|                 for bidder in bidders: | |||
|                     email_to += bidder + ',' | |||
|                 template_id.email_to = email_to | |||
|                 template_id.send_mail(auction.id, force_send=True) | |||
| 
 | 
| 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: 80 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: 93 KiB | 
| After Width: | Height: | Size: 87 KiB | 
| After Width: | Height: | Size: 85 KiB | 
| After Width: | Height: | Size: 102 KiB | 
| After Width: | Height: | Size: 90 KiB | 
| After Width: | Height: | Size: 86 KiB | 
| After Width: | Height: | Size: 126 KiB | 
| After Width: | Height: | Size: 115 KiB | 
| After Width: | Height: | Size: 108 KiB | 
| After Width: | Height: | Size: 96 KiB | 
| After Width: | Height: | Size: 99 KiB | 
| After Width: | Height: | Size: 284 KiB | 
| After Width: | Height: | Size: 151 KiB | 
| After Width: | Height: | Size: 123 KiB | 
| After Width: | Height: | Size: 150 KiB | 
| After Width: | Height: | Size: 60 KiB | 
| After Width: | Height: | Size: 112 KiB | 
| After Width: | Height: | Size: 291 KiB | 
| After Width: | Height: | Size: 91 KiB | 
| After Width: | Height: | Size: 15 KiB | 
| @ -0,0 +1,854 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| 
 | |||
| <head> | |||
|     <meta charset="UTF-8"> | |||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |||
|     <title>Odoo App 3 Index</title> | |||
|     <!-- Bootstrap CSS --> | |||
|     <link rel="stylesheet" | |||
|           href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css" | |||
|           integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" | |||
|           crossorigin="anonymous"> | |||
|     <link rel="stylesheet" | |||
|           href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css"> | |||
|     <link rel="preconnect" href="https://fonts.googleapis.com"> | |||
|     <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |||
|     <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" | |||
|           rel="stylesheet"> | |||
| </head> | |||
| <body> | |||
| <section> | |||
|     <div class="container" | |||
|          style="font-family: 'Inter', sans-serif !important;background-color: #fff !important;"> | |||
|         <div class="row"> | |||
|             <div class="col-sm-12 col-md-12 col-lg-12 d-flex justify-content-between flex-wrap align-items-sm-center" | |||
|                  style="border-bottom:1px solid rgba(0, 0, 0, 0.22)"> | |||
|                 <div class="my-3"> | |||
|                     <img src="assets/misc/Cybrosys_new.png" | |||
|                          style="width:auto !important; height:40px !important"> | |||
|                 </div> | |||
|                 <div class="my-3 d-flex align-items-center"> | |||
|                     <div class="text-center" | |||
|                          style="background-color:#017E84 !important;font-size: 0.8rem !important; color:#fff !important; font-weight:500 !important; padding:4px !important; margin:0 3px !important; border-radius:50px !important; min-width: 120px !important;"> | |||
|                         Community | |||
|                     </div> | |||
|                     <div class="text-center" | |||
|                          style="background-color:#875A7B !important; color:#fff !important;font-size: 0.8rem !important; font-weight:500 !important; padding:4px !important; margin:0 3px !important; border-radius:50px !important;min-width: 120px !important;"> | |||
|                         Enterprise | |||
|                     </div> | |||
|                     <div class="text-center" | |||
|                          style="background-color:#7C7BAD !important; color:#fff !important;font-size: 0.8rem !important; font-weight:500 !important; padding:4px !important; margin:0 3px !important; border-radius:50px !important; min-width: 120px !important;"> | |||
|                         Odoo.sh | |||
|                     </div> | |||
|                 </div> | |||
|             </div> | |||
|         </div> | |||
|         <div class="row"> | |||
|             <div class="col-sm-12 col-md-12 col-lg-12 text-center d-flex align-items-center flex-column" | |||
|                  style="margin: 80px 0px !important;"> | |||
|                 <h1 style="font-size: 2.8rem;font-weight: 700; color: | |||
|                     #1A202C;"> | |||
|                     Product Bidding In ECommerce                </h1> | |||
|                 <p class="my-3 mb-4" | |||
|                    style="max-width: 80%; font-weight: 400 !important; line-height: 32px; color: #718096;"> | |||
|                    Bid For Products In Odoo | |||
|                 </p> | |||
|                 <div style="width: 80%; margin-top: 3rem;"> | |||
|                     <img src="assets/screenshots/hero-v17.gif" | |||
|                          class="img-responsive" width="100%" height="auto"> | |||
|                 </div> | |||
|             </div> | |||
|         </div> | |||
|         <div class="container mt-5 mb-5"> | |||
|             <div class="col-lg-12 d-flex flex-column justify-content-center align-items-center mt-4"> | |||
|                 <p class="m-0" | |||
|                    style="font-weight: 600; font-size: 24px; color:#714b67 !important"> | |||
|                     Key Highlights | |||
|                 </p> | |||
|             </div> | |||
|             <div class="row py-4"> | |||
|                 <div class="col-md-6 col-sm-12 p-3"> | |||
|                     <div class="d-flex h-100" style="padding: 30px;border-radius: 12px; | |||
|                                     background: #FFF; | |||
|                                     box-shadow: 1px 2px 3px 0px rgba(0, 0, 0, 0.25); "> | |||
|                         <div style="width: 36px; height: 36px; border-radius: 50%; background: #714B67; | |||
|                                     display: flex; justify-content: center; align-items: center; | |||
|                                     margin-right: 10px; flex-shrink: 0;"> | |||
|                             <i class="fa-solid fa-star  " | |||
|                                style="color: #fff;font-size:14px;"></i> | |||
|                         </div> | |||
|                         <div> | |||
|                             <p style="color: #1A202C;font-weight: 600; | |||
|                                       font-size: 1.2rem; margin-bottom: 2px;"> | |||
|                                 Timer On Product Until End Of Auction                                .</p> | |||
|                         </div> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="col-md-6 col-sm-12 p-3"> | |||
|                     <div class="d-flex   h-100" style="padding: 30px;border-radius: 12px; | |||
|                                     background: #FFF; | |||
|                                     box-shadow: 1px 2px 3px 0px rgba(0, 0, 0, 0.25); "> | |||
|                         <div style="width: 36px; height: 36px; border-radius: 50%; background: #714B67; | |||
|                                     display: flex; justify-content: center; align-items: center; | |||
|                                     margin-right: 10px; flex-shrink: 0;"> | |||
|                             <i class="fa-solid fa-star  " | |||
|                                style="color: #fff;font-size:14px;"></i> | |||
|                         </div> | |||
|                         <div> | |||
|                             <p style="color: #1A202C;font-weight: 600; | |||
|                                       font-size: 1.2rem; margin-bottom: 2px;"> | |||
|                                 Subscription Available                                .</p> | |||
|                         </div> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="col-md-6 col-sm-12 p-3"> | |||
|                     <div class="d-flex   h-100" style="padding: 30px;border-radius: 12px; | |||
|                                     background: #FFF; | |||
|                                     box-shadow: 1px 2px 3px 0px rgba(0, 0, 0, 0.25); "> | |||
|                         <div style="width: 36px; height: 36px; border-radius: 50%; background: #714B67; | |||
|                                     display: flex; justify-content: center; align-items: center; | |||
|                                     margin-right: 10px; flex-shrink: 0;"> | |||
|                             <i class="fa-solid fa-star  " | |||
|                                style="color: #fff;font-size:14px;"></i> | |||
|                         </div> | |||
|                         <div> | |||
|                             <p style="color: #1A202C;font-weight: 600; | |||
|                                       font-size: 1.2rem; margin-bottom: 2px;"> | |||
|                                 Different Email Notifications                                .</p> | |||
|                         </div> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="col-md-6 col-sm-12 p-3"> | |||
|                     <div class="d-flex   h-100" style="padding: 30px;border-radius: 12px; | |||
|                                     background: #FFF; | |||
|                                     box-shadow: 1px 2px 3px 0px rgba(0, 0, 0, 0.25); "> | |||
|                         <div style="width: 36px; height: 36px; border-radius: 50%; background: #714B67; | |||
|                                     display: flex; justify-content: center; align-items: center; | |||
|                                     margin-right: 10px; flex-shrink: 0;"> | |||
|                             <i class="fa-solid fa-star  " | |||
|                                style="color: #fff;font-size:14px;"></i> | |||
|                         </div> | |||
|                         <div> | |||
|                             <p style="color: #1A202C;font-weight: 600; | |||
|                                       font-size: 1.2rem; margin-bottom: 2px;"> | |||
|                                 Option To See Bidders. | |||
|                             </p> | |||
|                         </div> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="col-md-6 col-sm-12 p-3"> | |||
|                     <div class="d-flex   h-100" style="padding: 30px;border-radius: 12px; | |||
|                                     background: #FFF; | |||
|                                     box-shadow: 1px 2px 3px 0px rgba(0, 0, 0, 0.25); "> | |||
|                         <div style="width: 36px; height: 36px; border-radius: 50%; background: #714B67; | |||
|                                     display: flex; justify-content: center; align-items: center; | |||
|                                     margin-right: 10px; flex-shrink: 0;"> | |||
|                             <i class="fa-solid fa-star  " | |||
|                                style="color: #fff;font-size:14px;"></i> | |||
|                         </div> | |||
|                         <div> | |||
|                             <p style="color: #1A202C;font-weight: 600; | |||
|                                       font-size: 1.2rem; margin-bottom: 2px;"> | |||
|                                 Option For Buy Now                                . | |||
|                             </p> | |||
|                         </div> | |||
|                     </div> | |||
|                 </div> | |||
|             </div> | |||
|         </div> | |||
|         <div class="container rounded"> | |||
|             <ul class="nav nav-tabs d-flex" | |||
|                 style="width: fit-content;margin: 0 auto;gap: 1rem;"> | |||
|                 <li class="col text-center py-2 text-nowrap " | |||
|                     style="color: #fff; background-color: #714B67;border-radius: 6px 6px 0px 0px;"> | |||
|                     <a | |||
|                             class="active show" data-toggle="tab" href="#tab1" | |||
|                             style="color: #fff;font-weight: 500; background-color: #714B67; text-decoration: none;"> | |||
|                         <i class="fa-regular fa-image  pr-2" | |||
|                            style="color: #fff;"></i> | |||
|                         Screenshots</a></li> | |||
|                 <li class="col text-center py-2 text-nowrap " | |||
|                     style="color: #fff; background-color: #714B67;border-radius: 6px 6px 0px 0px;"> | |||
|                     <a | |||
|                             data-toggle="tab" href="#tab2" | |||
|                             style="color: #fff;font-weight: 500;  text-decoration: none;"><i | |||
|                             class="fa-solid fa-star  pr-2" | |||
|                             style="color: #fff;"></i>Features</a></li> | |||
|                 <li class="col text-center py-2 text-nowrap " | |||
|                     style="color: #fff; background-color: #714B67;border-radius: 6px 6px 0px 0px;"> | |||
|                     <a | |||
|                             data-toggle="tab" href="#tab3" | |||
|                             style="color: #fff;font-weight: 500; text-decoration: none; background-color: #714B67;"><i | |||
|                             class="fa-solid fa-book-open  pr-2" | |||
|                             style="color: #fff;"></i>Released Notes</a></li> | |||
|             </ul> | |||
|             <div class="tab-content" | |||
|                  style="background-color: rgba(121, 113, 119, 0.04);"> | |||
|                 <div id="tab1" class="tab-pane fade in active show"> | |||
|                     <div class="col-lg-12 py-2" | |||
|                          style="padding: 1rem 4rem !important;"> | |||
|                         <div | |||
|                                 style="border: 1px solid #d8d6d6; border-radius: 4px; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> | |||
|                             <div class="row justify-content-center p-3 w-100 m-0"> | |||
|                                 <img src="assets/screenshots/1.png" | |||
|                                      class="img-responsive" width="100%" | |||
|                                      height="auto"> | |||
|                             </div> | |||
|                             <div class="px-3"> | |||
|                                 <h4 class="mt-2" | |||
|                                     style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> | |||
|                                     Auction Home Page | |||
|                                 </h4> | |||
|                                 <p class="m-0" style="color:#718096"> | |||
|                                     Website -> Auction ->Auctions Here created auction can be seen . </p> | |||
|                             </div> | |||
|                         </div> | |||
|                     </div> | |||
|                     <div class="col-lg-12 py-2" | |||
|                          style="padding: 1rem 4rem !important;"> | |||
|                         <div style="border: 1px solid #d8d6d6; border-radius: 4px;  background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> | |||
|                             <div class="row justify-content-center p-3 w-100 m-0"> | |||
|                                 <img src="assets/screenshots/2.png" | |||
|                                      class="img-responsive" width="100%" | |||
|                                      height="auto"> | |||
|                             </div> | |||
|                             <div class="px-3"> | |||
|                                 <h4 class="mt-2" | |||
|                                     style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> | |||
|                                     Create a Auction and click CONFIRM</h4> | |||
|                          | |||
|                             </div> | |||
|                         </div> | |||
|                     </div> | |||
|                     <div class="col-lg-12 py-2" | |||
|                          style="padding: 1rem 4rem !important;"> | |||
|                         <div | |||
|                                 style="border: 1px solid #d8d6d6; border-radius: 4px;  background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> | |||
|                             <div class="row justify-content-center p-3 w-100 m-0"> | |||
|                                 <img src="assets/screenshots/3.png" | |||
|                                      class="img-responsive" width="100%" | |||
|                                      height="auto"> | |||
|                             </div> | |||
|                             <div class="px-3"> | |||
|                                 <h4 class="mt-2" | |||
|                                     style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> | |||
|                                     Run Auction</h4> | |||
|                                 <p class="m-0" style="color:#718096"> Auction will automatically start at the Start Date Time.If you want to run manually just click on RUN AUCTION Button.                                </p> | |||
|                             </div> | |||
|                         </div> | |||
|                     </div> | |||
|                     <div class="col-lg-12 py-2" | |||
|                          style="padding: 1rem 4rem !important;"> | |||
|                         <div | |||
|                                 style="border: 1px solid #d8d6d6; border-radius: 4px;  background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> | |||
|                             <div class="row justify-content-center p-3 w-100 m-0"> | |||
|                                 <img src="assets/screenshots/4.png" | |||
|                                      class="img-responsive" width="100%" | |||
|                                      height="auto"> | |||
|                             </div> | |||
|                             <div class="px-3"> | |||
|                                 <h4 class="mt-2" | |||
|                                     style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> | |||
|                                     Product in Product List | |||
| 
 | |||
|                                 </h4> | |||
|                                 <p class="m-0" style="color:#718096"> | |||
|                                     Customes can see AUCTION ON on that product. | |||
|                                 </p> | |||
|                             </div> | |||
|                         </div> | |||
|                     </div> | |||
|                     <div class="col-lg-12 py-2" | |||
|                          style="padding: 1rem 4rem !important;"> | |||
|                         <div style="border: 1px solid #d8d6d6; border-radius: 4px;  background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> | |||
|                             <div class="row justify-content-center p-3 w-100 m-0"> | |||
|                                 <img src="assets/screenshots/5.png" | |||
|                                      class="img-responsive" width="100%" | |||
|                                      height="auto"> | |||
|                             </div> | |||
|                             <div class="px-3"> | |||
|                                 <h4 class="mt-2" | |||
|                                     style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> | |||
|                                     Product in Website.</h4> | |||
|                                 <p class="m-0" style="color:#718096"> | |||
|                                     This will be the product view in website.</p> | |||
|                             </div> | |||
|                         </div> | |||
|                     </div> | |||
|                     <div class="col-lg-12 py-2" | |||
|                          style="padding: 1rem 4rem !important;"> | |||
|                         <div | |||
|                                 style="border: 1px solid #d8d6d6; border-radius: 4px;  background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> | |||
|                             <div class="row justify-content-center p-3 w-100 m-0"> | |||
|                                 <img src="assets/screenshots/6.png" | |||
|                                      class="img-responsive" width="100%" | |||
|                                      height="auto"> | |||
|                             </div> | |||
|                             <div class="px-3"> | |||
|                                 <h4 class="mt-2" | |||
|                                     style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> | |||
|                                     Subscribers</h4> | |||
|                             </div> | |||
|                         </div> | |||
|                     </div> | |||
|                     <div class="col-lg-12 py-2" | |||
|                          style="padding: 1rem 4rem !important;"> | |||
|                         <div | |||
|                                 style="border: 1px solid #d8d6d6; border-radius: 4px;  background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> | |||
|                             <div class="row justify-content-center p-3 w-100 m-0"> | |||
|                                 <img src="assets/screenshots/7.png" | |||
|                                      class="img-responsive" width="100%" | |||
|                                      height="auto"> | |||
|                             </div> | |||
|                             <div class="px-3"> | |||
|                                 <h4 class="mt-2" | |||
|                                     style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> | |||
|                                     Bidders | |||
|                             </h4> | |||
|                                 <p class="m-0" style="color:#718096">While | |||
|                                     Click on the Bidders.</p> | |||
|                             </div> | |||
|                         </div> | |||
|                     </div> | |||
|                     <div class="col-lg-12 py-2" | |||
|                     style="padding: 1rem 4rem !important;"> | |||
|                    <div | |||
|                            style="border: 1px solid #d8d6d6; border-radius: 4px;  background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> | |||
|                        <div class="row justify-content-center p-3 w-100 m-0"> | |||
|                            <img src="assets/screenshots/8.png" | |||
|                                 class="img-responsive" width="100%" | |||
|                                 height="auto"> | |||
|                        </div> | |||
|                        <div class="px-3"> | |||
|                            <h4 class="mt-2" | |||
|                                style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> | |||
|                                This will be the bidders view in website.</h4> | |||
|                        </div> | |||
|                    </div> | |||
|                </div> | |||
|                     <div class="col-lg-12 py-2" | |||
|                     style="padding: 1rem 4rem !important;"> | |||
|                    <div | |||
|                            style="border: 1px solid #d8d6d6; border-radius: 4px;  background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> | |||
|                        <div class="row justify-content-center p-3 w-100 m-0"> | |||
|                            <img src="assets/screenshots/9.png" | |||
|                                 class="img-responsive" width="100%" | |||
|                                 height="auto"> | |||
|                        </div> | |||
|                        <div class="px-3"> | |||
|                            <h4 class="mt-2" | |||
|                                style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> | |||
|                                View in backend.</h4> | |||
|                        </div> | |||
|                    </div> | |||
|                </div> | |||
|                <div class="col-lg-12 py-2" | |||
|                style="padding: 1rem 4rem !important;"> | |||
|               <div | |||
|                       style="border: 1px solid #d8d6d6; border-radius: 4px;  background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> | |||
|                   <div class="row justify-content-center p-3 w-100 m-0"> | |||
|                       <img src="assets/screenshots/11.png" | |||
|                            class="img-responsive" width="100%" | |||
|                            height="auto"> | |||
|                   </div> | |||
|                   <div class="px-3"> | |||
|                       <h4 class="mt-2" | |||
|                           style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> | |||
|                           These are different Notifications options.</h4> | |||
|                   </div> | |||
|               </div> | |||
|           </div> | |||
|                 </div> | |||
|                 <div id="tab2" class="tab-pane fade"> | |||
|                     <div class="col-mg-12" style="padding: 1rem 4rem;"> | |||
|                         <ul style="list-style: none; padding: 1rem 0;font-weight: 500;"> | |||
|                             <li class="py-3" | |||
|                                 style="font-weight: 500;background-color: #fff; border-radius: 4px; padding: 1rem; margin-bottom: 1rem; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> | |||
|                                     <span style="margin-right: 12px;"><img | |||
|                                             src="assets/misc/star (1) 2.svg" | |||
|                                             alt="" | |||
|                                             width="16px"></span>Hide products price in website. | |||
|                             </li> | |||
|                             <li class="py-3" | |||
|                                 style="font-weight: 500;background-color: #fff; border-radius: 4px; padding: 1rem; margin-bottom: 1rem; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> | |||
|                                     <span style="margin-right: 12px;"><img | |||
|                                             src="assets/misc/star (1) 2.svg" | |||
|                                             alt="" | |||
|                                             width="16px"></span>Hide add to cart button in the website. | |||
|                             </li> | |||
|                             <li class="py-3" | |||
|                                 style="font-weight: 500;background-color: #fff; border-radius: 4px; padding: 1rem; margin-bottom: 1rem; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> | |||
|                                     <span style="margin-right: 12px;"><img | |||
|                                             src="assets/misc/star (1) 2.svg" | |||
|                                             alt="" | |||
|                                             width="16px"></span>Adds a button for price requests from merchants. | |||
|                             </li> | |||
|                             <li class="py-3" | |||
|                                 style="font-weight: 500;background-color: #fff; border-radius: 4px; padding: 1rem; margin-bottom: 1rem; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> | |||
|                                     <span style="margin-right: 12px;"><img | |||
|                                             src="assets/misc/star (1) 2.svg" | |||
|                                             alt="" | |||
|                                             width="16px"></span>Track all requests from the backend. | |||
|                             </li> | |||
|                         </ul> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div id="tab3" class="tab-pane fade"> | |||
|                     <div class="col-mg-12 active" style="padding: 1rem 4rem;"> | |||
|                         <div class="py-3" | |||
|                              style="font-weight: 500;background-color: #fff; border-radius: 4px; padding: 1rem; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> | |||
|                             <div class="d-flex mb-3" | |||
|                                  style="font-size: 0.8rem; font-weight: 500;"><span>Version | |||
|                                         17.0.1.0.0</span><span | |||
|                                     class="px-2">|</span><span | |||
|                                     style="color: #714B67;font-weight: 600;">Released on:22nd February 2024</span> | |||
|                             </div> | |||
|                             <p class="m-0" | |||
|                                style=" color:#718096!important; font-size:1rem !important;line-height: 28px;"> | |||
|                                 Initial Commit for Website Call For Price.</p> | |||
|                         </div> | |||
|                     </div> | |||
|                 </div> | |||
|             </div> | |||
|         </div> | |||
|         <div class="container mt-5"> | |||
|             <div class="col-lg-12 d-flex flex-column justify-content-center align-items-center mt-5"> | |||
|                 <p class="m-0" | |||
|                    style="font-weight: 600; font-size: 24px; color:#000 !important"> | |||
|                     Related Products</p> | |||
|             </div> | |||
|         </div> | |||
|         <div id="myCarousel" class="carousel slide py-3" data-ride="carousel"> | |||
|             <div class="carousel-inner"> | |||
|                 <div class="carousel-item active"> | |||
|                     <div class="row p-4"> | |||
|                         <div class="col"> | |||
|                             <div class="p-3"> | |||
|                                 <a href="https://apps.odoo.com/apps/modules/17.0/website_product_publish/" | |||
|                                    style="color: #000; text-decoration: none;"> | |||
|                                     <div style="border:1px solid #CBCBCB !important;border-radius: 4px;"> | |||
|                                         <div style="width: 300px; "> | |||
|                                             <img src="assets/modules/1.jpg" | |||
|                                                  alt="" width="100%" | |||
|                                                  height="auto"> | |||
| 
 | |||
|                                         </div> | |||
|                                         <p class="text-center pt-2 text-black font-weight-bold"> | |||
|                                             Quick Product Publish/Unpublish</p> | |||
|                                     </div> | |||
|                                 </a> | |||
|                             </div> | |||
|                         </div> | |||
|                         <div class="col"> | |||
|                             <div class="p-3"> | |||
|                                 <a href="https://apps.odoo.com/apps/modules/17.0/odoo_icecat_connector/" | |||
|                                    style="color: #000; text-decoration: none;"> | |||
|                                     <div style="border:1px solid #CBCBCB !important;border-radius: 4px;"> | |||
|                                         <div style="width: 300px; "> | |||
|                                             <img src="assets/modules/2.jpg" | |||
|                                                  alt="" width="100%" | |||
|                                                  height="auto"> | |||
| 
 | |||
|                                         </div> | |||
|                                         <p class="text-center pt-2 text-black font-weight-bold"> | |||
|                                             Odoo Icecat Connector</p> | |||
|                                     </div> | |||
|                                 </a> | |||
|                             </div> | |||
|                         </div> | |||
|                         <div class="col"> | |||
|                             <div class="p-3"> | |||
|                                 <a href="https://apps.odoo.com/apps/modules/17.0/shopping_through_agent/" | |||
|                                    style="color: #000; text-decoration: none;"> | |||
|                                     <div style="border:1px solid #CBCBCB !important;border-radius: 4px;"> | |||
|                                         <div style="width: 300px; "> | |||
|                                             <img src="assets/modules/3.jpg" | |||
|                                                  alt="" width="100%" | |||
|                                                  height="auto"> | |||
| 
 | |||
|                                         </div> | |||
|                                         <p class="text-center pt-2 text-black font-weight-bold"> | |||
|                                             Shopping Through Agent</p> | |||
|                                     </div> | |||
|                                 </a> | |||
|                             </div> | |||
|                         </div> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="carousel-item"> | |||
|                     <div class="row p-4"> | |||
|                         <div class="col"> | |||
|                             <div class="p-3"> | |||
|                                 <a href="https://apps.odoo.com/apps/modules/17.0/website_upload_files/" | |||
|                                    style="color: #000; text-decoration: none;"> | |||
|                                     <div style="border:1px solid #CBCBCB !important;border-radius: 4px;"> | |||
|                                         <div style="width: 300px; "> | |||
|                                             <img src="assets/modules/4.jpg" | |||
|                                                  alt="" width="100%" | |||
|                                                  height="auto"> | |||
| 
 | |||
|                                         </div> | |||
|                                         <p class="text-center pt-2 text-black font-weight-bold"> | |||
|                                             Multiple Attachments In eCommerce Order</p> | |||
|                                     </div> | |||
|                                 </a> | |||
|                             </div> | |||
|                         </div> | |||
|                         <div class="col"> | |||
|                             <div class="p-3"> | |||
|                                 <a href="https://apps.odoo.com/apps/modules/17.0/website_multi_variant/" | |||
|                                    style="color: #000; text-decoration: none;"> | |||
|                                     <div style="border:1px solid #CBCBCB !important;border-radius: 4px;"> | |||
|                                         <div style="width: 300px;"> | |||
|                                             <img src="assets/modules/5.jpg" | |||
|                                                  alt="" width="100%" | |||
|                                                  height="auto"> | |||
| 
 | |||
|                                         </div> | |||
|                                         <p class="text-center pt-2 text-black font-weight-bold"> | |||
|                                             Website Multi Variant Add to Cart</p> | |||
|                                     </div> | |||
|                                 </a> | |||
|                             </div> | |||
|                         </div> | |||
|                         <div class="col"> | |||
|                             <div class="p-3"> | |||
|                                 <a href="https://apps.odoo.com/apps/modules/17.0/website_pdf_preview_snippet/" | |||
|                                    style="color: #000; text-decoration: none;"> | |||
|                                     <div style="border:1px solid #CBCBCB !important;border-radius: 4px;"> | |||
|                                         <div style="width: 300px;"> | |||
|                                             <img src="assets/modules/6.jpg" | |||
|                                                  alt="" width="100%" | |||
|                                                  height="auto"> | |||
|                                         </div> | |||
|                                         <p class="text-center pt-2 text-black font-weight-bold"> | |||
|                                             Website PDF Preview Snippet</p> | |||
|                                     </div> | |||
|                                 </a> | |||
|                             </div> | |||
|                         </div> | |||
|                     </div> | |||
|                 </div> | |||
|             </div> | |||
|             <a class="carousel-control-prev" href="#myCarousel" | |||
|                data-slide="prev" style="width: 35px; color: #000;"> | |||
|                     <span class="carousel-control-prev-icon"> | |||
|                         <i class="fa fa-chevron-left" | |||
|                            style="font-size: 24px;"></i> | |||
|                     </span> | |||
|             </a> | |||
|             <a class="carousel-control-next" href="#myCarousel" | |||
|                data-slide="next" style="width: 35px; color: #000;"> | |||
|                     <span class="carousel-control-next-icon"> | |||
|                         <i class="fa fa-chevron-right" | |||
|                            style="font-size: 24px;"></i> | |||
|                     </span> | |||
|             </a> | |||
|         </div> | |||
|         <div class="container mt-5"> | |||
|             <div class="col-lg-12 d-flex flex-column justify-content-center align-items-center mt-4"> | |||
|                 <p class="m-0" | |||
|                    style="font-weight: 600; font-size: 24px; color:#000 !important"> | |||
|                     Our Services</p> | |||
| 
 | |||
|             </div> | |||
|         </div> | |||
|         <div class="container my-5"> | |||
|             <div class="row py-3"> | |||
|                 <div class="col-md-4 col-sm-6 px-4 py-4"> | |||
|                     <div | |||
|                             style="background-color: #fff; padding: 25px; text-align: center;  box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px; position: relative;border-radius: 4px;"> | |||
|                         <div style="position: absolute; top: 0%; left: 50%; transform: translate(-50%, -50%);"> | |||
|                             <div style="background-color:#13EA36 ; border-radius: 50%; padding: 15px;    width: 68px; | |||
|                                     height: 68px; display: inline-block; box-shadow:0px 4px 4px rgba(0, 0, 0, 0.25);"> | |||
|                                 <img src="assets/icons/cogs.png" | |||
|                                      alt="service-icon" width="38px" | |||
|                                      height="auto"> | |||
|                             </div> | |||
|                         </div> | |||
|                         <p style="margin-top: 20px; font-weight: bold;">Odoo | |||
|                             Customization</p> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="col-md-4 col-sm-6 px-4 py-4"> | |||
|                     <div | |||
|                             style="background-color: #fff; padding: 25px; text-align: center; box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px; position: relative;border-radius: 4px;"> | |||
|                         <div style="position: absolute; top: 0%; left: 50%; transform: translate(-50%, -50%);"> | |||
|                             <div style="background-color:#DBC711; border-radius: 50%; padding: 15px;    width: 68px; | |||
|                                     height: 68px; display: inline-block; box-shadow:0px 4px 4px rgba(0, 0, 0, 0.25);"> | |||
|                                 <img src="assets/icons/wrench.png" | |||
|                                      alt="service-icon" width="38px" | |||
|                                      height="auto"> | |||
|                             </div> | |||
|                         </div> | |||
|                         <p style="margin-top: 20px; font-weight: bold;">Odoo | |||
|                             Implementation</p> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="col-md-4 col-sm-6 px-4 py-4"> | |||
|                     <div | |||
|                             style="background-color: #fff; padding: 25px; text-align: center;  box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px; position: relative; border-radius: 4px;"> | |||
|                         <div style="position: absolute; top: 0%; left: 50%; transform: translate(-50%, -50%);"> | |||
|                             <div style="background-color:#FF6B6B ; border-radius: 50%; padding: 15px;    width: 68px; | |||
|                                     height: 68px; display: inline-block; box-shadow:0px 4px 4px rgba(0, 0, 0, 0.25);"> | |||
|                                 <img src="assets/icons/lifebuoy.png" | |||
|                                      alt="service-icon" width="38px" | |||
|                                      height="auto"> | |||
|                             </div> | |||
|                         </div> | |||
|                         <p style="margin-top: 20px; font-weight: bold;">Odoo | |||
|                             Support</p> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="col-md-4 col-sm-6 px-4 py-4"> | |||
|                     <div | |||
|                             style="background-color: #fff; padding: 25px; text-align: center; box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px; position: relative; border-radius: 4px;"> | |||
|                         <div style="position: absolute; top: 0%; left: 50%; transform: translate(-50%, -50%);"> | |||
|                             <div style="background-color:#FFA801 ; border-radius: 50%; padding: 15px;    width: 68px; | |||
|                                     height: 68px; display: inline-block; box-shadow:0px 4px 4px rgba(0, 0, 0, 0.25);"> | |||
|                                 <img src="assets/icons/user.png" | |||
|                                      alt="service-icon" width="38px" | |||
|                                      height="auto"> | |||
|                             </div> | |||
|                         </div> | |||
|                         <p style="margin-top: 20px; font-weight: bold;">Hire | |||
|                             Odoo Developer</p> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="col-md-4 col-sm-6 px-4 py-4"> | |||
|                     <div | |||
|                             style="background-color: #fff; padding: 25px; text-align: center;  box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px; position: relative; border-radius: 4px;"> | |||
| 
 | |||
|                         <div style="position: absolute; top: 0%; left: 50%; transform: translate(-50%, -50%);"> | |||
|                             <div style="background-color:#54A0FF; border-radius: 50%; padding: 15px;    width: 68px; | |||
|                                     height: 68px; display: inline-block; box-shadow:0px 4px 4px rgba(0, 0, 0, 0.25);"> | |||
|                                 <img src="assets/icons/puzzle.png" | |||
|                                      alt="service-icon" width="38px" | |||
|                                      height="auto"> | |||
|                             </div> | |||
|                         </div> | |||
|                         <p style="margin-top: 20px; font-weight: bold;">Odoo | |||
|                             Integration</p> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="col-md-4 col-sm-6 px-4 py-4"> | |||
|                     <div | |||
|                             style="background-color: #fff; padding: 25px; text-align: center;  box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px; position: relative;border-radius: 4px;"> | |||
|                         <div style="position: absolute; top: 0%; left: 50%; transform: translate(-50%, -50%);"> | |||
|                             <div style="background-color:#6D7680 ; border-radius: 50%; padding: 15px;    width: 68px; | |||
|                                     height: 68px; display: inline-block; box-shadow:0px 4px 4px rgba(0, 0, 0, 0.25);"> | |||
|                                 <img src="assets/icons/update.png" | |||
|                                      alt="service-icon" width="38px" | |||
|                                      height="auto"> | |||
|                             </div> | |||
|                         </div> | |||
|                         <p style="margin-top: 20px; font-weight: bold;">Odoo | |||
|                             Migration</p> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="col-md-4 col-sm-6 px-4 py-4"> | |||
|                     <div | |||
|                             style="background-color: #fff; padding: 25px; text-align: center;  box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px; position: relative;border-radius: 4px;"> | |||
|                         <div style="position: absolute; top: 0%; left: 50%; transform: translate(-50%, -50%);"> | |||
|                             <div style="background-color:#786FA6 ; border-radius: 50%; padding: 15px;    width: 68px; | |||
|                                     height: 68px; display: inline-block; box-shadow:0px 4px 4px rgba(0, 0, 0, 0.25);"> | |||
|                                 <img src="assets/icons/consultation.png" | |||
|                                      alt="service-icon" width="38px" | |||
|                                      height="auto"> | |||
|                             </div> | |||
|                         </div> | |||
|                         <p style="margin-top: 20px; font-weight: bold;">Odoo | |||
|                             Consultancy</p> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="col-md-4 col-sm-6 px-4 py-4"> | |||
|                     <div | |||
|                             style="background-color: #fff; padding: 25px; text-align: center; box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px;position: relative;border-radius: 4px;"> | |||
|                         <div style="position: absolute; top: 0%; left: 50%; transform: translate(-50%, -50%);"> | |||
|                             <div style="background-color:#F8A5C2 ; border-radius: 50%; padding: 15px;    width: 68px; | |||
|                                     height: 68px; display: inline-block; box-shadow:0px 4px 4px rgba(0, 0, 0, 0.25);"> | |||
|                                 <img src="assets/icons/training.png" | |||
|                                      alt="service-icon" width="38px" | |||
|                                      height="auto"> | |||
|                             </div> | |||
|                         </div> | |||
|                         <p style="margin-top: 20px; font-weight: bold;">Odoo | |||
|                             Implementation</p> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="col-md-4 col-sm-6 px-4 py-4"> | |||
|                     <div | |||
|                             style="background-color: #fff; padding: 25px; text-align: center;  box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px; position: relative;border-radius: 4px;"> | |||
|                         <div style="position: absolute; top: 0%; left: 50%; transform: translate(-50%, -50%);"> | |||
|                             <div style="background-color:#E6BE26; border-radius: 50%; padding: 15px;    width: 68px; | |||
|                                     height: 68px; display: inline-block; box-shadow:0px 4px 4px rgba(0, 0, 0, 0.25);"> | |||
|                                 <img src="assets/icons/license.png" | |||
|                                      alt="service-icon" width="38px" | |||
|                                      height="auto"> | |||
|                             </div> | |||
|                         </div> | |||
|                         <p style="margin-top: 20px; font-weight: bold;">Odoo | |||
|                             Licensing Consultancy</p> | |||
|                     </div> | |||
|                 </div> | |||
|             </div> | |||
|         </div> | |||
|         <div class="container mt-5"> | |||
|             <div class="col-lg-12 d-flex flex-column justify-content-center align-items-center mt-4"> | |||
|                 <p class="m-0" | |||
|                    style="font-weight: 600; font-size: 24px; color:#000 !important"> | |||
|                     Our Industries</p> | |||
| 
 | |||
|             </div> | |||
|         </div> | |||
|         <div class="container"> | |||
|             <div class="row my-5 py-4"> | |||
|                 <div class="col-md-3 col-sm-6 p-0"> | |||
|                     <div class="d-flex flex-column h-100 " | |||
|                          style="border-right: 1px solid rgb(209, 209, 209); border-bottom: 1px solid  rgb(209, 209, 209); padding: 30px; box-shadow: 6px 0 10px rgba(228, 227, 227, 0.373);"> | |||
|                         <img src="assets/icons/trading-black.png" width="42px" | |||
|                              height="auto" alt=""> | |||
|                         <p style="color: #714B67;font-weight: 600; margin-top: 10px; | |||
|                            font-size: 1.2rem; margin-bottom: 2px;">Trading</p> | |||
|                         <p>Easily procure and sell your products</p> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="col-md-3 col-sm-6  p-0"> | |||
|                     <div class="d-flex flex-column h-100" | |||
|                          style="border-right: 1px solid rgb(209, 209, 209);border-bottom: 1px solid  rgb(209, 209, 209); padding: 30px;"> | |||
|                         <img src="assets/icons/pos-black.png" width="42px" | |||
|                              height="auto" alt=""> | |||
|                         <p style="color: #714B67;font-weight: 600; margin-top: 10px; | |||
|                             font-size: 1.2rem; margin-bottom: 2px;">POS</p> | |||
|                         <p>Easy configuration and convivial experience</p> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="col-md-3 col-sm-6  p-0"> | |||
|                     <div class="d-flex flex-column h-100" | |||
|                          style="border-right: 1px solid  rgb(209, 209, 209);border-bottom: 1px solid   rgba(0, 0, 0, 0.2); padding: 30px; box-shadow: 0 5px 10px  rgba(228, 227, 227, 0.373)"> | |||
|                         <img src="assets/icons/education-black.png" width="42px" | |||
|                              height="auto" alt=""> | |||
|                         <p style="color: #714B67;font-weight: 600; margin-top: 10px; | |||
|                             font-size: 1.2rem; margin-bottom: 2px;"> | |||
|                             Education</p> | |||
|                         <p>A platform for educational management</p> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="col-md-3 col-sm-6  p-0"> | |||
|                     <div class="d-flex flex-column h-100" | |||
|                          style="border-bottom: 1px solid  rgb(209, 209, 209); padding: 30px; "> | |||
|                         <img src="assets/icons/manufacturing-black.png" | |||
|                              width="42px" height="auto" alt=""> | |||
|                         <p style="color: #714B67;font-weight: 600; margin-top: 10px; | |||
|                             font-size: 1.2rem; margin-bottom: 2px;"> | |||
|                             Manufacturing</p> | |||
|                         <p>Plan, track and schedule your operations</p> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="col-md-3 col-sm-6 p-0"> | |||
|                     <div class="d-flex flex-column h-100" | |||
|                          style="border-right: 1px solid  rgb(209, 209, 209); padding: 30px;"> | |||
|                         <img src="assets/icons/ecom-black.png" width="42px" | |||
|                              height="auto" alt=""> | |||
|                         <p style="color: #714B67;font-weight: 600; margin-top: 10px; | |||
|                             font-size: 1.2rem; margin-bottom: 2px;">E-commerce & | |||
|                             Website</p> | |||
|                         <p>Mobile friendly, awe-inspiring product pages</p> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="col-md-3 col-sm-6   p-0"> | |||
|                     <div class="d-flex flex-column h-100" | |||
|                          style="border-right: 1px solid  rgb(209, 209, 209); padding: 30px;box-shadow: 0 -5px 10px  rgba(228, 227, 227, 0.373);"> | |||
|                         <img src="assets/icons/service-black.png" width="42px" | |||
|                              height="auto" alt=""> | |||
|                         <p style="color: #714B67;font-weight: 600; margin-top: 10px; | |||
|                             font-size: 1.2rem; margin-bottom: 2px;">Service | |||
|                             Management</p> | |||
|                         <p>Keep track of services and invoice</p> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="col-md-3 col-sm-6    p-0"> | |||
|                     <div class="d-flex flex-column h-100" | |||
|                          style="border-right: 1px solid  rgb(209, 209, 209); padding: 30px; "> | |||
|                         <img src="assets/icons/restaurant-black.png" | |||
|                              width="42px" height="auto" alt=""> | |||
|                         <p style="color: #714B67;font-weight: 600; margin-top: 10px; | |||
|                             font-size: 1.2rem; margin-bottom: 2px;"> | |||
|                             Restaurant</p> | |||
|                         <p>Run your bar or restaurant methodically</p> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="col-md-3 col-sm-6   p-0"> | |||
|                     <div class="d-flex flex-column h-100" | |||
|                          style=" padding: 30px;box-shadow: -5px 0 10px  rgba(228, 227, 227, 0.373);"> | |||
|                         <img src="assets/icons/hotel-black.png" width="42px" | |||
|                              height="auto" alt=""> | |||
|                         <p style="color: #714B67;font-weight: 600; margin-top: 10px; | |||
|                             font-size: 1.2rem; margin-bottom: 2px;">Hotel | |||
|                             Management</p> | |||
|                         <p>An all-inclusive hotel management application</p> | |||
|                     </div> | |||
|                 </div> | |||
|             </div> | |||
|         </div> | |||
|         <div class="container mt-5"> | |||
|             <div class="col-lg-12 d-flex flex-column justify-content-center align-items-center mt-5"> | |||
|                 <p class="m-0" | |||
|                    style="font-weight: 600; font-size: 24px; color:#000 !important"> | |||
|                     Support</p> | |||
|             </div> | |||
|         </div> | |||
|         <div class="container my-5"> | |||
|             <div class="row" style="background-color: #FFFAFE;"> | |||
|                 <div class="col-md-6 pb-4  d-flex align-items-center justify-content-center" | |||
|                      style="border-right: 1px solid #D9D9D9;"> | |||
|                     <div style="padding: 30px;"> | |||
|                         <div class="d-flex align-items-center"> | |||
|                             <img src="assets/misc/support (1) 1.svg" alt="" | |||
|                                  width="60px" style="margin-right: 12px;"> | |||
|                             <div style="padding: 0px 8px;"> | |||
|                                     <span | |||
|                                             style="color: #714B67;font-size: 24px;font-weight: 600;padding-bottom: 1rem;">Need | |||
|                                         Help?</span> | |||
|                                 <p class="m-0" style="color:#718096;">Got | |||
|                                     questions or need help? Get in touch.</p> | |||
|                                 <div style="font-weight: 400;"><span><img | |||
|                                         src="assets/misc/support-email.svg" | |||
|                                         alt="" | |||
|                                         width="18px" | |||
|                                         style="filter: invert(1);margin-right: 0.8rem;"></span>odoo@cybrosys.com | |||
|                                 </div> | |||
|                             </div> | |||
|                         </div> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="col-md-6 pb-4 d-flex align-items-center justify-content-center"> | |||
|                     <div style="padding: 30px;"> | |||
|                         <div class="d-flex align-items-center"> | |||
|                             <img src="assets/misc/whatsapp 1.svg" alt="" | |||
|                                  width="60px" style="margin-right: 12px;"> | |||
|                             <div> | |||
|                                 <span style="color: #714B67;font-size: 24px;font-weight: 600;">WhatsApp</span> | |||
|                                 <p class="m-0" style="color:#718096;">Say hi to | |||
|                                     us on WhatsApp!</p> | |||
|                                 <div style="font-weight: 400; font-size: 16px;"><span><img | |||
|                                         src="assets/misc/phone.svg" | |||
|                                         alt="" width="14px" | |||
|                                         style="filter: invert(1); margin-right: 0.8rem;"></span>+91 | |||
|                                     99456767686 | |||
|                                 </div> | |||
|                             </div> | |||
|                         </div> | |||
|                     </div> | |||
|                 </div> | |||
|             </div> | |||
|         </div> | |||
|     </div> | |||
| </section> | |||
| <!-- Optional JavaScript --> | |||
| <!-- jQuery first, then Popper.js, then Bootstrap JS --> | |||
| <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> | |||
| <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script> | |||
| </body> | |||
| </html> | |||
| @ -0,0 +1,66 @@ | |||
| p { | |||
|     font - size: 16 px; | |||
|     line - height: 1.5; | |||
| } | |||
| #subscribe_bid { | |||
|     color: #007bff; | |||
|     text-decoration:none; | |||
|     font-weight:bold; | |||
| } | |||
| #subscribe_bid:hover{ | |||
|     cursor:pointer; | |||
|     transform:scale(1.2); | |||
| } | |||
| 
 | |||
| #bidder_information{ | |||
|     width:100%; | |||
|     border-collapse:collapse; | |||
| } | |||
| #bidder_information th,td{ | |||
|     padding:8px; | |||
|     text-align:left; | |||
|     border-bottom:1px solid #ddd; | |||
| } | |||
| #bidder_information thead th{ | |||
|     position:sticky; | |||
|     top:0; | |||
|     background-color:#f5f5f5; | |||
| } | |||
| #bidder_information tbody{ | |||
|     height:200px; | |||
|     overflow-y:scroll; | |||
| } | |||
| #auction_bidders{ | |||
|     padding-left:60px; | |||
|     color: #007bff; | |||
| } | |||
| #auction_bidders:hover{ | |||
|     cursor:pointer; | |||
|     transform:scale(1.2); | |||
| } | |||
| #bid_amount{ | |||
|     max-width:10rem; | |||
|     font-size:16px; | |||
| } | |||
| .auction_timer{ | |||
|     border: 2px solid #ccc; | |||
|     border-radius:6px; | |||
|     padding:20px; | |||
|     display: inline-block; | |||
|     background:#dbdbdb4a; | |||
| } | |||
| .auction_timer:hover{ | |||
|     transform:scale(1.2); | |||
| } | |||
| #timer{ | |||
|     font-size: 24px; | |||
|     font-weight: bold; | |||
|     color: #333; | |||
|     background-color: #f5f5f5; | |||
| } | |||
| .auction_min_amount{ | |||
|     padding: 10px; | |||
| } | |||
| .alert { | |||
|     display: none; | |||
| } | |||
| @ -0,0 +1,270 @@ | |||
| /** @odoo-module **/ | |||
| import { WebsiteSale } from '@website_sale/js/website_sale'; | |||
| import { jsonrpc } from "@web/core/network/rpc_service"; | |||
| 
 | |||
| /**This is a JavaScript code written for the Odoo e-commerce platform. | |||
| It extends the functionality of the WebsiteSale module by adding an auction | |||
| feature, allowing customers to bid on products, and setting up a timer to track | |||
| the duration of the auction.**/ | |||
| WebsiteSale.include({ | |||
|     /**The start function initializes the auction timer when the page is loaded. | |||
|      It first checks if there are any ongoing auctions and hides the | |||
|      "add to cart" button if the product is being auctioned. Then, it retrieves | |||
|      the product and auction IDs from the input fields, sends an AJAX request to | |||
|       the server to fetch the auction details, and calculates the time remaining | |||
|        until the auction ends. If the auction has ended, the function redirects | |||
|         the user to the shop page, and if not, it sets up an interval to update | |||
|         the timer every second.**/ | |||
|     start: function() { | |||
|         /** function to add timer and check the time **/ | |||
|         this._super(...arguments); | |||
|         var modal_title = this.$('#modal_title')[0] | |||
|         var modal_message = this.$('#modal_message')[0] | |||
|         var product_name = this.$('input[name="auction_product_id"]').val(); | |||
|         var auction_id_status = this.$('input[name="auction_id"]').val() | |||
|         var bellIcon = this.el.querySelector('#subscribe_bid'); | |||
|         if (auction_id_status != undefined){ | |||
|         jsonrpc('/subscribe/status', { | |||
|                 'auction_id': auction_id_status, | |||
|             }).then((data) => { | |||
|             if (data){ | |||
|             bellIcon.style.color = 'red' | |||
|             bellIcon.classList.remove('fa-bell-o') | |||
|             bellIcon.classList.add('fa-bell') | |||
|             bellIcon.innerHTML = 'Unsubscribe' | |||
|             } | |||
|             else { | |||
|             bellIcon.style.color = '#007bff' | |||
|             bellIcon.classList.remove('fa-bell') | |||
|             bellIcon.classList.add('fa-bell-o') | |||
|             bellIcon.innerHTML = 'Subscribe' | |||
|             } | |||
|             }) | |||
|         } | |||
|         let auctionText = this.$('#modal_message')[0] | |||
|         if (auctionText) { | |||
|             $.each($('.o_wsale_product_btn'), (key, values) => { | |||
|                 if (values.nextElementSibling.innerHTML == 'AUCTION ON') { | |||
|                     values.style.display = "none" | |||
|                 } | |||
|             }) | |||
|         } | |||
|         let product_id = this.$('input[name="auction_product_id"]').val(); | |||
|         let auction_id = this.$('input[name="auction_id"]').val(); | |||
|         let timerId; // variable to hold the ID of the interval timer
 | |||
|         if (product_id) { | |||
|             let product_product_id = this.$('input[name="product_product_id"]').val() | |||
|             jsonrpc('/auction/timer', { | |||
|                 'product_id': product_id, | |||
|                 'auction_id': auction_id | |||
|             }).then((data) => { | |||
|                 if (new Date() > new Date(data['end_time'])) { | |||
|                     if (data['extend_time']) { | |||
|                         if (new Date() > new Date(data['extend_time'])) { | |||
|                             jsonrpc('/auction/close', { | |||
|                                 'product_id': product_id, | |||
|                                 'auction_id': auction_id | |||
|                             }).then(() => { | |||
|                                 jsonrpc('/shop/sale/order', { | |||
|                                     'product_product_id': product_product_id, | |||
|                                     'product_id': product_id, | |||
|                                     'auction_id': auction_id | |||
|                                 }) | |||
|                             }) | |||
|                             window.location.href = '/shop' | |||
|                         } | |||
|                     } else { | |||
|                         jsonrpc('/auction/close', { | |||
|                             'product_id': product_id, | |||
|                             'auction_id': auction_id | |||
|                         }).then(() => { | |||
|                             jsonrpc('/shop/sale/order', { | |||
|                                 'product_product_id': product_product_id, | |||
|                                 'product_id': product_id, | |||
|                                 'auction_id': auction_id | |||
|                             }) | |||
|                         }) | |||
|                         window.location.href = '/shop' | |||
|                     } | |||
|                 } else { | |||
|                     var self = this; | |||
|                     timerId = setInterval(function() { | |||
|                         var time_key = data['extend_time'] ? 'extend_time' : 'end_time' | |||
|                         var time_remaining = new Date(data[time_key]) - new Date() | |||
|                         var days = Math.floor(time_remaining / (1000 * 60 * 60 * 24)); | |||
|                         var hours = Math.floor((time_remaining / (1000 * 60 * 60)) % 24); | |||
|                         var minutes = Math.floor((time_remaining / (1000 * 60)) % 60); | |||
|                         var seconds = Math.floor((time_remaining / 1000) % 60); | |||
|                         if (self.el.querySelector('#timer')) { | |||
|                             self.el.querySelector('#timer').innerHTML = days + "d." + " " + hours + "h." + " " + minutes + "m." + " " + seconds + "s." | |||
|                         } | |||
|                         if (time_remaining <= 0) { | |||
|                             clearInterval(timerId); | |||
|                         } | |||
|                     }, 1000); | |||
|                     var time_key = data['extend_time'] ? 'extend_time' : 'end_time' | |||
|                     var time_remaining = new Date(data[time_key]) - new Date() | |||
|                     if (time_remaining <= 0) { | |||
|                         window.location.href = '/shop'; | |||
|                     } | |||
|                 } | |||
|             }) | |||
|         } | |||
|     }, | |||
|     events: { | |||
|         /** Click event for subscribe button**/ | |||
|         'click #subscribe_bid': '_clickSubscribe', | |||
| 
 | |||
|          /**Click event for add to cart and buy now buttons**/ | |||
|         'click #add_to_cart, .o_we_buy_now, #products_grid .o_wsale_product_btn .a-submit': 'async _onClickAdd', | |||
| 
 | |||
|          /**Click event for place bid button**/ | |||
|         'click #place_bid_button': '_placeBid', | |||
| 
 | |||
|          /**Click event for hide modal button**/ | |||
|         'click #hide_modal': '_hideModal', | |||
| 
 | |||
|          /**Click event for buy now button**/ | |||
|         'click .js_add_cart': '_buyNow' | |||
|     }, | |||
|     /** Function to hide auction messages after 5 seconds **/ | |||
|     timeout: function() { | |||
|         var self = this; | |||
|         setTimeout(function() { | |||
|             self.el.querySelector('#auction_messages').style.display = "none" | |||
|         }, 5000) | |||
|     }, | |||
|     /** Function to handle subscription to auction updates **/ | |||
|     _clickSubscribe: function() { | |||
|         // Get product and auction IDs
 | |||
|         let product_id = this.$('input[name="auction_product_id"]').val() | |||
|         let auction_id = this.$('input[name="auction_id"]').val(); | |||
| 
 | |||
|         // Get subscribe button and auction messages elements
 | |||
|         var bellIcon = this.el.querySelector('#subscribe_bid'); | |||
|         var messages = this.el.querySelector('#auction_messages') | |||
| 
 | |||
|         // If button says "Subscribe", subscribe user to auction updates
 | |||
|         if (bellIcon.innerHTML == 'Subscribe' ) { | |||
|             bellIcon.style.color = 'red' | |||
|             bellIcon.classList.remove('fa-bell-o') | |||
|             bellIcon.classList.add('fa-bell') | |||
|             bellIcon.innerHTML = 'Unsubscribe' | |||
|             jsonrpc('/subscribe/bid', { | |||
|                 'text': 'subscribe', | |||
|                 'product_id': product_id, | |||
|                 'auction_id': auction_id | |||
|             }).then((data) => { | |||
|                 messages.innerHTML = data | |||
|                 messages.classList.remove('alert-warning') | |||
|                 messages.classList.add('alert-success') | |||
|                 messages.style.display = "block" | |||
|                 this.timeout() | |||
|             }) | |||
|         } | |||
|         /** Otherwise, unsubscribe user from auction updates **/ | |||
|         else { | |||
|             bellIcon.style.color = '#007bff' | |||
|             bellIcon.classList.remove('fa-bell') | |||
|             bellIcon.classList.add('fa-bell-o') | |||
|             bellIcon.innerHTML = 'Subscribe' | |||
|             jsonrpc('/subscribe/bid', { | |||
|                 'text': 'unsubscribe', | |||
|                 'auction_id': auction_id | |||
|             }).then((data) => { | |||
|                 messages.classList.add('alert-warning') | |||
|                 messages.innerHTML = data | |||
|                 messages.style.display = "block" | |||
|                 this.timeout() | |||
|             }) | |||
|         } | |||
|     }, | |||
|     /** Function to handle adding products to cart **/ | |||
|     _onClickAdd: function(ev) { | |||
|         ev.preventDefault(); | |||
|         var def = () => { | |||
|             this.getCartHandlerOptions(ev); | |||
|             return this._handleAdd($(ev.currentTarget).closest('form')); | |||
|         }; | |||
|         if ($('.js_add_cart_variants').children().length) { | |||
|             return this._getCombinationInfo(ev).then(() => { | |||
|                 return !$(ev.target).closest('.js_product').hasClass("css_not_available") ? def() : Promise.resolve(); | |||
|             }); | |||
|         } | |||
|         return def(); | |||
|     }, | |||
|     /** Function to submit form when adding products to cart **/ | |||
|     _submitForm: function() { | |||
|         const params = this.rootProduct; | |||
|         const $product = $('#product_detail'); | |||
|         const productTrackingInfo = $product.data('product-tracking-info'); | |||
|         if (productTrackingInfo) { | |||
|             productTrackingInfo.quantity = params.quantity; | |||
|             $product.trigger('add_to_cart_event', [productTrackingInfo]); | |||
|         } | |||
|         params.add_qty = params.quantity; | |||
|         params.product_custom_attribute_values = JSON.stringify(params.product_custom_attribute_values); | |||
|         params.no_variant_attribute_values = JSON.stringify(params.no_variant_attribute_values); | |||
|         delete params.quantity; | |||
|         return this.addToCart(params); | |||
|     }, | |||
|     _placeBid: function() { | |||
|         /** Function to place a bid | |||
|          Get the bid amount and minimum amount from the page **/ | |||
|         var bid_amount = parseFloat(this.$('input[id="bid_amount"]').val()) | |||
|         var min_amount = parseFloat(this.$('#min_amount')[0].innerHTML) | |||
|         let product_id = this.$('input[name="auction_product_id"]').val() | |||
|         let auction_id = this.$('input[name="auction_id"]').val(); | |||
|         var messages = this.$('#auction_messages')[0] | |||
|         if (min_amount >= bid_amount) { | |||
|             modal_title.innerHTML = "Warning!" | |||
|             modal_message.innerHTML = "Please check the minimum bid amount" | |||
|             this.$('#modal_product_warning').modal('show') | |||
|         } else { | |||
|             jsonrpc('/place_bid', { | |||
|                 'bid_amount': bid_amount, | |||
|                 'product_id': product_id, | |||
|                 'auction_id': auction_id | |||
|             }).then((data) => { | |||
|                 if (data){ | |||
|                     messages.innerHTML = data['bid_placed'] | |||
|                     messages.style.display = "block"; | |||
|                     this.timeout() | |||
|                     window.location.reload() | |||
|                 } | |||
|                 else { | |||
|                     modal_title.innerHTML = "Same amount placed" | |||
|                     modal_message.innerHTML = "You have already placed this amount. Please reconsider your bid amount" | |||
|                     this.$('#modal_product_warning').modal('show') | |||
|                 } | |||
|             }) | |||
|         } | |||
|     }, | |||
|     /**Click event for hide modal button**/ | |||
|     _hideModal: function() { | |||
|         this.$('#modal_product_warning').modal('hide') | |||
|     }, | |||
|     _buyNow: function() { | |||
|         /** function for buy now button **/ | |||
|         let product_id = this.$('input[name="auction_product_id"]').val() | |||
|         let product_template_id = this.$('input[name="product_product_id"]').val() | |||
|         let auction_id = this.$('input[name="auction_id"]').val(); | |||
|         jsonrpc('/buy/now', { | |||
|             product_id: parseInt(product_template_id), | |||
|             'product_id': product_template_id, | |||
|             'auction_id': auction_id, | |||
|             'auction_product_id': product_id, | |||
|             'add_qty': 1 | |||
|         }).then(function(data) {}) | |||
|         jsonrpc('/auction/close', { | |||
|             'product_id': product_id, | |||
|             'auction_id': auction_id, | |||
|         }) | |||
|         modal_title.innerHTML = "Success" | |||
|         modal_message.innerHTML = "You will get a email please confirm and pay now you will be redirected to home page" | |||
|         $('#modal_product_warning').modal('show') | |||
|         setTimeout(function() { | |||
|         window.location.href = '/shop' | |||
|         }, 5000) | |||
|     }, | |||
| }) | |||
| @ -0,0 +1,51 @@ | |||
| <?xml version="1.0" encoding="UTF-8" ?> | |||
| <odoo> | |||
|     <!-- Define a form view for the bargain information model --> | |||
|     <record id="bargain_information_view_form" model="ir.ui.view"> | |||
|         <field name="name">bargain.information.view.form</field> | |||
|         <field name="model">bargain.information</field> | |||
|         <field name="arch" type="xml"> | |||
|             <form> | |||
|                 <sheet> | |||
|                     <group> | |||
|                         <group> | |||
|                             <field name="bidder_id"/> | |||
|                             <field name="auction_id"/> | |||
|                             <field name="product_id"/> | |||
|                         </group> | |||
|                         <group> | |||
|                             <field name="currency_id" invisible="1"/> | |||
|                             <field name="bid_offer" widget="monetary" | |||
|                                    force_save="1"/> | |||
|                             <field name="status"/> | |||
|                         </group> | |||
|                     </group> | |||
|                 </sheet> | |||
|                 <div class="oe_chatter"> | |||
|                     <field name="message_follower_ids"/> | |||
|                     <field name="activity_ids"/> | |||
|                     <field name="message_ids" | |||
|                            options="{'post_refresh':'recipients'}"/> | |||
|                 </div> | |||
|             </form> | |||
|         </field> | |||
|     </record> | |||
|     <!-- Define a tree view for the bargain information model --> | |||
|     <record id="bargain_information_view_tree" model="ir.ui.view"> | |||
|         <field name="name">bargain.information.view.tree</field> | |||
|         <field name="model">bargain.information</field> | |||
|         <field name="arch" type="xml"> | |||
|             <tree> | |||
|                 <field name="bidder_id"/> | |||
|                 <field name="auction_id"/> | |||
|                 <field name="bid_offer"/> | |||
|                 <field name="status"/> | |||
|             </tree> | |||
|         </field> | |||
|     </record> | |||
|     <record id="bargain_information_action" model="ir.actions.act_window"> | |||
|         <field name="name">Bidder Information</field> | |||
|         <field name="res_model">bargain.information</field> | |||
|         <field name="view_mode">tree,form,activity</field> | |||
|     </record> | |||
| </odoo> | |||
| @ -0,0 +1,53 @@ | |||
| <?xml version="1.0" encoding="UTF-8" ?> | |||
| <odoo> | |||
|     <!-- Define a form view for the "bargain.subscribers" model --> | |||
|     <record id="bargain_subscribers_view_form" model="ir.ui.view"> | |||
|         <field name="name">bargain.subscribers.view.form</field> | |||
|         <field name="model">bargain.subscribers</field> | |||
|         <field name="arch" type="xml"> | |||
|             <form> | |||
|                 <sheet> | |||
|                     <group> | |||
|                         <group> | |||
|                             <field name="subscriber_id"/> | |||
|                             <field name="name"/> | |||
|                             <field name="email"/> | |||
|                         </group> | |||
|                         <group> | |||
|                             <field name="auction_id"/> | |||
|                             <field name="subscribe_time"/> | |||
|                             <field name="is_subscribed"/> | |||
|                         </group> | |||
|                     </group> | |||
|                 </sheet> | |||
|                 <!-- Add a chatter to the form view for messaging and activities --> | |||
|                 <div class="oe_chatter"> | |||
|                     <field name="message_follower_ids"/> | |||
|                     <field name="activity_ids"/> | |||
|                     <field name="message_ids" | |||
|                            options="{'post_refresh':'recipients'}"/> | |||
|                 </div> | |||
|             </form> | |||
|         </field> | |||
|     </record> | |||
|     <!-- Define a tree view for the "bargain.subscribers" model --> | |||
|     <record id="bargain_subscribers_view_tree" model="ir.ui.view"> | |||
|         <field name="name">bargain.subscribers.view.tree</field> | |||
|         <field name="model">bargain.subscribers</field> | |||
|         <field name="arch" type="xml"> | |||
|             <tree> | |||
|                 <field name="subscriber_id"/> | |||
|                 <field name="name"/> | |||
|                 <field name="email"/> | |||
|                 <field name="auction_id"/> | |||
|                 <field name="subscribe_time"/> | |||
|             </tree> | |||
|         </field> | |||
|     </record> | |||
|     <!-- Define an action to open the "bargain.subscribers" model --> | |||
|     <record id="bargain_subscribers_action" model="ir.actions.act_window"> | |||
|         <field name="name">Bargain Subscribers</field> | |||
|         <field name="res_model">bargain.subscribers</field> | |||
|         <field name="view_mode">tree,form</field> | |||
|     </record> | |||
| </odoo> | |||
| @ -0,0 +1,31 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo> | |||
|     <!-- Define a view for the website bargain template --> | |||
|     <record id="bargain_template_view_form" model="ir.ui.view"> | |||
|         <field name="name">bargain.template.view.form</field> | |||
|         <field name="model">bargain.template</field> | |||
|         <field name="arch" type="xml"> | |||
|             <form> | |||
|                 <sheet> | |||
|                     <!-- Define a group for the name and product_id fields --> | |||
|                     <group class="mt-4"> | |||
|                         <field name="name"/> | |||
|                         <field name="product_id"/> | |||
|                     </group> | |||
|                 </sheet> | |||
|                 <div class="oe_chatter"> | |||
|                     <field name="message_follower_ids"/> | |||
|                     <field name="activity_ids"/> | |||
|                     <field name="message_ids" | |||
|                            options="{'post_refres':'recipients'}"/> | |||
|                 </div> | |||
|             </form> | |||
|         </field> | |||
|     </record> | |||
|     <!-- Define an action for the bargain template --> | |||
|     <record id="bargain_template_action" model="ir.actions.act_window"> | |||
|         <field name="name">Website Bidding Template</field> | |||
|         <field name="res_model">bargain.template</field> | |||
|         <field name="view_mode">tree,form</field> | |||
|     </record> | |||
| </odoo> | |||
| @ -0,0 +1,64 @@ | |||
| <?xml version="1.0" encoding="UTF-8" ?> | |||
| <odoo> | |||
|     <template id="bidders_information" name="Website bidders"> | |||
|         <!-- Template extending website.layout --> | |||
|         <t t-call="website.layout"> | |||
|             <div id="wrap" class="o_portal_wrap"> | |||
|                 <div class="container mv64"> | |||
|                     <!-- Bootstrap table to show bidders information --> | |||
|                     <div class="table-responsive border rounded border-top-0 "> | |||
|                         <!-- Title of the table --> | |||
|                         <h2 class="text-center">Bid for | |||
|                             <t t-esc="product_id.name"/> | |||
|                         </h2> | |||
|                         <!-- Table headers --> | |||
|                         <table id="bidder_information"> | |||
|                             <thead> | |||
|                                 <tr class="active"> | |||
|                                     <th class="text-center">Name</th> | |||
|                                     <th class="text-center">Bid Amount</th> | |||
|                                     <th class="text-center">Bid Status</th> | |||
|                                     <th class="text-center">Phone</th> | |||
|                                     <th class="text-center">Email</th> | |||
|                                 </tr> | |||
|                             </thead> | |||
|                             <tbody> | |||
|                                 <!-- Looping over the bidders_information to show the bid details --> | |||
|                                 <t t-foreach="bidders_information" | |||
|                                    t-as="bidders"> | |||
|                                     <tr> | |||
|                                         <!-- Bidder's name --> | |||
|                                         <td class="text-center" | |||
|                                             t-esc="bidders.bidder_id.name"/> | |||
|                                         <!-- Bid amount --> | |||
|                                         <td class="text-center" | |||
|                                             t-esc="bidders.bid_offer"/> | |||
|                                         <!-- Bid status --> | |||
|                                         <td class="text-center" | |||
|                                             t-esc="bidders.status"/> | |||
|                                         <!-- Bidder's phone number --> | |||
|                                         <td class="text-center" | |||
|                                             t-esc="bidders.bidder_id.phone"/> | |||
|                                         <!-- Bidder's email --> | |||
|                                         <td class="text-center" | |||
|                                             t-esc="bidders.bidder_id.email"/> | |||
|                                         <!-- Checking if the bidder is the current user and the bid status is 'Bid Placed', then show cancel bid link --> | |||
|                                         <t t-set="partner" | |||
|                                            t-value="request.env.user.partner_id"/> | |||
|                                         <t t-if="(bidders.status=='Bid Placed') and (partner==bidders.bidder_id)"> | |||
|                                             <td> | |||
|                                                 <a t-attf-href="/bid/cancel/{{ slug(bidders) }}"> | |||
|                                                     cancel bid | |||
|                                                 </a> | |||
|                                             </td> | |||
|                                         </t> | |||
|                                     </tr> | |||
|                                 </t> | |||
|                             </tbody> | |||
|                         </table> | |||
|                     </div> | |||
|                 </div> | |||
|             </div> | |||
|         </t> | |||
|     </template> | |||
| </odoo> | |||
| @ -0,0 +1,17 @@ | |||
| <?xml version="1.0" encoding="UTF-8" ?> | |||
| <odoo> | |||
|     <!--Inherit product template to add auction --> | |||
|     <record id="product_template_only_form_view" model="ir.ui.view"> | |||
|         <field name="name">product.template.view.form.inherit.website.bargain | |||
|         </field> | |||
|         <field name="model">product.template</field> | |||
|         <field name="inherit_id" | |||
|                ref="product.product_template_only_form_view"/> | |||
|         <field name="arch" type="xml"> | |||
|             <xpath expr="//page[@name='sales']//group[@name='shop']" | |||
|                    position="inside"> | |||
|                 <field name="is_auction"/> | |||
|             </xpath> | |||
|         </field> | |||
|     </record> | |||
| </odoo> | |||
| @ -0,0 +1,27 @@ | |||
| <?xml version="1.0" encoding="UTF-8" ?> | |||
| <odoo> | |||
|     <menuitem id="website_auction_menu" | |||
|               name="Auction" | |||
|               sequence="10" | |||
|               parent="website.menu_website_configuration"/> | |||
|     <menuitem id="website_bargain_menu_open_website_bargain" | |||
|               parent="website_auction_menu" | |||
|               sequence="20" | |||
|               name="Auctions" | |||
|               action="website_bargain_action"/> | |||
|     <menuitem id="bargain_template_menu_open_bargain_template" | |||
|               parent="website_auction_menu" | |||
|               sequence="21" | |||
|               name="Template" | |||
|               action="bargain_template_action"/> | |||
|     <menuitem id="bargain_information_menu_open_bidder_information" | |||
|               parent="website_auction_menu" | |||
|               sequence="23" | |||
|               name="Bidder Information" | |||
|               action="bargain_information_action"/> | |||
|     <menuitem id="bargain_subscribers_menu_open_bargain_subscribers" | |||
|               parent="website_auction_menu" | |||
|               sequence="24" | |||
|               name="Subscribers" | |||
|               action="bargain_subscribers_action"/> | |||
| </odoo> | |||
| @ -0,0 +1,158 @@ | |||
| <?xml version="1.0" encoding="UTF-8" ?> | |||
| <odoo> | |||
|     <!-- Form view for website.bargain model --> | |||
|     <record id="website_bargain_view_form" model="ir.ui.view"> | |||
|         <field name="name">website.bargain.view.form</field> | |||
|         <field name="model">website.bargain</field> | |||
|         <field name="arch" type="xml"> | |||
|             <form> | |||
|                 <header> | |||
|                     <button name="action_confirm" type="object" | |||
|                             string="Confirm" class="oe_highlight" | |||
|                             invisible="state == True or state not in ('draft')"/> | |||
|                     <button name="action_reset_to_draft" type="object" | |||
|                             string="Reset to draft" class="oe_highlight" | |||
|                             invisible="state == True or state in ('draft', 'finished','closed') "/> | |||
|                     <button name="action_run_auction" type="object" | |||
|                             string="Run Auction" class="oe_highlight" | |||
|                             invisible="state == True or state not in ('confirmed')"/> | |||
|                     <button name="action_complete" type="object" | |||
|                             string="Completed" class="oe_highlight" | |||
|                             invisible="state == True or state not in ('running', 'extended')"/> | |||
|                     <button name="action_close" type="object" string="Closed" | |||
|                             class="oe_highlight" | |||
|                             invisible="state == True or state not in ('running', 'extended','finished')" | |||
|                             /> | |||
|                     <field name="state" widget="statusbar"/> | |||
|                 </header> | |||
|                 <sheet> | |||
|                     <group class="mt-4"> | |||
|                         <field name="website_id" | |||
|                                readonly="state not in ['draft']"/> | |||
|                         <field name="auction_manager_id" | |||
|                                readonly="state not in ['draft']"/> | |||
|                         <field name="template_id" | |||
|                                readonly="state not in ['draft']"/> | |||
|                         <field name="product_id" | |||
|                                readonly="state not in ['draft']"/> | |||
|                         <field name="name" | |||
|                                readonly="state not in ['draft']"/> | |||
|                     </group> | |||
|                     <group> | |||
|                         <group name="price_configuration" | |||
|                                string="Price Configuration"> | |||
|                             <field name="currency_id" position="attributes" | |||
|                                    readonly="state not in ['draft']"/> | |||
|                             <field name="initial_price" widget="monetary" | |||
|                                    readonly="state not in ['draft']" | |||
|                                    force_save="1"/> | |||
|                             <field name="is_buy_now" | |||
|                                    readonly="state not in ['draft']"/> | |||
|                             <field name="price_buy_now" widget="monetary" | |||
|                                    force_save="1" | |||
|                                    invisible="is_buy_now == False" | |||
|                                    /> | |||
|                         </group> | |||
|                         <group name="time_configuration" | |||
|                                string="TIME CONFIGURATION"> | |||
|                             <field name="start_time" | |||
|                                    readonly="state not in ['draft']"/> | |||
|                             <field name="end_time" | |||
|                                    readonly="state not in ['draft']"/> | |||
|                             <field name="extend_time" | |||
|                                    readonly="state in ['finished', 'closed']" | |||
|                                    /> | |||
|                         </group> | |||
|                     </group> | |||
|                     <notebook> | |||
|                         <page name="bidder_information" | |||
|                               string="Bidder Information" sequence="2"> | |||
|                             <div> | |||
|                                 <h4>Bidder Information</h4> | |||
|                             </div> | |||
|                             <field name="bargain_information_ids"/> | |||
|                         </page> | |||
|                         <page name="subscribers" string="Subscribers" | |||
|                               sequence="3"> | |||
|                             <div> | |||
|                                 <h4>Subscribers</h4> | |||
|                             </div> | |||
|                             <field name="bargain_subscribers_ids"/> | |||
|                         </page> | |||
|                         <page name="notification" string="Notification" | |||
|                               sequence="4"> | |||
|                             <group> | |||
|                                 <group string="Notification to admin"> | |||
|                                     <field name="is_activate"/> | |||
|                                     <label for="notify_on" | |||
|                                            string="Notify before" | |||
|                                            invisible="is_activate == False"/> | |||
|                                     <div class="o_checkbox_optional_field" | |||
|                                          invisible="is_activate == False"> | |||
|                                         <field name="notify_on" | |||
|                                                class="oe_inline"/> | |||
|                                         <div class="oe_inline"> | |||
|                                             <field name="notify_selection"/> | |||
|                                         </div> | |||
|                                     </div> | |||
|                                     <field name="is_notification_send" | |||
|                                            invisible="is_activate == False" | |||
|                                            /> | |||
|                                 </group> | |||
|                                 <group string="Miscellaneous Notification Settings"> | |||
|                                     <field name="is_winner_notification"/> | |||
|                                     <field name="is_loser_notification"/> | |||
|                                 </group> | |||
|                                 <group string="Subscriber Notification"> | |||
|                                     <field name="is_subscriber_start_notification"/> | |||
|                                     <field name="is_extend_auction_notification"/> | |||
|                                     <field name="is_new_bid_notification"/> | |||
|                                     <field name="is_bid_end_notification"/> | |||
|                                     <field name="is_send_mail" invisible="1"/> | |||
|                                 </group> | |||
|                             </group> | |||
|                         </page> | |||
|                         <page name="product_info" string="Product Info"> | |||
|                             <group string="Product Information"> | |||
|                                 <field name="product_img" widget="image" | |||
|                                        style="padding: 0px;" nolabel="1"/> | |||
|                             </group> | |||
|                             <group> | |||
|                                 <field name="product_id" | |||
|                                        string="Auction Product Name"/> | |||
|                                 <field name="product_description"/> | |||
|                             </group> | |||
|                         </page> | |||
|                     </notebook> | |||
|                 </sheet> | |||
|                 <div class="oe_chatter"> | |||
|                     <field name="message_follower_ids"/> | |||
|                     <field name="activity_ids"/> | |||
|                     <field name="message_ids" | |||
|                            options="{'post_refres':'recipients'}"/> | |||
|                 </div> | |||
|             </form> | |||
|         </field> | |||
|     </record> | |||
|     <!-- Tree view for website.bargain model --> | |||
|     <record id="website_bargain_view_tree" model="ir.ui.view"> | |||
|         <field name="name">website.bargain.view.tree</field> | |||
|         <field name="model">website.bargain</field> | |||
|         <field name="arch" type="xml"> | |||
|             <tree> | |||
|                 <field name="name"/> | |||
|                 <field name="product_id"/> | |||
|                 <field name="start_time"/> | |||
|                 <field name="end_time"/> | |||
|                 <field name="extend_time" optional="hide"/> | |||
|                 <field name="state"/> | |||
|                 <field name="website_id" optional="hide"/> | |||
|             </tree> | |||
|         </field> | |||
|     </record> | |||
|     <record id="website_bargain_action" model="ir.actions.act_window"> | |||
|         <field name="name">Website Bargain</field> | |||
|         <field name="res_model">website.bargain</field> | |||
|         <field name="view_mode">tree,form</field> | |||
|     </record> | |||
| </odoo> | |||
| @ -0,0 +1,241 @@ | |||
| <?xml version="1.0" encoding="UTF-8" ?> | |||
| <odoo> | |||
|     <template id="website_product_view" inherit_id="website_sale.product"> | |||
|         <xpath expr="//div[@id='product_details']" position="replace"> | |||
|             <t t-if="product.is_auction"> <!-- Conditionally render elements based on the "is_auction" attribute of the product object --> | |||
|                 <!-- Create hidden input fields with values from the product and auction objects --> | |||
|                 <t t-if="request.env.user.is_public"> | |||
|                     <t t-log="request.env.user.is_public"/> | |||
|                     <div t-attf-class="col-lg-#{image_cols[1]} mt-md-4" | |||
|                          id="product_details"> | |||
|                         <h1 itemprop="name" t-field="product.name"> | |||
|                             Product | |||
|                             Name | |||
|                         </h1> | |||
|                         Please <a href="/web/login">sign in</a> to participate | |||
|                     </div> | |||
|                 </t> | |||
|                 <t t-else=""> | |||
|                     <input type="hidden" class="product_id" | |||
|                            name="product_product_id" | |||
|                            t-att-value="product_variant.id"/> | |||
|                     <input type="hidden" name="auction_product_id" | |||
|                            t-att-value="product.id"/> | |||
|                     <!-- Iterate over the auction objects --> | |||
|                     <t t-foreach="auction" t-as="bid"> | |||
|                         <!-- Check if the auction is running, matches the current product, and matches the current website --> | |||
|                         <t t-if="(bid['state']=='running') and (bid['product_id'][0]==product.id) and (website.id == bid['website_id'][0])"> | |||
|                             <input type="hidden" class="auction" | |||
|                                    name="auction_id" t-att-value="bid['id']"/> | |||
|                             <!-- Create a div to display details about the product and auction --> | |||
|                             <div t-attf-class="col-lg-#{image_cols[1]} mt-md-4" | |||
|                                  id="product_details"> | |||
|                                 <h1 itemprop="name" t-field="product.name"> | |||
|                                     Product | |||
|                                     Name | |||
|                                 </h1> | |||
|                                 <span id="auction_messages" | |||
|                                       class="alert alert-info"/> | |||
|                                 <div class="auction_timer"> | |||
|                                     Auction will end in | |||
|                                     <h3 id="timer">---</h3> | |||
|                                     Till | |||
|                                     <!-- Display either the extended time or the end time of the auction --> | |||
|                                     <t t-if="bid['extend_time']"> | |||
|                                         <t t-esc="bid['extend_time']"/> | |||
|                                     </t> | |||
|                                     <t t-else=""> | |||
|                                         <t t-esc="bid['end_time']"/> | |||
|                                     </t> | |||
|                                 </div> | |||
|                                 <div class="auction_min_amount"> | |||
|                                     Min bid amount | |||
|                                     <t t-esc="bid['currency_id'][1] "/> | |||
|                                     <strong id="min_amount" | |||
|                                             t-esc="bid['initial_price']"/> | |||
|                                 </div> | |||
|                                 <input type="number" id="bid_amount" step="any" | |||
|                                        required="1"/> | |||
|                                 <button type="button" class="btn btn-primary" | |||
|                                         id="place_bid_button">Place bid | |||
|                                 </button> | |||
|                                 <p class="subscribe"> | |||
|                                     <i class="fa fa-bell-o o_notification_icon" | |||
|                                        id="subscribe_bid">Subscribe | |||
|                                     </i> | |||
|                                     <i class="fa fa-users" id="auction_bidders"> | |||
|                                         <a t-attf-href="/bidders/{{ slug(product) }}"> | |||
|                                             Bidders | |||
|                                         </a> | |||
|                                     </i> | |||
|                                 </p> | |||
|                                 <!-- Create a modal to display warnings or messages about the auction --> | |||
|                                 <div class="modal fade" | |||
|                                      id="modal_product_warning" | |||
|                                      tableindex="-1" role="dialog"> | |||
|                                     <div class="modal-dialog" role="document"> | |||
|                                         <div class="modal-content"> | |||
|                                             <div class="modal-header"> | |||
|                                                 <h4 class="modal-title" | |||
|                                                     id="modal_title"/> | |||
|                                             </div> | |||
|                                             <div class="modal-body"> | |||
|                                                 <p class="message" | |||
|                                                    id="modal_message"/> | |||
| 
 | |||
|                                             </div> | |||
|                                             <div class="modal-footer"> | |||
|                                                 <button type="button" | |||
|                                                         id="hide_modal" | |||
|                                                         class="btn btn-default" | |||
|                                                         data-dismiss="modal"> | |||
|                                                     Close | |||
|                                                 </button> | |||
|                                             </div> | |||
|                                         </div> | |||
|                                     </div> | |||
|                                 </div> | |||
|                                 <!-- Display a "buy now" option if the auction allows it --> | |||
|                                 <t t-if="bid['is_buy_now']"> | |||
|                                     <div> | |||
|                                         or | |||
|                                         <br/> | |||
|                                         <a class="btn btn-primary js_add_cart" | |||
|                                            data-productiid="1">Buy Now | |||
|                                         </a> | |||
|                                         For just | |||
|                                         <t t-esc="bid['currency_id'][1]"/> | |||
|                                         <t t-esc="bid['price_buy_now']"/> | |||
|                                     </div> | |||
|                                 </t> | |||
|                             </div> | |||
|                             <div id="o_product_terms_and_share" | |||
|                                  class="d-flex justify-content-between flex-column flex-md-row align-items-md-end mb-3"> | |||
|                             </div> | |||
|                         </t> | |||
|                     </t> | |||
|                 </t> | |||
|             </t> | |||
|             <t t-else=""> <!-- start of else block --> | |||
|                 <div t-attf-class="col-lg-#{image_cols[1]} mt-md-4" id="product_details"> | |||
|                     <t t-set="base_url" t-value="product.get_base_url()"/> | |||
|                     <h1 itemprop="name" t-field="product.name">Product Name</h1> | |||
|                     <span itemprop="url" style="display:none;" t-esc="base_url + product.website_url"/> | |||
|                     <span itemprop="image" style="display:none;" | |||
|                           t-esc="base_url + website.image_url(product, 'image_1920')"/> | |||
|                     <t t-if="is_view_active('website_sale.product_comment')"> | |||
|                         <a href="#o_product_page_reviews" class="o_product_page_reviews_link text-decoration-none"> | |||
|                             <t t-call="portal_rating.rating_widget_stars_static"> | |||
|                                 <t t-set="rating_avg" t-value="product.rating_avg"/> | |||
|                                 <t t-set="trans_text_plural">%s reviews</t> | |||
|                                 <t t-set="trans_text_singular">%s review</t> | |||
|                                 <t t-set="rating_count" | |||
|                                    t-value="(trans_text_plural if product.rating_count > 1 else trans_text_singular) % product.rating_count"/> | |||
|                             </t> | |||
|                         </a> | |||
|                     </t> | |||
|                     <p t-field="product.description_sale" class="text-muted my-2" | |||
|                        placeholder="A short description that will also appear on documents."/> | |||
|                     <div t-field="product.description_ecommerce" class="oe_structure" | |||
|                          placeholder="A detailed, formatted description to promote your product on this page. Use '/' to discover more features."/> | |||
|                     <form t-if="product._is_add_to_cart_possible()" action="/shop/cart/update" method="POST"> | |||
|                         <input type="hidden" name="csrf_token" t-att-value="request.csrf_token()" | |||
|                                t-nocache="The csrf token must always be up to date."/> | |||
|                         <div class="js_product js_main_product mb-3"> | |||
|                             <div> | |||
|                                 <t t-call="website_sale.product_price"/> | |||
|                                 <small t-if="combination_info['base_unit_price']" | |||
|                                        class="ms-1 text-muted o_base_unit_price_wrapper d-none" | |||
|                                        groups="website_sale.group_show_uom_price"> | |||
|                                     <t t-call='website_sale.base_unit_price'/> | |||
|                                 </small> | |||
|                             </div> | |||
|                             <t t-placeholder="select"> | |||
|                                 <input type="hidden" class="product_id" name="product_id" | |||
|                                        t-att-value="product_variant.id"/> | |||
|                                 <input type="hidden" class="product_template_id" name="product_template_id" | |||
|                                        t-att-value="product.id"/> | |||
|                                 <input t-if="product.public_categ_ids.ids" type="hidden" class="product_category_id" | |||
|                                        name="product_category_id" t-att-value="product.public_categ_ids.ids[0]"/> | |||
|                                 <t t-call="website_sale.variants"> | |||
|                                     <t t-set="ul_class" t-valuef="flex-column"/> | |||
|                                     <t t-set="parent_combination" t-value="None"/> | |||
|                                 </t> | |||
|                             </t> | |||
|                             <p t-if="True" class="css_not_available_msg alert alert-warning">This combination does not | |||
|                                 exist. | |||
|                             </p> | |||
|                             <div id="o_wsale_cta_wrapper" class="d-flex flex-wrap align-items-center"> | |||
|                                 <t t-set="hasQuantities" t-value="false"/> | |||
|                                 <t t-set="hasBuyNow" t-value="false"/> | |||
|                                 <t t-set="ctaSizeBig" t-value="not hasQuantities or not hasBuyNow"/> | |||
| 
 | |||
|                                 <div id="add_to_cart_wrap" | |||
|                                      t-attf-class="{{'d-none' if combination_info['prevent_zero_price_sale'] else 'd-inline-flex'}} align-items-center mb-2 me-auto"> | |||
|                                     <a data-animation-selector=".o_wsale_product_images" role="button" id="add_to_cart" | |||
|                                        t-attf-class="btn btn-primary js_check_product a-submit flex-grow-1" href="#"> | |||
|                                         <i class="fa fa-shopping-cart me-2"/> | |||
|                                         Add to cart | |||
|                                     </a> | |||
|                                 </div> | |||
|                                 <div id="product_option_block" class="d-flex flex-wrap w-100"/> | |||
|                             </div> | |||
|                             <div id="contact_us_wrapper" | |||
|                                  t-attf-class="{{'d-flex' if combination_info['prevent_zero_price_sale'] else 'd-none'}} oe_structure oe_structure_solo #{_div_classes}"> | |||
|                                 <section class="s_text_block" data-snippet="s_text_block" data-name="Text"> | |||
|                                     <div class="container"> | |||
|                                         <a t-att-href="website.contact_us_button_url" | |||
|                                            class="btn btn-primary btn_cta">Contact Us | |||
|                                         </a> | |||
|                                     </div> | |||
|                                 </section> | |||
|                             </div> | |||
|                             <t t-if="is_view_active('website_sale.product_tags')" t-call="website_sale.product_tags"> | |||
|                                 <t t-set="all_product_tags" t-value="product_variant.all_product_tag_ids"/> | |||
|                             </t> | |||
|                         </div> | |||
|                     </form> | |||
|                     <p t-elif="not product.active" class="alert alert-warning">This product is no longer available.</p> | |||
|                     <p t-else="" class="alert alert-warning">This product has no valid combination.</p> | |||
|                     <div id="product_attributes_simple"> | |||
|                         <t t-set="single_value_attributes" | |||
|                            t-value="product.valid_product_template_attribute_line_ids._prepare_single_value_for_display()"/> | |||
|                         <table t-attf-class="table table-sm text-muted {{'' if single_value_attributes else 'd-none'}}"> | |||
|                             <t t-foreach="single_value_attributes" t-as="attribute"> | |||
|                                 <tr> | |||
|                                     <td> | |||
|                                         <span t-field="attribute.name"/>: | |||
|                                         <t t-foreach="single_value_attributes[attribute]" t-as="ptal"> | |||
|                                             <span t-field="ptal.product_template_value_ids._only_active().name"/> | |||
|                                             <t t-if="not ptal_last">,</t> | |||
|                                         </t> | |||
|                                     </td> | |||
|                                 </tr> | |||
|                             </t> | |||
|                         </table> | |||
|                     </div> | |||
|                     <t t-set="product_documents" | |||
|                        t-value="product.sudo().product_document_ids.filtered(lambda doc: doc.shown_on_product_page)"/> | |||
|                     <div id="product_documents" class="my-2" t-if="product_documents"> | |||
|                         <h5>Documents</h5> | |||
|                         <t t-foreach="product_documents" t-as="document_sudo"> | |||
|                             <t t-set="attachment_sudo" t-value="document_sudo.ir_attachment_id"/> | |||
|                             <t t-set="target" t-value="attachment_sudo.type == 'url' and '_blank' or '_self'"/> | |||
|                             <t t-set="icon" t-value="attachment_sudo.type == 'url' and 'fa-link' or 'fa-download'"/> | |||
|                             <div> | |||
|                                 <a t-att-href="'/shop/' + slug(product) + '/document/' + str(document_sudo.id)" | |||
|                                    t-att-target="target"> | |||
|                                     <i t-att-class="'fa ' + icon"/> | |||
|                                     <t t-out="attachment_sudo.name"/> | |||
|                                 </a> | |||
|                             </div> | |||
|                         </t> | |||
|                     </div> | |||
|                     <div id="o_product_terms_and_share" | |||
|                          class="d-flex justify-content-between flex-column flex-md-row align-items-md-end mb-3"> | |||
|                     </div> | |||
|                 </div> | |||
|             </t> | |||
|         </xpath> | |||
|     </template> | |||
| </odoo> | |||
| @ -0,0 +1,40 @@ | |||
| <?xml version="1.0" encoding="UTF-8" ?> | |||
| <odoo> | |||
|     <!-- This template is used to modify the product page on the Odoo e-commerce website. --> | |||
|     <template id="website_shop_auction" inherit_id="website_sale.products_item"> | |||
|         <!-- Replace the existing div with class "product_price" --> | |||
|         <xpath expr="//div[hasclass('product_price')]" position="replace"> | |||
|             <!-- If the product is an auction, display "AUCTION ON" --> | |||
|             <t t-if="product.is_auction"> | |||
|                 <span id="auction_on">AUCTION ON</span> | |||
|             </t> | |||
|             <!-- If the product is not an auction, display the regular price --> | |||
|             <t t-else=""> | |||
|                 <div class="product_price" itemprop="offers" | |||
|                      itemscope="itemscope" itemtype="http://schema.org/Offer"> | |||
|                     <t t-if="'base_price' in template_price_vals"> | |||
|                         <del t-attf-class="text-muted me-1 h6 mb-0" | |||
|                              style="white-space: nowrap;"> | |||
|                             <!-- Display the original price with a strikethrough --> | |||
|                             <em class="small" | |||
|                                 t-esc="template_price_vals['base_price']" | |||
|                                 t-options="{'widget': 'monetary', 'display_currency': website.currency_id}"/> | |||
|                         </del> | |||
|                     </t> | |||
|                     <!-- Display the reduced price, or the text "Contact us for price" if the price is zero --> | |||
|                     <span class="h6 mb-0" | |||
|                           t-if="template_price_vals['price_reduce'] or not website.prevent_zero_price_sale" | |||
|                           t-esc="template_price_vals['price_reduce']" | |||
|                           t-options="{'widget': 'monetary', 'display_currency': website.currency_id}"/> | |||
|                     <span class="h6 mb-0" t-else="" | |||
|                           t-field="website.prevent_zero_price_sale_text"/> | |||
|                     <!-- Set the price and currency information for the schema.org metadata --> | |||
|                     <span itemprop="price" style="display:none;" | |||
|                           t-esc="template_price_vals['price_reduce']"/> | |||
|                     <span itemprop="priceCurrency" style="display:none;" | |||
|                           t-esc="website.currency_id.name"/> | |||
|                 </div> | |||
|             </t> | |||
|         </xpath> | |||
|     </template> | |||
| </odoo> | |||