@ -0,0 +1,46 @@ |
|||
.. image:: https://img.shields.io/badge/license-LGPL--3-green.svg |
|||
:target: https://www.gnu.org/licenses/lgpl-3.0-standalone.html |
|||
:alt: License: LGPL-3 |
|||
|
|||
Product Bidding In ECommerce |
|||
============================ |
|||
This module helps you to add auction in website sale. |
|||
|
|||
Configuration |
|||
============= |
|||
* No additional configurations needed |
|||
|
|||
Company |
|||
------- |
|||
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ |
|||
|
|||
License |
|||
------- |
|||
Lesser General Public License, Version 3 (LGPL v3). |
|||
(http://www.gnu.org/licenses/lgpl-3.0-standalone.html) |
|||
|
|||
Credits |
|||
------- |
|||
* Developers: (V17) Anfas Faisal K, |
|||
(V15) Safa Faheem PE |
|||
Contact:odoo@cybrosys.com |
|||
|
|||
Contacts |
|||
-------- |
|||
* Mail Contact : odoo@cybrosys.com |
|||
* Website : https://cybrosys.com |
|||
|
|||
Bug Tracker |
|||
----------- |
|||
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. |
|||
|
|||
Maintainer |
|||
========== |
|||
.. image:: https://cybrosys.com/images/logo.png |
|||
:target: https://cybrosys.com |
|||
This module is maintained by Cybrosys Technologies. |
|||
For support and more information, please visit `Our Website <https://cybrosys.com/>`__ |
|||
|
|||
Further information |
|||
=================== |
|||
HTML Description: `<static/description/index.html>`__ |
@ -0,0 +1,23 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
from . import controllers |
|||
from . import models |
@ -0,0 +1,60 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<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': '15.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.png'], |
|||
'license': 'LGPL-3', |
|||
'installable': True, |
|||
'auto-install': False, |
|||
'application': False, |
|||
} |
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Anfas Faisal K (odoo@cybrosys.com) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
from . import website_bargain |
@ -0,0 +1,352 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU 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([]) |
|||
values.update({ |
|||
'auction': auction, |
|||
'website': current_website |
|||
}) |
|||
return values |
|||
|
|||
@http.route('/auction/timer', type='json', auth='user', csrf=False) |
|||
def auction_timer(self, auction_id): |
|||
"""Summary: |
|||
Function to pass timer details from auction like start |
|||
time,end time,extended time |
|||
Args: |
|||
auction_id:used to get auction id from website |
|||
Return: |
|||
Values which include start_time,end time,extended |
|||
time and state id""" |
|||
auction = request.env['website.bargain'].sudo().browse(int(auction_id)) |
|||
values = { |
|||
'start_time': auction.start_time, |
|||
'end_time': fields.Datetime.context_timestamp(auction, |
|||
auction.end_time), |
|||
'state': auction.state, |
|||
} |
|||
if auction.extend_time: |
|||
values['extend_time'] = fields.Datetime.context_timestamp(auction, |
|||
auction.extend_time) |
|||
return values |
|||
|
|||
@http.route('/auction/close', type='json', auth='user', csrf=False) |
|||
def auction_close(self, auction_id): |
|||
"""Summary: |
|||
Function to close auction when a customer buys |
|||
a product instantly or the auction is ended |
|||
Args: |
|||
auction_id: used to get auction id from website |
|||
Return: |
|||
a string auction ended to website""" |
|||
auction = request.env['website.bargain'].sudo().browse(int(auction_id)) |
|||
auction.product_id.is_auction = False |
|||
auction.product_id.is_published = False |
|||
auction.write({'state': 'finished'}) |
|||
return "auction ended" |
|||
|
|||
@http.route('/place_bid', type='json', auth='user', csrf=False) |
|||
def place_bid(self, auction_id, **post): |
|||
"""Summary: |
|||
When place bid button is clicked it will trigger this function |
|||
and will add bidders details to backend and will send |
|||
notification to the subscribers if its enabled |
|||
Args: |
|||
auction_id:used to get auction id from website |
|||
post:used to get bid amount from frontend |
|||
Return: |
|||
A message bid placed and suction details""" |
|||
bid_amount = post.get('bid_amount') |
|||
auction = request.env['website.bargain'].sudo().browse(int(auction_id)) |
|||
bidder_total = auction.bargain_information_ids.search_count( |
|||
[('bidder_id', '=', request.env.user.partner_id.id), |
|||
('bid_offer', '=', bid_amount)]) |
|||
if bidder_total >= 1: |
|||
return False |
|||
else: |
|||
auction.bargain_information_ids.sudo().create({ |
|||
'bidder_id': request.env.user.partner_id.id, |
|||
'auction_id': auction.id, |
|||
'bid_offer': bid_amount, |
|||
'status': 'Bid Placed' |
|||
}) |
|||
if auction.is_subscriber_start_notification and not auction.is_send_mail: |
|||
data = 'Bidding has started for ' + auction.name + '. Please check our website for more details.' |
|||
subscribers = "" |
|||
for record in auction.bargain_subscribers_ids: |
|||
subscribers += record.subscriber_id.email + ',' |
|||
email_values = {'email_from': auction.auction_manager_id.email, |
|||
'subject': 'Bidding Started for ' + auction.name, |
|||
'email_to': subscribers, 'body_html': data} |
|||
request.env['mail.mail'].sudo().create(email_values).send() |
|||
auction.is_send_mail = True |
|||
auction.write({'is_send_mail': True}) |
|||
|
|||
if auction.is_new_bid_notification: |
|||
data = 'A new bid has been placed with amount ' + str( |
|||
bid_amount) + ', on ' \ |
|||
+ auction.name + ', by ' + request.env.user.partner_id.name \ |
|||
+ '. Please check the website.' |
|||
subscribers = " " |
|||
for record in auction.bargain_subscribers_ids: |
|||
subscribers += record.subscriber_id.email + ',' |
|||
email_values = {'email_from': auction.auction_manager_id.email, |
|||
'subject': 'New Bid Placed on ' + auction.name, |
|||
'email_to': subscribers, 'body_html': data} |
|||
request.env['mail.mail'].sudo().create(email_values).send() |
|||
values = ({ |
|||
'bid_placed': 'Bid Placed', |
|||
'auction': auction |
|||
}) |
|||
|
|||
return values |
|||
|
|||
@http.route('/bidders/<model("product.template"):product_id>', type='http', |
|||
auth='user', csrf=False, website=True) |
|||
def bidders(self, product_id): |
|||
""" |
|||
This method is used to fetch the details of the bidders participating in |
|||
an auction and render them on the website. |
|||
Args: |
|||
product_id: A product template model object. |
|||
Returns: |
|||
A rendered HTML template with information about the bidders in the |
|||
auction.""" |
|||
auction = request.env['website.bargain'].sudo().search( |
|||
[('product_id', '=', product_id.id), ('state', '=', 'running')]) |
|||
bidders_information = request.env['bargain.information'].sudo().search( |
|||
[('auction_id', '=', auction.id)], |
|||
order='bid_offer desc') |
|||
values = ({ |
|||
'bidders_information': bidders_information, |
|||
'product_id': product_id, |
|||
}) |
|||
return request.render('website_bargain.bidders_information', values) |
|||
|
|||
@http.route('/bid/cancel/<model("bargain.information"):bidders>', |
|||
type='http', auth='user', csrf='false') |
|||
def bid_cancel(self, bidders): |
|||
"""This function is for cancel the bid |
|||
Args: |
|||
bidders:Bidders name will be getting here |
|||
Returns:It returns previous page""" |
|||
bidders.status = 'cancelled' |
|||
previous_web_url = request.httprequest.headers.get('referer') |
|||
return request.redirect(previous_web_url) |
|||
|
|||
@http.route('/shop/sale/order', type='json', auth='public', website=True, |
|||
csrf=False) |
|||
def winner_sale_order(self, auction_id, **post): |
|||
""" |
|||
This route creates a draft sale order for the winner of an auction |
|||
and sends notifications for winning and losing. |
|||
Args: |
|||
auction_id: the ID of the auction obtained from the frontend |
|||
post: used to get data of product from frontend |
|||
Returns: |
|||
True""" |
|||
# Get the ID of the product from the post data |
|||
product_product_id = post.get('product_product_id') |
|||
# Find the auction with the given ID |
|||
auction = request.env['website.bargain'].sudo().browse(int(auction_id)) |
|||
auction.write({'state': 'finished'}) |
|||
if auction.is_bid_end_notification: |
|||
data = 'Bidding has ended for ' + auction.name + '. Thank you for participating.' |
|||
subscribers = "" |
|||
for record in auction.bargain_subscribers_ids: |
|||
subscribers += record.subscriber_id.email + ',' |
|||
email_values = {'email_from': auction.auction_manager_id.email, |
|||
'subject': 'Bidding Ended for ' + auction.name, |
|||
'email_to': subscribers, 'body_html': data} |
|||
request.env['mail.mail'].sudo().create(email_values).send() |
|||
# Find the highest bidder for the auction |
|||
bid_record = auction.bargain_information_ids.filtered( |
|||
lambda r: r.status == 'Bid Placed').sorted( |
|||
key=lambda r: r.bid_offer)[-1] |
|||
# Create a draft sale order for the winner |
|||
sale_order = request.env['sale.order'].sudo().create({ |
|||
'partner_id': bid_record.bidder_id.id, |
|||
'state': 'draft', |
|||
}) |
|||
# Add the product to the sale order and set the price to the bid offer |
|||
sale_order.sudo().write({ |
|||
'order_line': [(0, 0, { |
|||
'product_id': int(product_product_id), |
|||
'product_uom_qty': 1, |
|||
'price_unit': bid_record.bid_offer, |
|||
'name': 'auction won', |
|||
})] |
|||
}) |
|||
mail_compose_message = request.env['mail.compose.message'] |
|||
so_mcm_vals = sale_order.sudo().action_quotation_send().get('context', |
|||
{}) |
|||
compose_msg = mail_compose_message.sudo().with_context( |
|||
so_mcm_vals).create({}) |
|||
compose_msg.sudo().action_send_mail() |
|||
# Send a notification email to the winner and/or losers, if enabled |
|||
if auction.is_winner_notification: |
|||
data = "You have won in " + auction.name + " Kindly pay now and" \ |
|||
" collect the product " \ |
|||
"from our website" |
|||
email_values = { |
|||
'email_from': auction.auction_manager_id.email, |
|||
'subject': 'Won ' + auction.name, |
|||
'email_to': bid_record.bidder_id.email, |
|||
'body_html': data |
|||
} |
|||
request.env['mail.mail'].sudo().create(email_values).send() |
|||
if auction.is_loser_notification: |
|||
data = "You have lost in " + auction.name + "Better luck next time"\ |
|||
" thank you for your " \ |
|||
"effort and time" |
|||
email_to = '' |
|||
for record in auction.bargain_information_ids: |
|||
if record.bidder_id.id != bid_record.bidder_id.id: |
|||
email_to += record.bidder_id.email + ',' |
|||
email_values = { |
|||
'email_from': auction.auction_manager_id.email, |
|||
'subject': 'Lost ' + auction.name, |
|||
'email_to': email_to, |
|||
'body_html': data |
|||
} |
|||
request.env['mail.mail'].sudo().create(email_values).send() |
|||
return True |
|||
|
|||
@http.route('/subscribe/bid', type='json', auth='user', csrf=False) |
|||
def subscribe(self, auction_id, **post): |
|||
""" |
|||
Endpoint to manage subscription to an auction |
|||
auction_id: integer ID of the auction being subscribed to/unsubscribed |
|||
text: string indicating whether the user is subscribing or |
|||
unsubscribing ('subscribe' or 'unsubscribe') |
|||
return: string message indicating success or failure of |
|||
subscription/unsubscription action |
|||
""" |
|||
text = post.get('text') |
|||
auction = request.env['website.bargain'].sudo().browse(int(auction_id)) |
|||
if text == 'subscribe': |
|||
if request.env.user.partner_id in \ |
|||
auction.bargain_subscribers_ids.subscriber_id: |
|||
return 'You have already subscribed' |
|||
auction.bargain_subscribers_ids.sudo().create({ |
|||
'subscriber_id': request.env.user.partner_id.id, |
|||
'auction_id': auction.id, |
|||
'is_subscribed': True |
|||
}) |
|||
return 'You have been successfully subscribed to this auction' |
|||
elif text == 'unsubscribe': |
|||
auction.bargain_subscribers_ids.sudo().search( |
|||
[('subscriber_id', '=', request.env.user.partner_id.id), |
|||
('auction_id', '=', auction.id)]).unlink() |
|||
return 'Unsubscribed successfully' |
|||
|
|||
@http.route('/subscribe/status', type='json', auth='user', csrf=False) |
|||
def subscribe_status(self, auction_id, **post): |
|||
""" |
|||
Controller method to handle subscription to an auction. |
|||
""" |
|||
auction = request.env['website.bargain'].sudo().browse(int(auction_id)) |
|||
is_subscribed = False |
|||
for subscriber in auction.bargain_subscribers_ids: |
|||
if subscriber.subscriber_id == request.env.user.partner_id: |
|||
is_subscribed = subscriber.is_subscribed |
|||
break |
|||
|
|||
return is_subscribed |
|||
|
|||
@http.route('/buy/now', type='json', auth='public', website=True, |
|||
csrf=False) |
|||
def buy_now(self, auction_id, product_id): |
|||
""" |
|||
Args: |
|||
auction_id: the ID of the auction obtained from the frontend |
|||
product_id: the ID of the product used to get data from the frontend |
|||
""" |
|||
# Find the auction with the given ID |
|||
auction = request.env['website.bargain'].sudo().browse(int(auction_id)) |
|||
# Create a draft sale order for the winner |
|||
sale_order = request.env['sale.order'].sudo().create({ |
|||
'partner_id': request.env.user.partner_id.id, |
|||
'state': 'draft', |
|||
}) |
|||
sale_order.sudo().write({ |
|||
'order_line': [(0, 0, { |
|||
'product_id': int(product_id), |
|||
'product_uom_qty': 1, |
|||
'name': '(auction won)' + auction.name, |
|||
'price_unit': auction.price_buy_now, |
|||
})] |
|||
}) |
|||
# Send a notification email to the winner |
|||
mail_compose_message = request.env['mail.compose.message'] |
|||
so_mcm_vals = sale_order.sudo().action_quotation_send().get('context', |
|||
{}) |
|||
compose_msg = mail_compose_message.sudo().with_context( |
|||
so_mcm_vals).create({}) |
|||
compose_msg.sudo().action_send_mail() |
@ -0,0 +1,25 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<!-- Cron action for automatic email notifications --> |
|||
<record id="ir_cron_auto_send_email_admin" model="ir.cron"> |
|||
<field name="name">Auction: Email Notification</field> |
|||
<field name="model_id" ref="model_website_bargain"/> |
|||
<field name="state">code</field> |
|||
<field name="code">model.send_email_notification()</field> |
|||
<field name="interval_number">1</field> |
|||
<field name="interval_type">minutes</field> |
|||
<field name="numbercall">-1</field> |
|||
<field name="doall" eval="False"/> |
|||
</record> |
|||
<!-- Cron action for auction auto start --> |
|||
<record id="ir_cron_auto_start_auction" model="ir.cron"> |
|||
<field name="name">Auction: Auto Start</field> |
|||
<field name="model_id" ref="model_website_bargain"/> |
|||
<field name="state">code</field> |
|||
<field name="code">model.auction_auto_start()</field> |
|||
<field name="interval_number">1</field> |
|||
<field name="interval_type">minutes</field> |
|||
<field name="numbercall">-1</field> |
|||
<field name="doall" eval="False"/> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,104 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<!-- Email template for admin notification --> |
|||
<record id="admin_email_template" model="mail.template"> |
|||
<field name="name">Auction: Admin Notification Email</field> |
|||
<field name="model_id" ref="website_bargain.model_website_bargain"/> |
|||
<field name="email_from">{{ |
|||
(object.auction_manager_id.partner_id.email) }} |
|||
</field> |
|||
<field name="email_to">{{ |
|||
(object.auction_manager_id.partner_id.email) }} |
|||
</field> |
|||
<field name="subject">{{ (object.name) }} end time is near</field> |
|||
<field name="body_html" type="html"> |
|||
<div style="margin: 0px; padding: 0px;"> |
|||
<p style="margin: 0px; padding: 0px; font-size: 13px"> |
|||
Dear |
|||
<t t-if="object.auction_manager_id.name"> |
|||
<t t-out="object.auction_manager_id.name"/> |
|||
</t> |
|||
<br/> |
|||
<br/> |
|||
This mail is a reminder that |
|||
<t t-if="object.name"> |
|||
<span style="font-weight:bold;" t-out="object.name"> |
|||
Auction |
|||
</span> |
|||
</t> |
|||
will end at |
|||
<t t-if="object.end_time"> |
|||
<span style="font-weight:bold;" |
|||
t-out="object.end_time">End Time |
|||
</span> |
|||
</t> |
|||
.So if its need to be |
|||
extended kindly reminding you to extend it fast. |
|||
</p> |
|||
</div> |
|||
</field> |
|||
</record> |
|||
<!-- Email template for auction start notification --> |
|||
<record id="email_template_auction_start" model="mail.template"> |
|||
<field name="name">Auction: Auction Start Notification Email</field> |
|||
<field name="model_id" ref="website_bargain.model_website_bargain"/> |
|||
<field name="email_from">{{ |
|||
(object.auction_manager_id.partner_id.email) }} |
|||
</field> |
|||
<field name="subject">{{ (object.name) }} has started</field> |
|||
<field name="body_html" type="html"> |
|||
<div style="margin: 0px; padding: 0px;"> |
|||
<p style="margin: 0px; padding: 0px; font-size: 13px"> |
|||
Dear Sir/Madam |
|||
<br/> |
|||
<br/> |
|||
This mail is a reminder that |
|||
<t t-if="object.name"> |
|||
<span style="font-weight:bold;" t-out="object.name"> |
|||
Auction |
|||
</span> |
|||
</t> |
|||
has started |
|||
<t t-if="object.start_time"> |
|||
<span style="font-weight:bold;" |
|||
t-field="object.start_time">Start Time Time |
|||
</span> |
|||
</t> |
|||
.Place your bids and win the auction. |
|||
</p> |
|||
</div> |
|||
</field> |
|||
</record> |
|||
<!-- Email template for auction extended notification --> |
|||
<record id="email_template_auction_extended" model="mail.template"> |
|||
<field name="name">Auction: Auction Extend Notification Email |
|||
</field> |
|||
<field name="model_id" ref="website_bargain.model_website_bargain"/> |
|||
<field name="email_from">{{ |
|||
(object.auction_manager_id.partner_id.email) }} |
|||
</field> |
|||
<field name="subject">{{ (object.name) }} has extended</field> |
|||
<field name="body_html" type="html"> |
|||
<div style="margin: 0px; padding: 0px;"> |
|||
<p style="margin: 0px; padding: 0px; font-size: 13px"> |
|||
Dear Sir/Madam |
|||
<br/> |
|||
<br/> |
|||
This mail is a reminder that |
|||
<t t-if="object.name"> |
|||
<span style="font-weight:bold;" t-out="object.name"> |
|||
Auction |
|||
</span> |
|||
</t> |
|||
has extended |
|||
<t t-if="object.extend_time"> |
|||
<span style="font-weight:bold;" |
|||
t-out="object.extend_time">Extended Time Time |
|||
</span> |
|||
</t> |
|||
.Place your bids and win the auction. |
|||
</p> |
|||
</div> |
|||
</field> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,7 @@ |
|||
## Module <website_bargain> |
|||
|
|||
#### 19.09.2024 |
|||
#### Version 15.0.1.0.0 |
|||
#### ADD |
|||
|
|||
- Initial Commit for Product Bidding In ECommerce |
@ -0,0 +1,26 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<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 |
@ -0,0 +1,44 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
from odoo import fields, models |
|||
|
|||
|
|||
class BargainInformation(models.Model): |
|||
"""Class for adding bidder details to the database""" |
|||
_name = 'bargain.information' |
|||
_rec_name = 'auction_id' |
|||
_description = "Bidder Details" |
|||
_inherit = ['mail.thread', 'mail.activity.mixin'] |
|||
|
|||
bidder_id = fields.Many2one('res.partner', string='Bidder', required=True, |
|||
help="Bidders details") |
|||
auction_id = fields.Many2one('website.bargain', string='Auction', |
|||
required=True, help="Auction Details") |
|||
currency_id = fields.Many2one(related="auction_id.currency_id", |
|||
help="Currency Details") |
|||
bid_offer = fields.Monetary(string="Bid Offer", |
|||
currency_field='currency_id', |
|||
help="Offered amount") |
|||
status = fields.Char(string="Status", readonly=True, |
|||
help="Current Status of bid") |
|||
product_id = fields.Many2one(related='auction_id.product_id', |
|||
string='Product', help="Product details") |
@ -0,0 +1,45 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<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") |
|||
is_subscribed = fields.Boolean(string="Is Subscribed", |
|||
help="Check if Subscribed or not") |
@ -0,0 +1,36 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<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") |
@ -0,0 +1,31 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
from odoo import fields, models |
|||
|
|||
|
|||
class ProductTemplateInherit(models.Model): |
|||
"""Model to add a new boolean field to product template""" |
|||
_inherit = 'product.template' |
|||
|
|||
is_auction = fields.Boolean(string='Auction On', readonly=True, |
|||
help="If auction is on this field will be true" |
|||
) |
@ -0,0 +1,301 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<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=lambda self: fields.datetime.now(), |
|||
help="Auction start time") |
|||
end_time = fields.Datetime(string='End Date Time', required=True, |
|||
help="Auction start time") |
|||
extend_time = fields.Datetime(string="Extended Time", |
|||
help="By setting days you can " |
|||
"extend the auction") |
|||
state = fields.Selection( |
|||
[('draft', "Draft"), ('confirmed', "Confirmed"), |
|||
('running', "Running"), |
|||
('closed', "Closed"), ('finished', "Finished")], default='draft') |
|||
bargain_information_ids = fields.One2many('bargain.information', |
|||
'auction_id', readonly=True) |
|||
bargain_subscribers_ids = fields.One2many('bargain.subscribers', |
|||
'auction_id') |
|||
is_activate = fields.Boolean(string='Activate', |
|||
help='this will activate ' |
|||
'notification for the admins') |
|||
notify_on = fields.Integer(string='Notify before', default='5', |
|||
help="Set notification time here") |
|||
notify_selection = fields.Selection( |
|||
[('days', "Days"), ('hours', "Hours"), ('minutes', "Minutes"), |
|||
('seconds', "Seconds")], default='minutes') |
|||
is_notification_send = fields.Boolean(string='Notification Send', |
|||
help='If notification send manually ' |
|||
'you can enable this field ' |
|||
'to restrict ' |
|||
'sending notification before ' |
|||
'the time added') |
|||
is_winner_notification = fields.Boolean( |
|||
string='Send Notification to Winner', |
|||
help='Enable this option to send notification to the winner') |
|||
is_loser_notification = fields.Boolean(string='Send Notification to Loser', |
|||
help='Enable this option to send ' |
|||
'notification to the losers') |
|||
is_subscriber_start_notification = fields.Boolean(string='Bidding Start', |
|||
help="Send subscribers " |
|||
"the bidding start " |
|||
"notification") |
|||
is_send_mail = fields.Boolean(string='Bidding Started Mail Sent', |
|||
help='If Bidding mail has been sent to customer') |
|||
is_extend_auction_notification = fields.Boolean(string='Auction Extended', |
|||
help="Send subscribers the" |
|||
"bidding extended " |
|||
"notification") |
|||
is_new_bid_notification = fields.Boolean(string='New Bid Placed', |
|||
help="Send subscribers " |
|||
"notifications if new bids" |
|||
" are placed") |
|||
is_bid_end_notification = fields.Boolean(string='Auction Finished', |
|||
help="Send subscribers " |
|||
"notifications if bidding " |
|||
"is over") |
|||
product_img = fields.Binary(related="product_id.image_1920") |
|||
product_description = fields.Text(related="product_id.description_sale", |
|||
string="Auction Product Description") |
|||
|
|||
@api.onchange('template_id', 'product_id') |
|||
def _onchange_template_id(self): |
|||
"""summary: |
|||
function to add name automatically""" |
|||
if self.product_id: |
|||
self.name = f"Auction for {self.product_id.name}" |
|||
|
|||
@api.constrains('end_time', 'start_time') |
|||
def _check_end_date(self): |
|||
""" |
|||
Summary: |
|||
start and end date validation function |
|||
""" |
|||
if self.end_time <= self.start_time: |
|||
raise ValidationError( |
|||
_('End time should be greater than start time')) |
|||
|
|||
@api.constrains('extend_time') |
|||
def _check_extend_time(self): |
|||
"""Summary: |
|||
function to validate extended time weather it is greater than |
|||
end time and after saving will send notification to subscribers |
|||
if enabled""" |
|||
if self.extend_time: |
|||
if self.extend_time <= self.end_time: |
|||
raise ValidationError( |
|||
_('This time is not greater than the old time(' + str( |
|||
self.end_time) + ')')) |
|||
if self.is_extend_auction_notification: |
|||
template_id = self.env.ref( |
|||
'website_bargain.email_template_auction_extended') |
|||
email_to = '' |
|||
for subscriber in self.bargain_subscribers_ids: |
|||
email_to += subscriber.email + ',' |
|||
template_id.email_to = email_to |
|||
template_id.send_mail(self.id, force_send=True) |
|||
|
|||
def action_confirm(self): |
|||
""" |
|||
Summary: |
|||
button function to confirm auction and will |
|||
make product as published |
|||
""" |
|||
if self.search([('product_id', '=', self.product_id.id), |
|||
('state', '=', 'running')]): |
|||
raise ValidationError( |
|||
_('Already an auction is running for this product please' |
|||
' close it to continue')) |
|||
if self.end_time <= fields.Datetime.today(): |
|||
raise ValidationError(_('End time is already over')) |
|||
self.product_id.is_published = True |
|||
self.product_id.website_id = self.website_id |
|||
self.write({'state': 'confirmed'}) |
|||
|
|||
def action_reset_to_draft(self): |
|||
""" |
|||
Summary: |
|||
button function to reset the auction to draft |
|||
""" |
|||
self.product_id.is_auction = False |
|||
self.write({'state': 'draft'}) |
|||
|
|||
def action_run_auction(self): |
|||
""" |
|||
Summary: |
|||
button function to start auction manually |
|||
""" |
|||
if self.search([('product_id', '=', self.product_id.id), |
|||
('state', '=', 'running')]): |
|||
raise ValidationError( |
|||
_('Already an auction is running for this product ' |
|||
'please close it to continue')) |
|||
self.product_id.is_auction = True |
|||
self.write({'state': 'running'}) |
|||
|
|||
def action_complete(self): |
|||
""" |
|||
Summary: |
|||
button function to end auction manually |
|||
""" |
|||
self.product_id.is_auction = False |
|||
self.product_id.is_published = False |
|||
self.write({'state': 'finished'}) |
|||
|
|||
def action_close(self): |
|||
""" |
|||
Summary: |
|||
button function to close auction |
|||
""" |
|||
self.product_id.is_auction = False |
|||
self.product_id.is_published = False |
|||
self.write({'state': 'closed'}) |
|||
|
|||
def send_email_notification(self): |
|||
""" |
|||
Summary: |
|||
Function for sending auction notification for admin e ending if |
|||
enabled |
|||
""" |
|||
# Get the email template for the admin notification |
|||
template_id = self.env.ref( |
|||
'website_bargain.admin_email_template') |
|||
# Find all running auctions that have notification enabled and have |
|||
# not been sent yet |
|||
auctions = self.search([('state', '=', 'running'), |
|||
('is_activate', '=', True), |
|||
('notify_on', '>', 0), |
|||
('is_notification_send', '=', False)]) |
|||
# Loop through the auctions that need to be notified |
|||
for auction in auctions: |
|||
# Map the time unit to a string for timedelta |
|||
time_unit_map = {'days': 'days', 'hours': 'hours', |
|||
'minutes': 'minutes', 'seconds': 'seconds'} |
|||
time_unit = time_unit_map.get(auction.notify_selection) |
|||
# Check if it's time to send the notification |
|||
if time_unit: |
|||
next_notification = auction.end_time - timedelta( |
|||
**{time_unit: auction.notify_on}) |
|||
if next_notification <= fields.Datetime.today(): |
|||
# Send the notification email and set the flag to True |
|||
template_id.send_mail(auction.id, force_send=True) |
|||
auction.is_notification_send = True |
|||
|
|||
def auction_auto_start(self): |
|||
""" |
|||
Summary: |
|||
Cron function for auction auto start when its start |
|||
time and also will send notification to customers about auction |
|||
""" |
|||
# Get all confirmed auctions |
|||
auctions = self.search([('state', '=', 'confirmed')]) |
|||
# Get the email template for auction start notification |
|||
template_id = self.env.ref( |
|||
'website_bargain.email_template_auction_start') |
|||
# Get the emails of all the bidders and sale order partners |
|||
bidders = self.env['bargain.information'].search([]).mapped( |
|||
'bidder_id.email') |
|||
sale_orders_partner = self.env['sale.order'].search( |
|||
[('state', '=', 'sale')]).mapped('partner_id.email') |
|||
# Loop through the auctions and check if any auction's start time has arrived |
|||
for auction in auctions: |
|||
if auction.start_time <= fields.Datetime.now(): |
|||
# Set the product as an auction and update the website |
|||
auction.product_id.is_auction = True |
|||
auction.product_id.website_id = auction.website_id |
|||
auction.write({'state': 'running'}) |
|||
# Send email notifications to all the bidders and sale order partners |
|||
email_to = "" |
|||
for partner in sale_orders_partner: |
|||
email_to += partner + ',' |
|||
for bidder in bidders: |
|||
email_to += bidder + ',' |
|||
template_id.email_to = email_to |
|||
template_id.send_mail(auction.id, force_send=True) |
|
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 733 B |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 673 B |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 905 B |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 627 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 988 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 589 B |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 967 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 49 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 294 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 93 KiB |
After Width: | Height: | Size: 96 KiB |
After Width: | Height: | Size: 277 KiB |
After Width: | Height: | Size: 128 KiB |
After Width: | Height: | Size: 115 KiB |
After Width: | Height: | Size: 129 KiB |
After Width: | Height: | Size: 105 KiB |
After Width: | Height: | Size: 108 KiB |
After Width: | Height: | Size: 118 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 8.0 KiB |
@ -0,0 +1,593 @@ |
|||
<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: #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> |
|||
<img src="./assets/screenshots/hero.gif" class="img-responsive" |
|||
width="100%" height="auto"/> |
|||
<!-- END OF APP HERO --> |
|||
</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;"> |
|||
x |
|||
<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: 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;">Timer On Product Until End Of Auction.</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;">Subscription Available.</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;">Different Email Notifications.</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;">Option To See Bidders.</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;">Option For Buy Now.</span> |
|||
</div> |
|||
</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;">Navigate to 'Auction' menu in Website to create new auctions.</p> |
|||
<img src="assets/screenshots/website_bargain_01.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
Create an auction by entering the details and then click 'CONFIRM'.</p> |
|||
<img src="assets/screenshots/website_bargain_02.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 it is in confirmed stage.If you want to run manually just click on RUN AUCTION Button.</p> |
|||
<img src="assets/screenshots/website_bargain_03.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;"> |
|||
'Auction On' in Shop Page.</h3> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
Customers can see 'AUCTION ON' on that product in the shop page.</p> |
|||
<img src="assets/screenshots/website_bargain_04.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/website_bargain_05.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/website_bargain_06.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/website_bargain_07.png" |
|||
class="img-thumbnail"> |
|||
<img src="assets/screenshots/website_bargain_08.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
View in backend. |
|||
</p> |
|||
<img src="assets/screenshots/website_bargain_09.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
These are different Notifications options.</p> |
|||
<img src="assets/screenshots/website_bargain_10.png" class="img-thumbnail"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- END OF SCREENSHOTS SECTION --> |
|||
<!-- SUGGESTED PRODUCTS --> |
|||
<div class="row"> |
|||
<div class="col-lg-12 d-flex flex-column justify-content-center" |
|||
style="text-align: center; padding: 2.5rem 1rem !important;"> |
|||
<h2 style="color: #212529 !important;">Suggested Products</h2> |
|||
<hr style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;"/> |
|||
<div id="demo1" class="row carousel slide" data-ride="carousel"> |
|||
<!-- The slideshow --> |
|||
<div class="carousel-inner"> |
|||
<div class="carousel-item active" style="min-height:0px"> |
|||
<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/user_audit/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-top-left-radius:10px; border-top-right-radius:10px" |
|||
src="./assets/modules/dynamic_financial_reports.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/15.0/login_user_detail/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-top-left-radius:10px; border-top-right-radius:10px" |
|||
src="./assets/modules/login_user.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/15.0/hide_menu_user/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-top-left-radius:10px; border-top-right-radius:10px" |
|||
src="./assets/modules/hid_menu.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div class="carousel-item" style="min-height:0px"> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" |
|||
style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/15.0/customer_product_qrcode/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-top-left-radius:10px; border-top-right-radius:10px" |
|||
src="./assets/modules/qr_code.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/15.0/web_login_styles/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-top-left-radius:10px; border-top-right-radius:10px" |
|||
src="./assets/modules/login_style.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/15.0/advanced_chatter_view/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-top-left-radius:10px; border-top-right-radius:10px" |
|||
src="./assets/modules/chatter_view.jpg"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- Left and right controls --> |
|||
<a class="carousel-control-prev" href="#demo1" data-slide="prev" |
|||
style="left:-25px;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="right:-25px;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 SUGGESTED 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 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 & 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 --> |
@ -0,0 +1,66 @@ |
|||
p { |
|||
font - size: 16 px; |
|||
line - height: 1.5; |
|||
} |
|||
#subscribe_bid { |
|||
color: #007bff; |
|||
text-decoration:none; |
|||
font-weight:bold; |
|||
} |
|||
#subscribe_bid:hover{ |
|||
cursor:pointer; |
|||
transform:scale(1.2); |
|||
} |
|||
|
|||
#bidder_information{ |
|||
width:100%; |
|||
border-collapse:collapse; |
|||
} |
|||
#bidder_information th,td{ |
|||
padding:8px; |
|||
text-align:left; |
|||
border-bottom:1px solid #ddd; |
|||
} |
|||
#bidder_information thead th{ |
|||
position:sticky; |
|||
top:0; |
|||
background-color:#f5f5f5; |
|||
} |
|||
#bidder_information tbody{ |
|||
height:200px; |
|||
overflow-y:scroll; |
|||
} |
|||
#auction_bidders{ |
|||
padding-left:60px; |
|||
color: #007bff; |
|||
} |
|||
#auction_bidders:hover{ |
|||
cursor:pointer; |
|||
transform:scale(1.2); |
|||
} |
|||
#bid_amount{ |
|||
max-width:10rem; |
|||
font-size:16px; |
|||
} |
|||
.auction_timer{ |
|||
border: 2px solid #ccc; |
|||
border-radius:6px; |
|||
padding:20px; |
|||
display: inline-block; |
|||
background:#dbdbdb4a; |
|||
} |
|||
.auction_timer:hover{ |
|||
transform:scale(1.2); |
|||
} |
|||
#timer{ |
|||
font-size: 24px; |
|||
font-weight: bold; |
|||
color: #333; |
|||
background-color: #f5f5f5; |
|||
} |
|||
.auction_min_amount{ |
|||
padding: 10px; |
|||
} |
|||
.alert { |
|||
display: none; |
|||
} |
@ -0,0 +1,270 @@ |
|||
/** @odoo-module **/ |
|||
var website_sale_inherit = require('website_sale.website_sale'); |
|||
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.**/ |
|||
website_sale_inherit.WebsiteSale.include({ |
|||
/**The start function initializes the auction timer when the page is loaded. |
|||
It first checks if there are any ongoing auctions and hides the |
|||
"add to cart" button if the product is being auctioned. Then, it retrieves |
|||
the product and auction IDs from the input fields, sends an AJAX request to |
|||
the server to fetch the auction details, and calculates the time remaining |
|||
until the auction ends. If the auction has ended, the function redirects |
|||
the user to the shop page, and if not, it sets up an interval to update |
|||
the timer every second.**/ |
|||
start: function() { |
|||
/** function to add timer and check the time **/ |
|||
this._super(...arguments); |
|||
var modal_title = this.$('#modal_title')[0] |
|||
var modal_message = this.$('#modal_message')[0] |
|||
var product_name = this.$('input[name="auction_product_id"]').val(); |
|||
var auction_id_status = this.$('input[name="auction_id"]').val() |
|||
var bellIcon = this.el.querySelector('#subscribe_bid'); |
|||
if (auction_id_status != undefined){ |
|||
ajax.jsonRpc('/subscribe/status', 'call', { |
|||
'auction_id': auction_id_status, |
|||
}).then((data) => { |
|||
if (data){ |
|||
bellIcon.style.color = 'red' |
|||
bellIcon.classList.remove('fa-bell-o') |
|||
bellIcon.classList.add('fa-bell') |
|||
bellIcon.innerHTML = 'Unsubscribe' |
|||
} |
|||
else { |
|||
bellIcon.style.color = '#007bff' |
|||
bellIcon.classList.remove('fa-bell') |
|||
bellIcon.classList.add('fa-bell-o') |
|||
bellIcon.innerHTML = 'Subscribe' |
|||
} |
|||
}) |
|||
} |
|||
let auctionText = this.$('#modal_message')[0] |
|||
if (auctionText) { |
|||
$.each($('.o_wsale_product_btn'), (key, values) => { |
|||
if (values.nextElementSibling.innerHTML == 'AUCTION ON') { |
|||
values.style.display = "none" |
|||
} |
|||
}) |
|||
} |
|||
let product_id = this.$('input[name="auction_product_id"]').val(); |
|||
let auction_id = this.$('input[name="auction_id"]').val(); |
|||
let timerId; // variable to hold the ID of the interval timer
|
|||
if (product_id) { |
|||
let product_product_id = this.$('input[name="product_product_id"]').val() |
|||
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 { |
|||
var self = this; |
|||
timerId = setInterval(function() { |
|||
var time_key = data['extend_time'] ? 'extend_time' : 'end_time' |
|||
var time_remaining = new Date(data[time_key]) - new Date() |
|||
var days = Math.floor(time_remaining / (1000 * 60 * 60 * 24)); |
|||
var hours = Math.floor((time_remaining / (1000 * 60 * 60)) % 24); |
|||
var minutes = Math.floor((time_remaining / (1000 * 60)) % 60); |
|||
var seconds = Math.floor((time_remaining / 1000) % 60); |
|||
if (self.el.querySelector('#timer')) { |
|||
self.el.querySelector('#timer').innerHTML = days + "d." + " " + hours + "h." + " " + minutes + "m." + " " + seconds + "s." |
|||
} |
|||
if (time_remaining <= 0) { |
|||
clearInterval(timerId); |
|||
} |
|||
}, 1000); |
|||
var time_key = data['extend_time'] ? 'extend_time' : 'end_time' |
|||
var time_remaining = new Date(data[time_key]) - new Date() |
|||
if (time_remaining <= 0) { |
|||
window.location.href = '/shop'; |
|||
} |
|||
} |
|||
}) |
|||
} |
|||
}, |
|||
events: { |
|||
/** Click event for subscribe button**/ |
|||
'click #subscribe_bid': '_clickSubscribe', |
|||
|
|||
/**Click event for add to cart and buy now buttons**/ |
|||
'click #add_to_cart, .o_we_buy_now, #products_grid .o_wsale_product_btn .a-submit': 'async _onClickAdd', |
|||
|
|||
/**Click event for place bid button**/ |
|||
'click #place_bid_button': '_placeBid', |
|||
|
|||
/**Click event for hide modal button**/ |
|||
'click #hide_modal': '_hideModal', |
|||
|
|||
/**Click event for buy now button**/ |
|||
'click .js_add_cart': '_buyNow' |
|||
}, |
|||
/** Function to hide auction messages after 5 seconds **/ |
|||
timeout: function() { |
|||
var self = this; |
|||
setTimeout(function() { |
|||
self.el.querySelector('#auction_messages').style.display = "none" |
|||
}, 5000) |
|||
}, |
|||
/** Function to handle subscription to auction updates **/ |
|||
_clickSubscribe: function() { |
|||
// Get product and auction IDs
|
|||
let product_id = this.$('input[name="auction_product_id"]').val() |
|||
let auction_id = this.$('input[name="auction_id"]').val(); |
|||
|
|||
// Get subscribe button and auction messages elements
|
|||
var bellIcon = this.el.querySelector('#subscribe_bid'); |
|||
var messages = this.el.querySelector('#auction_messages') |
|||
|
|||
// If button says "Subscribe", subscribe user to auction updates
|
|||
if (bellIcon.innerHTML == 'Subscribe' ) { |
|||
bellIcon.style.color = 'red' |
|||
bellIcon.classList.remove('fa-bell-o') |
|||
bellIcon.classList.add('fa-bell') |
|||
bellIcon.innerHTML = 'Unsubscribe' |
|||
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') |
|||
setTimeout(function() { |
|||
window.location.href = '/shop' |
|||
}, 5000) |
|||
}, |
|||
}) |
@ -0,0 +1,51 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<!-- Define a form view for the bargain information model --> |
|||
<record id="bargain_information_view_form" model="ir.ui.view"> |
|||
<field name="name">bargain.information.view.form</field> |
|||
<field name="model">bargain.information</field> |
|||
<field name="arch" type="xml"> |
|||
<form> |
|||
<sheet> |
|||
<group> |
|||
<group> |
|||
<field name="bidder_id"/> |
|||
<field name="auction_id"/> |
|||
<field name="product_id"/> |
|||
</group> |
|||
<group> |
|||
<field name="currency_id" invisible="1"/> |
|||
<field name="bid_offer" widget="monetary" |
|||
force_save="1"/> |
|||
<field name="status"/> |
|||
</group> |
|||
</group> |
|||
</sheet> |
|||
<div class="oe_chatter"> |
|||
<field name="message_follower_ids"/> |
|||
<field name="activity_ids"/> |
|||
<field name="message_ids" |
|||
options="{'post_refresh':'recipients'}"/> |
|||
</div> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
<!-- Define a tree view for the bargain information model --> |
|||
<record id="bargain_information_view_tree" model="ir.ui.view"> |
|||
<field name="name">bargain.information.view.tree</field> |
|||
<field name="model">bargain.information</field> |
|||
<field name="arch" type="xml"> |
|||
<tree> |
|||
<field name="bidder_id"/> |
|||
<field name="auction_id"/> |
|||
<field name="bid_offer"/> |
|||
<field name="status"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
<record id="bargain_information_action" model="ir.actions.act_window"> |
|||
<field name="name">Bidder Information</field> |
|||
<field name="res_model">bargain.information</field> |
|||
<field name="view_mode">tree,form,activity</field> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,53 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<!-- Define a form view for the "bargain.subscribers" model --> |
|||
<record id="bargain_subscribers_view_form" model="ir.ui.view"> |
|||
<field name="name">bargain.subscribers.view.form</field> |
|||
<field name="model">bargain.subscribers</field> |
|||
<field name="arch" type="xml"> |
|||
<form> |
|||
<sheet> |
|||
<group> |
|||
<group> |
|||
<field name="subscriber_id"/> |
|||
<field name="name"/> |
|||
<field name="email"/> |
|||
</group> |
|||
<group> |
|||
<field name="auction_id"/> |
|||
<field name="subscribe_time"/> |
|||
<field name="is_subscribed"/> |
|||
</group> |
|||
</group> |
|||
</sheet> |
|||
<!-- Add a chatter to the form view for messaging and activities --> |
|||
<div class="oe_chatter"> |
|||
<field name="message_follower_ids"/> |
|||
<field name="activity_ids"/> |
|||
<field name="message_ids" |
|||
options="{'post_refresh':'recipients'}"/> |
|||
</div> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
<!-- Define a tree view for the "bargain.subscribers" model --> |
|||
<record id="bargain_subscribers_view_tree" model="ir.ui.view"> |
|||
<field name="name">bargain.subscribers.view.tree</field> |
|||
<field name="model">bargain.subscribers</field> |
|||
<field name="arch" type="xml"> |
|||
<tree> |
|||
<field name="subscriber_id"/> |
|||
<field name="name"/> |
|||
<field name="email"/> |
|||
<field name="auction_id"/> |
|||
<field name="subscribe_time"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
<!-- Define an action to open the "bargain.subscribers" model --> |
|||
<record id="bargain_subscribers_action" model="ir.actions.act_window"> |
|||
<field name="name">Bargain Subscribers</field> |
|||
<field name="res_model">bargain.subscribers</field> |
|||
<field name="view_mode">tree,form</field> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,31 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Define a view for the website bargain template --> |
|||
<record id="bargain_template_view_form" model="ir.ui.view"> |
|||
<field name="name">bargain.template.view.form</field> |
|||
<field name="model">bargain.template</field> |
|||
<field name="arch" type="xml"> |
|||
<form> |
|||
<sheet> |
|||
<!-- Define a group for the name and product_id fields --> |
|||
<group class="mt-4"> |
|||
<field name="name"/> |
|||
<field name="product_id"/> |
|||
</group> |
|||
</sheet> |
|||
<div class="oe_chatter"> |
|||
<field name="message_follower_ids"/> |
|||
<field name="activity_ids"/> |
|||
<field name="message_ids" |
|||
options="{'post_refres':'recipients'}"/> |
|||
</div> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
<!-- Define an action for the bargain template --> |
|||
<record id="bargain_template_action" model="ir.actions.act_window"> |
|||
<field name="name">Website Bidding Template</field> |
|||
<field name="res_model">bargain.template</field> |
|||
<field name="view_mode">tree,form</field> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,64 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<template id="bidders_information" name="Website bidders"> |
|||
<!-- Template extending website.layout --> |
|||
<t t-call="website.layout"> |
|||
<div id="wrap" class="o_portal_wrap"> |
|||
<div class="container mv64"> |
|||
<!-- Bootstrap table to show bidders information --> |
|||
<div class="table-responsive border rounded border-top-0 "> |
|||
<!-- Title of the table --> |
|||
<h2 class="text-center">Bid for |
|||
<t t-esc="product_id.name"/> |
|||
</h2> |
|||
<!-- Table headers --> |
|||
<table id="bidder_information"> |
|||
<thead> |
|||
<tr class="active"> |
|||
<th class="text-center">Name</th> |
|||
<th class="text-center">Bid Amount</th> |
|||
<th class="text-center">Bid Status</th> |
|||
<th class="text-center">Phone</th> |
|||
<th class="text-center">Email</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<!-- Looping over the bidders_information to show the bid details --> |
|||
<t t-foreach="bidders_information" |
|||
t-as="bidders"> |
|||
<tr> |
|||
<!-- Bidder's name --> |
|||
<td class="text-center" |
|||
t-esc="bidders.bidder_id.name"/> |
|||
<!-- Bid amount --> |
|||
<td class="text-center" |
|||
t-esc="bidders.bid_offer"/> |
|||
<!-- Bid status --> |
|||
<td class="text-center" |
|||
t-esc="bidders.status"/> |
|||
<!-- Bidder's phone number --> |
|||
<td class="text-center" |
|||
t-esc="bidders.bidder_id.phone"/> |
|||
<!-- Bidder's email --> |
|||
<td class="text-center" |
|||
t-esc="bidders.bidder_id.email"/> |
|||
<!-- Checking if the bidder is the current user and the bid status is 'Bid Placed', then show cancel bid link --> |
|||
<t t-set="partner" |
|||
t-value="request.env.user.partner_id"/> |
|||
<t t-if="(bidders.status=='Bid Placed') and (partner==bidders.bidder_id)"> |
|||
<td> |
|||
<a t-attf-href="/bid/cancel/{{ slug(bidders) }}"> |
|||
cancel bid |
|||
</a> |
|||
</td> |
|||
</t> |
|||
</tr> |
|||
</t> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</t> |
|||
</template> |
|||
</odoo> |
@ -0,0 +1,17 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<!--Inherit product template to add auction --> |
|||
<record id="product_template_only_form_view" model="ir.ui.view"> |
|||
<field name="name">product.template.view.form.inherit.website.bargain |
|||
</field> |
|||
<field name="model">product.template</field> |
|||
<field name="inherit_id" |
|||
ref="product.product_template_only_form_view"/> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//page[@name='sales']//group[@name='shop']" |
|||
position="inside"> |
|||
<field name="is_auction"/> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,27 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<menuitem id="website_auction_menu" |
|||
name="Auction" |
|||
sequence="10" |
|||
parent="website.menu_website_configuration"/> |
|||
<menuitem id="website_bargain_menu_open_website_bargain" |
|||
parent="website_auction_menu" |
|||
sequence="20" |
|||
name="Auctions" |
|||
action="website_bargain_action"/> |
|||
<menuitem id="bargain_template_menu_open_bargain_template" |
|||
parent="website_auction_menu" |
|||
sequence="21" |
|||
name="Template" |
|||
action="bargain_template_action"/> |
|||
<menuitem id="bargain_information_menu_open_bidder_information" |
|||
parent="website_auction_menu" |
|||
sequence="23" |
|||
name="Bidder Information" |
|||
action="bargain_information_action"/> |
|||
<menuitem id="bargain_subscribers_menu_open_bargain_subscribers" |
|||
parent="website_auction_menu" |
|||
sequence="24" |
|||
name="Subscribers" |
|||
action="bargain_subscribers_action"/> |
|||
</odoo> |
@ -0,0 +1,158 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<!-- Form view for website.bargain model --> |
|||
<record id="website_bargain_view_form" model="ir.ui.view"> |
|||
<field name="name">website.bargain.view.form</field> |
|||
<field name="model">website.bargain</field> |
|||
<field name="arch" type="xml"> |
|||
<form> |
|||
<header> |
|||
<button name="action_confirm" type="object" |
|||
string="Confirm" class="oe_highlight" |
|||
states="draft"/> |
|||
<button name="action_reset_to_draft" type="object" |
|||
string="Reset to draft" class="oe_highlight" |
|||
states="confirmed,running"/> |
|||
<button name="action_run_auction" type="object" |
|||
string="Run Auction" class="oe_highlight" |
|||
states="confirmed"/> |
|||
<button name="action_complete" type="object" |
|||
string="Completed" class="oe_highlight" |
|||
states="running,extended"/> |
|||
<button name="action_close" type="object" string="Closed" |
|||
class="oe_highlight" |
|||
states="running,extended,finished" |
|||
/> |
|||
<field name="state" widget="statusbar"/> |
|||
</header> |
|||
<sheet> |
|||
<group class="mt-4"> |
|||
<field name="website_id" |
|||
attrs="{'readonly': [('state', 'not in', ['draft'])]}"/> |
|||
<field name="auction_manager_id" |
|||
attrs="{'readonly': [('state', 'not in', ['draft'])]}"/> |
|||
<field name="template_id" |
|||
attrs="{'readonly': [('state', 'not in', ['draft'])]}"/> |
|||
<field name="product_id" |
|||
attrs="{'readonly': [('state', 'not in', ['draft'])]}"/> |
|||
<field name="name" |
|||
attrs="{'readonly': [('state', 'not in', ['draft'])]}"/> |
|||
</group> |
|||
<group> |
|||
<group name="price_configuration" |
|||
string="Price Configuration"> |
|||
<field name="currency_id" position="attributes" |
|||
attrs="{'readonly': [('state', 'not in', ['draft'])]}"/> |
|||
<field name="initial_price" widget="monetary" |
|||
attrs="{'readonly': [('state', 'not in', ['draft'])]}" |
|||
force_save="1"/> |
|||
<field name="is_buy_now" |
|||
attrs="{'readonly': [('state', 'not in', ['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', 'not in', ['draft'])]}"/> |
|||
<field name="end_time" |
|||
attrs="{'readonly': [('state', 'not in', ['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"/> |
|||
<field name="is_send_mail" invisible="1"/> |
|||
</group> |
|||
</group> |
|||
</page> |
|||
<page name="product_info" string="Product Info"> |
|||
<group string="Product Information"> |
|||
<field name="product_img" widget="image" |
|||
style="padding: 0px;" nolabel="1"/> |
|||
</group> |
|||
<group> |
|||
<field name="product_id" |
|||
string="Auction Product Name"/> |
|||
<field name="product_description"/> |
|||
</group> |
|||
</page> |
|||
</notebook> |
|||
</sheet> |
|||
<div class="oe_chatter"> |
|||
<field name="message_follower_ids"/> |
|||
<field name="activity_ids"/> |
|||
<field name="message_ids" |
|||
options="{'post_refres':'recipients'}"/> |
|||
</div> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
<!-- Tree view for website.bargain model --> |
|||
<record id="website_bargain_view_tree" model="ir.ui.view"> |
|||
<field name="name">website.bargain.view.tree</field> |
|||
<field name="model">website.bargain</field> |
|||
<field name="arch" type="xml"> |
|||
<tree> |
|||
<field name="name"/> |
|||
<field name="product_id"/> |
|||
<field name="start_time"/> |
|||
<field name="end_time"/> |
|||
<field name="extend_time" optional="hide"/> |
|||
<field name="state"/> |
|||
<field name="website_id" optional="hide"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
<record id="website_bargain_action" model="ir.actions.act_window"> |
|||
<field name="name">Website Bargain</field> |
|||
<field name="res_model">website.bargain</field> |
|||
<field name="view_mode">tree,form</field> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,187 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<template id="website_product_view" inherit_id="website_sale.product"> |
|||
<xpath expr="//div[@id='product_details']" position="replace"> |
|||
<t t-if="product.is_auction"> <!-- Conditionally render elements based on the "is_auction" attribute of the product object --> |
|||
<!-- Create hidden input fields with values from the product and auction objects --> |
|||
<t t-if="request.env.user._is_public()"> |
|||
<t t-log="request.env.user._is_public()"/> |
|||
<div class="col-md-6 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.id==product.id) and (website.id == bid.website_id.id)"> |
|||
<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 class="col-md-6 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"> |
|||
<span t-field="bid.extend_time"/> |
|||
</t> |
|||
<t t-else=""> |
|||
<span t-field="bid.end_time"/> |
|||
</t> |
|||
</div> |
|||
<div class="auction_min_amount"> |
|||
Min bid amount |
|||
<t t-esc="bid.currency_id.name"/> |
|||
<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.symbol"/> |
|||
<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 class="col-md-6 mt-md-4" id="product_details"> |
|||
<t t-set="base_url" t-value="product.get_base_url()"/> |
|||
<h1 itemprop="name" t-field="product.name">Product Name</h1> |
|||
<span itemprop="url" style="display:none;" t-esc="base_url + product.website_url"/> |
|||
<span itemprop="image" style="display:none;" t-esc="base_url + website.image_url(product, 'image_1920')" /> |
|||
<t t-if="is_view_active('website_sale.product_comment')"> |
|||
<a href="#o_product_page_reviews" class="o_product_page_reviews_link text-decoration-none"> |
|||
<t t-call="portal_rating.rating_widget_stars_static"> |
|||
<t t-set="rating_avg" t-value="product.rating_avg"/> |
|||
<t t-set="trans_text_plural">%s reviews</t> |
|||
<t t-set="trans_text_singular">%s review</t> |
|||
<t t-set="rating_count" t-value="(trans_text_plural if product.rating_count > 1 else trans_text_singular) % product.rating_count"/> |
|||
</t> |
|||
</a> |
|||
</t> |
|||
<p t-field="product.description_sale" class="text-muted my-2" placeholder="A short description that will also appear on documents." /> |
|||
<form t-if="product._is_add_to_cart_possible()" action="/shop/cart/update" method="POST"> |
|||
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()" /> |
|||
<div class="js_product js_main_product mb-3"> |
|||
<div> |
|||
<t t-call="website_sale.product_price" /> |
|||
<small class="ml-1 text-muted o_base_unit_price_wrapper d-none" groups="website_sale.group_show_uom_price"> |
|||
<t t-call='website_sale.base_unit_price'/> |
|||
</small> |
|||
</div> |
|||
<t t-placeholder="select"> |
|||
<input type="hidden" class="product_id" name="product_id" t-att-value="product_variant.id" /> |
|||
<input type="hidden" class="product_template_id" name="product_template_id" t-att-value="product.id" /> |
|||
<input t-if="product.public_categ_ids.ids" type="hidden" class="product_category_id" name="product_category_id" t-att-value="product.public_categ_ids.ids[0]" /> |
|||
<t t-if="combination" t-call="sale.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" 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> |
|||
<div id="add_to_cart_wrap" class="d-inline"> |
|||
<a data-animation-selector=".o_wsale_product_images" role="button" id="add_to_cart" class="btn btn-primary btn-lg js_check_product a-submit my-1 mr-1 px-5 font-weight-bold flex-grow-1" href="#"><i class="fa fa-shopping-cart mr-2"/>ADD TO CART</a> |
|||
<div id="product_option_block" class="d-inline-block align-middle"/> |
|||
</div> |
|||
</div> |
|||
</form> |
|||
<p t-elif="not product.active" class="alert alert-warning">This product is no longer available.</p> |
|||
<p t-else="" class="alert alert-warning">This product has no valid combination.</p> |
|||
<div id="product_attributes_simple"> |
|||
<t t-set="single_value_attributes" t-value="product.valid_product_template_attribute_line_ids._prepare_single_value_for_display()"/> |
|||
<table t-attf-class="table table-sm text-muted {{'' if single_value_attributes else 'd-none'}}"> |
|||
<t t-foreach="single_value_attributes" t-as="attribute"> |
|||
<tr> |
|||
<td> |
|||
<span t-field="attribute.name"/>: |
|||
<t t-foreach="single_value_attributes[attribute]" t-as="ptal"> |
|||
<span t-field="ptal.product_template_value_ids._only_active().name"/><t t-if="not ptal_last">, </t> |
|||
</t> |
|||
</td> |
|||
</tr> |
|||
</t> |
|||
</table> |
|||
</div> |
|||
<div id="o_product_terms_and_share"> |
|||
</div> |
|||
</div> |
|||
</t> |
|||
</xpath> |
|||
</template> |
|||
</odoo> |
@ -0,0 +1,22 @@ |
|||
<?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 mb-1" itemprop="offers" itemscope="itemscope" itemtype="http://schema.org/Offer"> |
|||
<span class="h5" t-if="combination_info['price']" t-esc="combination_info['price']" t-options="{'widget': 'monetary', 'display_currency': website.currency_id}"/> |
|||
<del t-attf-class="text-danger ml-1 h6 {{'' if combination_info['has_discounted_price'] else 'd-none'}}" style="white-space: nowrap;" t-esc="combination_info['list_price']" t-options="{'widget': 'monetary', 'display_currency': website.currency_id}" /> |
|||
<span itemprop="price" style="display:none;" t-esc="combination_info['price']" /> |
|||
<span itemprop="priceCurrency" style="display:none;" t-esc="website.currency_id.name" /> |
|||
</div> |
|||
</t> |
|||
</xpath> |
|||
</template> |
|||
</odoo> |