Browse Source

Dec 04 : [ADD] Initial Commit 'website_bargain'

pull/295/head
RisvanaCybro 1 year ago
parent
commit
04945ab9cc
  1. 44
      website_bargain/README.rst
  2. 22
      website_bargain/__init__.py
  3. 60
      website_bargain/__manifest__.py
  4. 22
      website_bargain/controllers/__init__.py
  5. 318
      website_bargain/controllers/website_bargain.py
  6. 25
      website_bargain/data/ir_cron_data.xml
  7. 104
      website_bargain/data/mail_template_data.xml
  8. 6
      website_bargain/doc/RELEASE_NOTES.md
  9. 26
      website_bargain/models/__init__.py
  10. 45
      website_bargain/models/bargain_information.py
  11. 44
      website_bargain/models/bargain_subscribers.py
  12. 37
      website_bargain/models/bargain_template.py
  13. 32
      website_bargain/models/product_template.py
  14. 301
      website_bargain/models/website_bargain.py
  15. 5
      website_bargain/security/ir.model.access.csv
  16. BIN
      website_bargain/static/description/assets/icons/check.png
  17. BIN
      website_bargain/static/description/assets/icons/chevron.png
  18. BIN
      website_bargain/static/description/assets/icons/cogs.png
  19. BIN
      website_bargain/static/description/assets/icons/consultation.png
  20. BIN
      website_bargain/static/description/assets/icons/ecom-black.png
  21. BIN
      website_bargain/static/description/assets/icons/education-black.png
  22. BIN
      website_bargain/static/description/assets/icons/hotel-black.png
  23. BIN
      website_bargain/static/description/assets/icons/license.png
  24. BIN
      website_bargain/static/description/assets/icons/lifebuoy.png
  25. BIN
      website_bargain/static/description/assets/icons/manufacturing-black.png
  26. BIN
      website_bargain/static/description/assets/icons/pos-black.png
  27. BIN
      website_bargain/static/description/assets/icons/puzzle.png
  28. BIN
      website_bargain/static/description/assets/icons/restaurant-black.png
  29. BIN
      website_bargain/static/description/assets/icons/service-black.png
  30. BIN
      website_bargain/static/description/assets/icons/trading-black.png
  31. BIN
      website_bargain/static/description/assets/icons/training.png
  32. BIN
      website_bargain/static/description/assets/icons/update.png
  33. BIN
      website_bargain/static/description/assets/icons/user.png
  34. BIN
      website_bargain/static/description/assets/icons/wrench.png
  35. BIN
      website_bargain/static/description/assets/misc/categories.png
  36. BIN
      website_bargain/static/description/assets/misc/check-box.png
  37. BIN
      website_bargain/static/description/assets/misc/compass.png
  38. BIN
      website_bargain/static/description/assets/misc/corporate.png
  39. BIN
      website_bargain/static/description/assets/misc/customer-support.png
  40. BIN
      website_bargain/static/description/assets/misc/cybrosys-logo.png
  41. BIN
      website_bargain/static/description/assets/misc/features.png
  42. BIN
      website_bargain/static/description/assets/misc/logo.png
  43. BIN
      website_bargain/static/description/assets/misc/pictures.png
  44. BIN
      website_bargain/static/description/assets/misc/pie-chart.png
  45. BIN
      website_bargain/static/description/assets/misc/right-arrow.png
  46. BIN
      website_bargain/static/description/assets/misc/star.png
  47. BIN
      website_bargain/static/description/assets/misc/support.png
  48. BIN
      website_bargain/static/description/assets/misc/whatsapp.png
  49. BIN
      website_bargain/static/description/assets/modules/1.png
  50. BIN
      website_bargain/static/description/assets/modules/2.png
  51. BIN
      website_bargain/static/description/assets/modules/3.png
  52. BIN
      website_bargain/static/description/assets/modules/4.png
  53. BIN
      website_bargain/static/description/assets/modules/5.jpg
  54. BIN
      website_bargain/static/description/assets/modules/6.png
  55. BIN
      website_bargain/static/description/assets/screenshots/1.png
  56. BIN
      website_bargain/static/description/assets/screenshots/2.png
  57. BIN
      website_bargain/static/description/assets/screenshots/3.png
  58. BIN
      website_bargain/static/description/assets/screenshots/4.png
  59. BIN
      website_bargain/static/description/assets/screenshots/5.png
  60. BIN
      website_bargain/static/description/assets/screenshots/6.png
  61. BIN
      website_bargain/static/description/assets/screenshots/7.png
  62. BIN
      website_bargain/static/description/assets/screenshots/bidders_backend.png
  63. BIN
      website_bargain/static/description/assets/screenshots/hero.gif
  64. BIN
      website_bargain/static/description/banner.jpg
  65. BIN
      website_bargain/static/description/icon.png
  66. 695
      website_bargain/static/description/index.html
  67. 66
      website_bargain/static/src/css/website_product_bargain.css
  68. 246
      website_bargain/static/src/js/website_bargain.js
  69. 51
      website_bargain/views/bargain_information_views.xml
  70. 52
      website_bargain/views/bargain_subscribers_views.xml
  71. 31
      website_bargain/views/bargain_template_views.xml
  72. 64
      website_bargain/views/bidders_information_templates.xml
  73. 17
      website_bargain/views/product_template_views.xml
  74. 27
      website_bargain/views/website_bargain_menus.xml
  75. 153
      website_bargain/views/website_bargain_views.xml
  76. 277
      website_bargain/views/website_product_views_templates.xml
  77. 41
      website_bargain/views/website_shop_auction_templates.xml

44
website_bargain/README.rst

@ -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: (V16) Mruthul Raj, 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>`__

22
website_bargain/__init__.py

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Mruthul Raj (<https://www.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, models

60
website_bargain/__manifest__.py

@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Mruthul Raj (<https://www.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': '16.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,
}

22
website_bargain/controllers/__init__.py

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Mruthul Raj (<https://www.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

318
website_bargain/controllers/website_bargain.py

@ -0,0 +1,318 @@
"""Auctions main controller """
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Mruthul Raj (<https://www.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_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))
# 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()._onchange_template_id_wrapper()
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,
})
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('/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()._onchange_template_id_wrapper()
compose_msg.sudo().action_send_mail()

25
website_bargain/data/ir_cron_data.xml

@ -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>

104
website_bargain/data/mail_template_data.xml

@ -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>

6
website_bargain/doc/RELEASE_NOTES.md

@ -0,0 +1,6 @@
## Module <website_bargain>
#### 21.11.2023
#### Version 16.0.1.0.0
#### ADD
- Initial Commit for Product Bidding In ECommerce

26
website_bargain/models/__init__.py

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Mruthul Raj (<https://www.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

45
website_bargain/models/bargain_information.py

@ -0,0 +1,45 @@
"""bidders information and functions"""
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Mruthul Raj (<https://www.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")

44
website_bargain/models/bargain_subscribers.py

@ -0,0 +1,44 @@
"""subscribers class and its functions"""
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Mruthul Raj (<https://www.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")

37
website_bargain/models/bargain_template.py

@ -0,0 +1,37 @@
"""website bargains template and its functions"""
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Mruthul Raj (<https://www.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")

32
website_bargain/models/product_template.py

@ -0,0 +1,32 @@
"""Product template inherit """
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Mruthul Raj (<https://www.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"
)

301
website_bargain/models/website_bargain.py

@ -0,0 +1,301 @@
"""Auction main page"""
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Mruthul Raj (<https://www.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"),
('soldout', "Sold Out")], 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_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)

5
website_bargain/security/ir.model.access.csv

@ -0,0 +1,5 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_website_bargain_user,website.bargain.user,model_website_bargain,base.group_user,1,1,1,1
access_website_bargain_template_user,website.bargain.template.user,model_bargain_template,base.group_user,1,1,1,1
access_website_bidder_information_user,bidder.information.user,model_bargain_information,base.group_user,1,1,1,1
access_website_bargain_subscribers_user,bargain.subscribers.user,model_bargain_subscribers,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_website_bargain_user website.bargain.user model_website_bargain base.group_user 1 1 1 1
3 access_website_bargain_template_user website.bargain.template.user model_bargain_template base.group_user 1 1 1 1
4 access_website_bidder_information_user bidder.information.user model_bargain_information base.group_user 1 1 1 1
5 access_website_bargain_subscribers_user bargain.subscribers.user model_bargain_subscribers base.group_user 1 1 1 1

BIN
website_bargain/static/description/assets/icons/check.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
website_bargain/static/description/assets/icons/chevron.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

BIN
website_bargain/static/description/assets/icons/cogs.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
website_bargain/static/description/assets/icons/consultation.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
website_bargain/static/description/assets/icons/ecom-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

BIN
website_bargain/static/description/assets/icons/education-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

BIN
website_bargain/static/description/assets/icons/hotel-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

BIN
website_bargain/static/description/assets/icons/license.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
website_bargain/static/description/assets/icons/lifebuoy.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
website_bargain/static/description/assets/icons/manufacturing-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

BIN
website_bargain/static/description/assets/icons/pos-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 B

BIN
website_bargain/static/description/assets/icons/puzzle.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

BIN
website_bargain/static/description/assets/icons/restaurant-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

BIN
website_bargain/static/description/assets/icons/service-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 839 B

BIN
website_bargain/static/description/assets/icons/trading-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 B

BIN
website_bargain/static/description/assets/icons/training.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 627 B

BIN
website_bargain/static/description/assets/icons/update.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
website_bargain/static/description/assets/icons/user.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 988 B

BIN
website_bargain/static/description/assets/icons/wrench.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
website_bargain/static/description/assets/misc/categories.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
website_bargain/static/description/assets/misc/check-box.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
website_bargain/static/description/assets/misc/compass.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
website_bargain/static/description/assets/misc/corporate.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
website_bargain/static/description/assets/misc/customer-support.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
website_bargain/static/description/assets/misc/cybrosys-logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
website_bargain/static/description/assets/misc/features.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 B

BIN
website_bargain/static/description/assets/misc/logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
website_bargain/static/description/assets/misc/pictures.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
website_bargain/static/description/assets/misc/pie-chart.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
website_bargain/static/description/assets/misc/right-arrow.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 967 B

BIN
website_bargain/static/description/assets/misc/star.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
website_bargain/static/description/assets/misc/support.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
website_bargain/static/description/assets/misc/whatsapp.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
website_bargain/static/description/assets/modules/1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
website_bargain/static/description/assets/modules/2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

BIN
website_bargain/static/description/assets/modules/3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

BIN
website_bargain/static/description/assets/modules/4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
website_bargain/static/description/assets/modules/5.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

BIN
website_bargain/static/description/assets/modules/6.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

BIN
website_bargain/static/description/assets/screenshots/1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

BIN
website_bargain/static/description/assets/screenshots/2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

BIN
website_bargain/static/description/assets/screenshots/3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

BIN
website_bargain/static/description/assets/screenshots/4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 KiB

BIN
website_bargain/static/description/assets/screenshots/5.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 KiB

BIN
website_bargain/static/description/assets/screenshots/6.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

BIN
website_bargain/static/description/assets/screenshots/7.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

BIN
website_bargain/static/description/assets/screenshots/bidders_backend.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

BIN
website_bargain/static/description/assets/screenshots/hero.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

BIN
website_bargain/static/description/banner.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

BIN
website_bargain/static/description/icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

695
website_bargain/static/description/index.html

@ -0,0 +1,695 @@
<div style="background-color: #714B67; height: 810px; width: 100%; padding: 15px; position: relative;">
<!-- TITLE BAR -->
<div class="d-flex align-items-center justify-content-between"
style="border-bottom: 1px solid #875A7B; padding: 15px; display: flex; justify-content: space-between; align-items: center;">
<img src="assets/misc/cybrosys-logo.png" width="42" height="42"
style="width: 42px; height: 42px;"/>
<div>
<div
style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
class="mr-2">
<i class="fa fa-check mr-1"></i>Community
</div>
<div
style="color: #017E84; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
class="mr-2">
<i class="fa fa-check mr-1"></i>Odoo.sh
</div>
<div
style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
class="mr-2">
<i class="fa fa-check mr-1"></i>Enterprise
</div>
</div>
</div>
<!-- END OF TITLE BAR -->
<div class="container">
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12">
<!-- APP HERO -->
<h1 style="color: #FFFFFF; font-weight: bolder; font-size: 50px; text-align: center; margin-top: 50px;">
Product Bidding In ECommerce</h1>
<p style="color:#FFFFFF; padding: 8px 15px; text-align: center; font-size: 24px;">
Bid For Products In Odoo </p>
<!-- END OF APP HERO -->
<img src="assets/screenshots/hero.gif" class="img-responsive"
style="width: 100%; margin-left: auto; margin-right: auto;"/>
</div>
</div>
</div>
</div>
<!-- NAVIGATION SECTION -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px; margin-top: 300px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/compass.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Explore This
Module</h2>
</div>
<div class="row my-4" style="font-family: 'Montserrat', sans-serif;">
<div class="col-sm-12 col-md-6 my-3">
<a href="#overview">
<div class="d-flex justify-content-between align-items-center"
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
<div>
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Overview</span>
<span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">Learn
more about this
module</span>
</div>
<img src="assets/misc/right-arrow.png" width="36" height="36"/>
</div>
</a>
</div>
<div class="col-sm-12 col-md-6 my-3">
<a href="#features">
<div class="d-flex justify-content-between align-items-center"
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
<div>
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Features</span>
<span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">View
features of this
module</span>
</div>
<img src="assets/misc/right-arrow.png" width="36" height="36"/>
</div>
</a>
</div>
<div class="col-sm-12 col-md-6 my-3">
<a href="#screenshots">
<div class="d-flex justify-content-between align-items-center"
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
<div>
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Screenshots</span>
<span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">View
screenshots for this
module</span>
</div>
<img src="assets/misc/right-arrow.png" width="36" height="36"/>
</div>
</a>
</div>
</div>
<!-- END OF NAVIGATION SECTION -->
<!-- OVERVIEW SECTION -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;"
id="overview">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/pie-chart.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Overview
</h2>
</div>
<div class="row"
style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;">
<div class="col-sm-12 py-4">
This module provides a bidding system where customers can place their
bids on
products, and the highest bidder wins the auction. This module
integrates seamlessly with the website sale module of Odoo, and it is
highly configurable to meet the specific needs of each business.
Additionally, it provides several features such as starting and ending
dates for auctions, buy now option, and real-time updates for bids.
</div>
</div>
<!-- END OF OVERVIEW SECTION -->
<!-- FEATURES SECTION -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;"
id="features">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/features.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Features
</h2>
</div>
<div class="row"
style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;">
<div class="col-sm-12 col-md-6">
<div class="d-flex align-items-center"
style="margin-top: 40px; margin-bottom: 40px">
<img src="assets/misc/check-box.png" class="mr-2"/>
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Timer On Product Until End Of Auction.</span>
</div>
<div class="d-flex align-items-center"
style="margin-top: 30px; margin-bottom: 30px">
<img src="assets/misc/check-box.png" class="mr-2"/>
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Subscription Available.</span>
</div>
<div class="d-flex align-items-center"
style="margin-top: 30px; margin-bottom: 30px">
<img src="assets/misc/check-box.png" class="mr-2"/>
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Different Email Notifications.</span>
</div>
<div class="d-flex align-items-center"
style="margin-top: 30px; margin-bottom: 30px">
<img src="assets/misc/check-box.png" class="mr-2"/>
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Option To See Bidders.</span>
</div>
</div>
<div class="d-flex align-items-center"
style="margin-top: 30px; margin-bottom: 30px">
<img src="assets/misc/check-box.png" class="mr-2"/>
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Option For Buy Now.</span>
</div>
</div>
<div class="col-sm-12 col-md-6">
<div class="d-flex align-items-center"
style="margin-top: 30px; margin-bottom: 30px">
<img src="assets/misc/check-box.png" class="mr-2"/>
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Available in Odoo 16.0</span>
</div>
</div>
<!-- END OF FEATURES SECTION -->
<!-- SCREENSHOTS SECTION -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;"
id="screenshots">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/pictures.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Screenshots
</h2>
</div>
<div class="row">
<div class="col-sm-12">
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Auction Home Page
</h3>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
Website ->
Auction
->Auctions
Here created auction can be seen .</p>
<img src="assets/screenshots/1.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
Create a Auction and click CONFIRM.</p>
<img src="assets/screenshots/2.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Run Auction
</h3>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
Auction will automatically start at the Start Date Time.If you
want to run manually just click on RUN AUCTION Button</p>
<img src="assets/screenshots/3.png"
class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Product inProduct List
</h3>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
Customes can see AUCTION ON on that product.</p>
<img src="assets/screenshots/4.png"
class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Product in Website
</h3>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
This will be the product view in website.</p>
<img src="assets/screenshots/5.png"
class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Subscribers </h3>
<img src="assets/screenshots/6.png"
class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Bidders </h3>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
This will be the bidders view in website.</p>
<img src="assets/screenshots/7.png"
class="img-thumbnail">
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
View in backend.</p>
<img src="assets/screenshots/bidders_backend.png"
class="img-thumbnail">
</div>
</div>
</div>
<!-- END OF SCREENSHOTS SECTION -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/categories.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Related
Products
</h2>
</div>
<div class="row">
<div class="col-sm-12">
<div id="demo1" class="row carousel slide" data-ride="carousel">
<!-- The slideshow -->
<div class="carousel-inner" style="padding: 30px;">
<div class="carousel-item" style="min-height: 198.656px;">
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/16.0/odoo_website_helpdesk/"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-radius: 0px;"
src="assets/modules/1.png">
</div>
</a>
</div>
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/16.0/customer_geolocation/#"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-radius: 0px;"
src="assets/modules/2.png">
</div>
</a>
</div>
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/16.0/website_product_attachments/"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-radius: 0px;"
src="assets/modules/3.png">
</div>
</a>
</div>
</div>
<div class="carousel-item active"
style="min-height: 198.656px;">
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/16.0/animated_snippet/#"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-radius: 0px;"
src="assets/modules/4.png">
</div>
</a>
</div>
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/16.0/education_student_portal/"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-radius: 0px;"
src="assets/modules/5.jpg">
</div>
</a>
</div>
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/16.0/website_pdf_preview_snippet/"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-radius: 0px;"
src="assets/modules/6.png">
</div>
</a>
</div>
</div>
</div>
<!-- Left and right controls -->
<a class="carousel-control-prev" href="#demo1" 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="#demo1"
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>
</div>
<!-- END OF RELATED PRODUCTS -->
<!-- OUR SERVICES -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/star.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Our Services
</h2>
</div>
<div class="container my-5">
<div class="row">
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #1dd1a1 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/cogs.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Customization</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #ff6b6b !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/wrench.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Implementation</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #6462CD !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/lifebuoy.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Support</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #ffa801 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/user.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Hire
Odoo
Developer</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #54a0ff !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/puzzle.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Integration</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #6d7680 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/update.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Migration</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #786fa6 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/consultation.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Consultancy</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #f8a5c2 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/training.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Implementation</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #e6be26 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/license.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Licensing Consultancy</h6>
</div>
</div>
</div>
<!-- END OF OUR SERVICES -->
<!-- OUR INDUSTRIES -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/corporate.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Our
Industries
</h2>
</div>
<div class="container my-5">
<div class="row">
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/trading-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Trading
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Easily procure
and
sell your products</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/pos-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
POS
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Easy
configuration
and convivial experience</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/education-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Education
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
A platform for
educational management</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/manufacturing-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Manufacturing
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Plan, track and
schedule your operations</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/ecom-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
E-commerce &amp; Website
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Mobile
friendly,
awe-inspiring product pages</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/service-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Service Management
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Keep track of
services and invoice</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/restaurant-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Restaurant
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Run your bar or
restaurant methodically</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/hotel-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Hotel Management
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
An
all-inclusive
hotel management application</p>
</div>
</div>
</div>
</div>
<!-- END OF OUR INDUSTRIES -->
<!-- SUPPORT -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/customer-support.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Support
</h2>
</div>
<div class="container mt-5">
<div class="row">
<div class="col-sm-12 col-md-6">
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;">
<div class="mr-4 d-flex justify-content-center align-items-center"
style="background-color: #714B67; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;">
<img src="assets/misc/support.png" height="48" width="48"
style="width: 42px; height: 42px;"/>
</div>
<div>
<h4>Need Help?</h4>
<p style="line-height: 100%;">Got questions or need help?
Get in touch.</p>
<a href="mailto:odoo@cybrosys.com">
<p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;">
odoo@cybrosys.com</p>
</a>
</div>
</div>
</div>
<div class="col-sm-12 col-md-6">
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;">
<div class="mr-4 d-flex justify-content-center align-items-center"
style="background-color: #2AC44D; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;">
<img src="assets/misc/whatsapp.png" height="52" width="52"
style="width: 52px; height: 52px;"/>
</div>
<div>
<h4>WhatsApp</h4>
<p style="line-height: 100%;">Say hi to us on WhatsApp!</p>
<a href="https://api.whatsapp.com/send?phone=918606827707">
<p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;">
+91 86068
27707</p>
</a>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12 my-5 d-flex justify-content-center align-items-center">
<img src="assets/misc/logo.png" width="144" height="31"
style="width:144px; height: 31px; margin-top: 40px;"/>
</div>
</div>
</div>
<!-- END OF SUPPORT -->

66
website_bargain/static/src/css/website_product_bargain.css

@ -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;
}

246
website_bargain/static/src/js/website_bargain.js

@ -0,0 +1,246 @@
/** @odoo-module **/
import { WebsiteSale } from 'website_sale.website_sale'
var rpc = require('web.rpc');
var ajax = require('web.ajax');
/**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]
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()
ajax.jsonRpc('/auction/timer', 'call', {
'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'])) {
ajax.jsonRpc('/auction/close', 'call', {
'product_id': product_id,
'auction_id': auction_id
}).then(() => {
ajax.jsonRpc('/shop/sale/order', 'call', {
'product_product_id': product_product_id,
'product_id': product_id,
'auction_id': auction_id
})
})
window.location.href = '/shop'
}
} else {
ajax.jsonRpc('/auction/close', 'call', {
'product_id': product_id,
'auction_id': auction_id
}).then(() => {
ajax.jsonRpc('/shop/sale/order', 'call', {
'product_product_id': product_product_id,
'product_id': product_id,
'auction_id': auction_id
})
})
window.location.href = '/shop'
}
} else {
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 (document.getElementById('timer')) {
document.getElementById('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() {
setTimeout(function() {
document.getElementById('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 = document.getElementById('subscribe_bid');
var messages = document.getElementById('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'
ajax.jsonRpc('/subscribe/bid', 'call', {
'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'
ajax.jsonRpc('/subscribe/bid', 'call', {
'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 {
ajax.jsonRpc('/place_bid', 'call', {
'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();
ajax.jsonRpc('/buy/now', 'call', {
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) {})
ajax.jsonRpc('/auction/close', 'call', {
'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')
window.location.href = '/shop'
},
})

51
website_bargain/views/bargain_information_views.xml

@ -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>

52
website_bargain/views/bargain_subscribers_views.xml

@ -0,0 +1,52 @@
<?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"/>
</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>

31
website_bargain/views/bargain_template_views.xml

@ -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>

64
website_bargain/views/bidders_information_templates.xml

@ -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>

17
website_bargain/views/product_template_views.xml

@ -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>

27
website_bargain/views/website_bargain_menus.xml

@ -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>

153
website_bargain/views/website_bargain_views.xml

@ -0,0 +1,153 @@
<?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"
attrs="{'invisible':['|',('state','=',True),('state','not in',['draft'])]}"/>
<button name="action_reset_to_draft" type="object"
string="Reset to draft" class="oe_highlight"
attrs="{'invisible' :['|',('state','=',True),('state','in',['draft','finished','closed'])]}"/>
<button name="action_run_auction" type="object"
string="Run Auction" class="oe_highlight"
attrs="{'invisible':['|',('state','=',True),('state','not in',['confirmed'])]}"/>
<button name="action_complete" type="object"
string="Completed" class="oe_highlight"
attrs="{'invisible':['|',('state','=',True),('state','not in',['running','extended'])]}"/>
<button name="action_close" type="object" string="Closed"
class="oe_highlight"
attrs="{'invisible':['|',('state','=',True),('state','not in',['running','extended','finished'])]}"/>
<field name="state" widget="statusbar"/>
</header>
<sheet>
<group class="mt-4">
<field name="website_id"
attrs="{'readonly':[('state','!=','draft')]}"/>
<field name="auction_manager_id"
attrs="{'readonly':[('state','!=','draft')]}"/>
<field name="template_id"
attrs="{'readonly':[('state','!=','draft')]}"/>
<field name="product_id"
attrs="{'readonly':[('state','!=','draft')]}"/>
<field name="name"
attrs="{'readonly':[('state','!=','draft')]}"/>
</group>
<group>
<group name="price_configuration"
string="Price Configuration">
<field name="currency_id" position="attributes"
attrs="{'readonly':[('state','!=','draft')]}"/>
<field name="initial_price" widget="monetary"
attrs="{'readonly':[('state','!=','draft')]}"
force_save="1"/>
<field name="is_buy_now"
attrs="{'readonly':[('state','!=','draft')]}"/>
<field name="price_buy_now" widget="monetary"
force_save="1"
attrs="{'invisible':[('is_buy_now','=',False)]}"/>
</group>
<group name="time_configuration"
string="TIME CONFIGURATION">
<field name="start_time"
attrs="{'readonly':[('state','!=','draft')]}"/>
<field name="end_time"
attrs="{'readonly':[('state','!=','draft')]}"/>
<field name="extend_time"
attrs="{'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"
attrs="{'invisible':[('is_activate','=',False)]}"/>
<div class="o_checkbox_optional_field"
attrs="{'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"
attrs="{'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"/>
</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>

277
website_bargain/views/website_product_views_templates.xml

@ -0,0 +1,277 @@
<?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">
<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()"/> <!-- set base URL -->
<h1 itemprop="name" t-field="product.name">Product Name
</h1> <!-- display product name -->
<span itemprop="url" style="display:none;"
t-esc="base_url + product.website_url"/> <!-- set URL for product -->
<span itemprop="image" style="display:none;"
t-esc="base_url + website.image_url(product, 'image_1920')"/> <!-- set image for product -->
<t t-if="is_view_active('website_sale.product_comment')"> <!-- check if product comments are active -->
<a href="#o_product_page_reviews"
class="o_product_page_reviews_link text-decoration-none"> <!-- link to product reviews section -->
<t t-call="portal_rating.rating_widget_stars_static"> <!-- display product rating -->
<t t-set="rating_avg"
t-value="product.rating_avg"/> <!-- set product rating average -->
<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"/> <!-- set 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."/> <!-- display product description -->
<form t-if="product._is_add_to_cart_possible()"
action="/shop/cart/update"
method="POST"> <!-- add to a cart form -->
<input type="hidden" name="csrf_token"
t-att-value="request.csrf_token()"/> <!-- add CSRF token for security -->
<div class="js_product js_main_product mb-3">
<div>
<t t-call="website_sale.product_price"/> <!-- display 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'/> <!-- display product 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]"/>
<input t-if="product.product_tag_ids.ids"
type="hidden"
class="product_tag_id"
name="product_tag_id"
t-att-value="product.product_tag_ids.ids[0]"/>
<t t-if="combination"
t-call="sale.variants"> <!-- display product variants -->
<t t-set="ul_class"
t-valuef="flex-column"/>
<t t-set="parent_combination"
t-value="None"/>
</t>
<t t-else="">
<ul class="d-none js_add_cart_variants mb-0"
t-att-data-attribute_exclusions="{'exclusions: []'}"/>
</t>
</t>
<p t-if="True"
class="css_not_available_msg alert alert-warning">
This
combination does not exist.
</p>
<!-- Define a div element with an id of "o_wsale_cta_wrapper" and some classes -->
<div id="o_wsale_cta_wrapper"
class="d-flex flex-wrap align-items-center">
<!-- Define some variables in the template -->
<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"/>
<!-- Define a div element with an id of "add_to_cart_wrap" and some classes -->
<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">
<!-- Define an anchor element with an id of "add_to_cart" and some classes -->
<a role="button" id="add_to_cart"
t-attf-class="btn btn-primary js_check_product a-submit flex-grow-1 #{'btn-lg' if ctaSizeBig else ''}"
href="#">
<!-- Define an icon element with the FontAwesome class "fa fa-shopping-cart" -->
<i class="fa fa-shopping-cart me-2"/>
<!-- Define a span element with bold text -->
<span style="font-weight: bold">ADD TO
CART
</span>
</a>
</div>
<!-- Define a div element with an id of "product_option_block" and some classes -->
<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>
</div>
</form>
<!-- If the product is not active, show a warning message -->
<p t-elif="not product.active" class="alert alert-warning">
This product is no longer available.
</p>
<!-- If the product has no valid combination, show a warning message -->
<p t-else="" class="alert alert-warning">
This product has no valid combination.
</p>
<!-- Display the single value attributes of the product -->
<div id="product_attributes_simple">
<!-- Prepare single value attributes for display -->
<t t-set="single_value_attributes"
t-value="product.valid_product_template_attribute_line_ids._prepare_single_value_for_display()"/>
<!-- Display the attributes in a table format -->
<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"/>:
<!-- Display the attribute values -->
<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>
<!-- Display the product terms and share section -->
<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>

41
website_bargain/views/website_shop_auction_templates.xml

@ -0,0 +1,41 @@
<?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>
Loading…
Cancel
Save