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