@ -0,0 +1,44 @@ |
|||
.. image:: https://img.shields.io/badge/license-LGPL--3-green.svg |
|||
:target: https://www.gnu.org/licenses/lgpl-3.0-standalone.html |
|||
:alt: License: LGPL-3 |
|||
|
|||
Product Bidding In ECommerce |
|||
============================= |
|||
This module helps you to add auction in website sale. |
|||
|
|||
Configuration |
|||
============= |
|||
* No additional configurations needed |
|||
|
|||
Company |
|||
------- |
|||
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ |
|||
|
|||
License |
|||
------- |
|||
Lesser General Public License, Version 3 (LGPL v3). |
|||
(http://www.gnu.org/licenses/lgpl-3.0-standalone.html) |
|||
|
|||
Credits |
|||
------- |
|||
* Developers: (V16) Mruthul Raj, Contact:odoo@cybrosys.com |
|||
|
|||
Contacts |
|||
-------- |
|||
* Mail Contact : odoo@cybrosys.com |
|||
* Website : https://cybrosys.com |
|||
|
|||
Bug Tracker |
|||
----------- |
|||
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. |
|||
|
|||
Maintainer |
|||
========== |
|||
.. image:: https://cybrosys.com/images/logo.png |
|||
:target: https://cybrosys.com |
|||
This module is maintained by Cybrosys Technologies. |
|||
For support and more information, please visit `Our Website <https://cybrosys.com/>`__ |
|||
|
|||
Further information |
|||
=================== |
|||
HTML Description: `<static/description/index.html>`__ |
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Mruthul Raj (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from . import controllers, models |
@ -0,0 +1,60 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Mruthul Raj (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
{ |
|||
'name': 'Product Bidding In ECommerce', |
|||
'version': '16.0.1.0.0', |
|||
'category': 'Website', |
|||
'summary': 'App To Add Bidding option In Website', |
|||
'description': 'Website Bargain is an application where users can create ' |
|||
'and manage bargains on their website, enabling their ' |
|||
'customers to participate in bidding and negotiate prices ' |
|||
'for products or services', |
|||
'author': 'Cybrosys Techno Solution', |
|||
'company': 'Cybrosys Techno Solutions', |
|||
'maintainer': 'Cybrosys Techno Solution', |
|||
'website': 'https://www.cybrosys.com', |
|||
'depends': ['website_sale', 'contacts'], |
|||
'data': [ |
|||
'security/ir.model.access.csv', |
|||
'data/ir_cron_data.xml', |
|||
'data/mail_template_data.xml', |
|||
'views/website_bargain_views.xml', |
|||
'views/bargain_template_views.xml', |
|||
'views/bargain_information_views.xml', |
|||
'views/bargain_subscribers_views.xml', |
|||
'views/product_template_views.xml', |
|||
'views/website_shop_auction_templates.xml', |
|||
'views/website_product_views_templates.xml', |
|||
'views/website_bargain_menus.xml', |
|||
'views/bidders_information_templates.xml' |
|||
], |
|||
'assets': { |
|||
'web.assets_frontend': [ |
|||
'website_bargain/static/src/js/website_bargain.js', |
|||
'website_bargain/static/src/css/website_product_bargain.css', |
|||
]}, |
|||
'images': ['static/description/banner.jpg'], |
|||
'license': 'LGPL-3', |
|||
'installable': True, |
|||
'auto-install': False, |
|||
'application': False, |
|||
} |
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Mruthul Raj (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from . import website_bargain |
@ -0,0 +1,318 @@ |
|||
"""Auctions main controller """ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Mruthul Raj (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from odoo import fields, http |
|||
from odoo.addons.website_sale.controllers.main import WebsiteSale |
|||
from odoo.http import request |
|||
|
|||
|
|||
class WebsiteAuction(WebsiteSale): |
|||
"""This class enables is used to view the timer and related functions |
|||
of bidding,buy now and other routes |
|||
_prepare_product_values(self, product, category, search, **kwargs): |
|||
This function is inbuilt function in website sale and its |
|||
supered here and pass auction values in this function |
|||
auction_timer(self, auction_id): |
|||
This function gets the auction id and pass auction timing |
|||
details to website |
|||
buy_now(self, auction_id, product_id): |
|||
Its the function for button in buy now,in this function a new |
|||
sale order is created and send to the customer through email |
|||
def auction_close(self, auction_id): |
|||
Function gets the auction id and move the auction stage to |
|||
finished and make the product unavailable from website |
|||
winner_sale_order(self, auction_id, **post): |
|||
Makes a sale order to the winner and id notifications are |
|||
enabled it will send a email to the winners or losers |
|||
subscribe(self, auction_id, **post): |
|||
Used to add subscribers from website to database |
|||
place_bid(self, auction_id, **post): |
|||
When place bid button is triggered it will call this function |
|||
and the bidders details will be added to database and |
|||
if enabled it will send notification to subscribers |
|||
bidders(self, product_id): |
|||
Route to pass bidders details to website |
|||
bid_cancel(self, bidders): |
|||
Function to cancel the bid""" |
|||
|
|||
def _prepare_product_values(self, product, category, search, **kwargs): |
|||
"""Summary: |
|||
Function is used to pass auction details by supering |
|||
this function because its already defined it websitesale |
|||
Args: |
|||
product:pass the object product |
|||
category:pass the category if enabled |
|||
kwargs:used to pass variable to function |
|||
Return: |
|||
Values is updated with auction and current website and |
|||
passed to website sale""" |
|||
values = super()._prepare_product_values(product, category, search, |
|||
**kwargs) |
|||
current_website = request.website |
|||
auction = request.env['website.bargain'].sudo().search_read([]) |
|||
values.update({ |
|||
'auction': auction, |
|||
'website': current_website |
|||
}) |
|||
return values |
|||
|
|||
@http.route('/auction/timer', type='json', auth='user', csrf=False) |
|||
def auction_timer(self, auction_id): |
|||
"""Summary: |
|||
Function to pass timer details from auction like start |
|||
time,end time,extended time |
|||
Args: |
|||
auction_id:used to get auction id from website |
|||
Return: |
|||
Values which include start_time,end time,extended |
|||
time and state id""" |
|||
auction = request.env['website.bargain'].sudo().browse(int(auction_id)) |
|||
values = { |
|||
'start_time': auction.start_time, |
|||
'end_time': fields.Datetime.context_timestamp(auction, |
|||
auction.end_time), |
|||
'state': auction.state, |
|||
} |
|||
if auction.extend_time: |
|||
values['extend_time'] = fields.Datetime.context_timestamp(auction, |
|||
auction.extend_time) |
|||
return values |
|||
|
|||
@http.route('/auction/close', type='json', auth='user', csrf=False) |
|||
def auction_close(self, auction_id): |
|||
"""Summary: |
|||
Function to close auction when a customer buys |
|||
a product instantly or the auction is ended |
|||
Args: |
|||
auction_id: used to get auction id from website |
|||
Return: |
|||
a string auction ended to website""" |
|||
auction = request.env['website.bargain'].sudo().browse(int(auction_id)) |
|||
auction.product_id.is_auction = False |
|||
auction.product_id.is_published = False |
|||
auction.write({'state': 'finished'}) |
|||
return "auction ended" |
|||
|
|||
@http.route('/place_bid', type='json', auth='user', csrf=False) |
|||
def place_bid(self, auction_id, **post): |
|||
"""Summary: |
|||
When place bid button is clicked it will trigger this function |
|||
and will add bidders details to backend and will send |
|||
notification to the subscribers if its enabled |
|||
Args: |
|||
auction_id:used to get auction id from website |
|||
post:used to get bid amount from frontend |
|||
Return: |
|||
A message bid placed and suction details""" |
|||
bid_amount = post.get('bid_amount') |
|||
auction = request.env['website.bargain'].sudo().browse(int(auction_id)) |
|||
bidder_total = auction.bargain_information_ids.search_count( |
|||
[('bidder_id', '=', request.env.user.partner_id.id), |
|||
('bid_offer', '=', bid_amount)]) |
|||
if bidder_total >= 1: |
|||
return False |
|||
else: |
|||
auction.bargain_information_ids.sudo().create({ |
|||
'bidder_id': request.env.user.partner_id.id, |
|||
'auction_id': auction.id, |
|||
'bid_offer': bid_amount, |
|||
'status': 'Bid Placed' |
|||
}) |
|||
if auction.is_new_bid_notification: |
|||
data = 'A new bid has been placed with amount ' + str( |
|||
bid_amount) + ',on ' \ |
|||
+ auction.name + ',by ' + request.env.user.partner_id.name \ |
|||
+ 'please check into ' \ |
|||
'our website' |
|||
subscribers = " " |
|||
for record in auction.bargain_subscribers_ids: |
|||
subscribers += record.subscriber_id.email + ',' |
|||
email_values = {'email_from': auction.auction_manager_id.email, |
|||
'subject': 'New Bid Placed on ' + auction.name, |
|||
'email_to': subscribers, 'body_html': data} |
|||
request.env['mail.mail'].sudo().create(email_values).send() |
|||
values = ({ |
|||
'bid_placed': 'Bid Placed', |
|||
'auction': auction |
|||
}) |
|||
return values |
|||
|
|||
@http.route('/bidders/<model("product.template"):product_id>', type='http', |
|||
auth='user', csrf=False, website=True) |
|||
def bidders(self, product_id): |
|||
""" |
|||
This method is used to fetch the details of the bidders participating in |
|||
an auction and render them on the website. |
|||
Args: |
|||
product_id: A product template model object. |
|||
Returns: |
|||
A rendered HTML template with information about the bidders in the |
|||
auction.""" |
|||
auction = request.env['website.bargain'].sudo().search( |
|||
[('product_id', '=', product_id.id), ('state', '=', 'running')]) |
|||
bidders_information = request.env['bargain.information'].sudo().search( |
|||
[('auction_id', '=', auction.id)], |
|||
order='bid_offer desc') |
|||
values = ({ |
|||
'bidders_information': bidders_information, |
|||
'product_id': product_id, |
|||
}) |
|||
return request.render('website_bargain.bidders_information', values) |
|||
|
|||
@http.route('/bid/cancel/<model("bargain.information"):bidders>', |
|||
type='http', auth='user', csrf='false') |
|||
def bid_cancel(self, bidders): |
|||
"""This function is for cancel the bid |
|||
Args: |
|||
bidders:Bidders name will be getting here |
|||
Returns:It returns previous page""" |
|||
bidders.status = 'cancelled' |
|||
previous_web_url = request.httprequest.headers.get('referer') |
|||
return request.redirect(previous_web_url) |
|||
|
|||
@http.route('/shop/sale/order', type='json', auth='public', website=True, |
|||
csrf=False) |
|||
def winner_sale_order(self, auction_id, **post): |
|||
""" |
|||
This route creates a draft sale order for the winner of an auction |
|||
and sends notifications for winning and losing. |
|||
Args: |
|||
auction_id: the ID of the auction obtained from the frontend |
|||
post: used to get data of product from frontend |
|||
Returns: |
|||
True""" |
|||
# Get the ID of the product from the post data |
|||
product_product_id = post.get('product_product_id') |
|||
# Find the auction with the given ID |
|||
auction = request.env['website.bargain'].sudo().browse(int(auction_id)) |
|||
# Find the highest bidder for the auction |
|||
bid_record = auction.bargain_information_ids.filtered( |
|||
lambda r: r.status == 'Bid Placed').sorted( |
|||
key=lambda r: r.bid_offer)[-1] |
|||
# Create a draft sale order for the winner |
|||
sale_order = request.env['sale.order'].sudo().create({ |
|||
'partner_id': bid_record.bidder_id.id, |
|||
'state': 'draft', |
|||
}) |
|||
# Add the product to the sale order and set the price to the bid offer |
|||
sale_order.sudo().write({ |
|||
'order_line': [(0, 0, { |
|||
'product_id': int(product_product_id), |
|||
'product_uom_qty': 1, |
|||
'price_unit': bid_record.bid_offer, |
|||
'name': 'auction won', |
|||
})] |
|||
}) |
|||
mail_compose_message = request.env['mail.compose.message'] |
|||
so_mcm_vals = sale_order.sudo().action_quotation_send().get('context', |
|||
{}) |
|||
compose_msg = mail_compose_message.sudo().with_context( |
|||
so_mcm_vals).create({}) |
|||
compose_msg.sudo()._onchange_template_id_wrapper() |
|||
compose_msg.sudo().action_send_mail() |
|||
# Send a notification email to the winner and/or losers, if enabled |
|||
if auction.is_winner_notification: |
|||
data = "You have won in " + auction.name + " Kindly pay now and" \ |
|||
" collect the product " \ |
|||
"from our website" |
|||
email_values = { |
|||
'email_from': auction.auction_manager_id.email, |
|||
'subject': 'Won ' + auction.name, |
|||
'email_to': bid_record.bidder_id.email, |
|||
'body_html': data |
|||
} |
|||
request.env['mail.mail'].sudo().create(email_values).send() |
|||
if auction.is_loser_notification: |
|||
data = "You have lost in " + auction.name + "Better luck next time"\ |
|||
" thank you for your " \ |
|||
"effort and time" |
|||
email_to = '' |
|||
for record in auction.bargain_information_ids: |
|||
if record.bidder_id.id != bid_record.bidder_id.id: |
|||
email_to += record.bidder_id.email + ',' |
|||
email_values = { |
|||
'email_from': auction.auction_manager_id.email, |
|||
'subject': 'Lost ' + auction.name, |
|||
'email_to': email_to, |
|||
'body_html': data |
|||
} |
|||
request.env['mail.mail'].sudo().create(email_values).send() |
|||
return True |
|||
|
|||
@http.route('/subscribe/bid', type='json', auth='user', csrf=False) |
|||
def subscribe(self, auction_id, **post): |
|||
""" |
|||
Endpoint to manage subscription to an auction |
|||
auction_id: integer ID of the auction being subscribed to/unsubscribed |
|||
text: string indicating whether the user is subscribing or |
|||
unsubscribing ('subscribe' or 'unsubscribe') |
|||
return: string message indicating success or failure of |
|||
subscription/unsubscription action |
|||
""" |
|||
text = post.get('text') |
|||
auction = request.env['website.bargain'].sudo().browse(int(auction_id)) |
|||
if text == 'subscribe': |
|||
if request.env.user.partner_id in \ |
|||
auction.bargain_subscribers_ids.subscriber_id: |
|||
return 'You have already subscribed' |
|||
auction.bargain_subscribers_ids.sudo().create({ |
|||
'subscriber_id': request.env.user.partner_id.id, |
|||
'auction_id': auction.id, |
|||
}) |
|||
return 'You have been successfully subscribed to this auction' |
|||
elif text == 'unsubscribe': |
|||
auction.bargain_subscribers_ids.sudo().search( |
|||
[('subscriber_id', '=', request.env.user.partner_id.id), |
|||
('auction_id', '=', auction.id)]).unlink() |
|||
return 'Unsubscribed successfully' |
|||
|
|||
@http.route('/buy/now', type='json', auth='public', website=True, |
|||
csrf=False) |
|||
def buy_now(self, auction_id, product_id): |
|||
""" |
|||
Args: |
|||
auction_id: the ID of the auction obtained from the frontend |
|||
product_id: the ID of the product used to get data from the frontend |
|||
""" |
|||
# Find the auction with the given ID |
|||
auction = request.env['website.bargain'].sudo().browse(int(auction_id)) |
|||
# Create a draft sale order for the winner |
|||
sale_order = request.env['sale.order'].sudo().create({ |
|||
'partner_id': request.env.user.partner_id.id, |
|||
'state': 'draft', |
|||
}) |
|||
sale_order.sudo().write({ |
|||
'order_line': [(0, 0, { |
|||
'product_id': int(product_id), |
|||
'product_uom_qty': 1, |
|||
'name': '(auction won)' + auction.name, |
|||
'price_unit': auction.price_buy_now, |
|||
})] |
|||
}) |
|||
# Send a notification email to the winner |
|||
mail_compose_message = request.env['mail.compose.message'] |
|||
so_mcm_vals = sale_order.sudo().action_quotation_send().get('context', |
|||
{}) |
|||
compose_msg = mail_compose_message.sudo().with_context( |
|||
so_mcm_vals).create({}) |
|||
compose_msg.sudo()._onchange_template_id_wrapper() |
|||
compose_msg.sudo().action_send_mail() |
@ -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,6 @@ |
|||
## Module <website_bargain> |
|||
|
|||
#### 21.11.2023 |
|||
#### Version 16.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) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Mruthul Raj (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from . import bargain_information |
|||
from . import bargain_subscribers |
|||
from . import bargain_template |
|||
from . import product_template |
|||
from . import website_bargain |
@ -0,0 +1,45 @@ |
|||
"""bidders information and functions""" |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Mruthul Raj (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from odoo import fields, models |
|||
|
|||
|
|||
class BargainInformation(models.Model): |
|||
"""Class for adding bidder details to the database""" |
|||
_name = 'bargain.information' |
|||
_rec_name = 'auction_id' |
|||
_description = "Bidder Details" |
|||
_inherit = ['mail.thread', 'mail.activity.mixin'] |
|||
|
|||
bidder_id = fields.Many2one('res.partner', string='Bidder', required=True, |
|||
help="Bidders details") |
|||
auction_id = fields.Many2one('website.bargain', string='Auction', |
|||
required=True, help="Auction Details") |
|||
currency_id = fields.Many2one(related="auction_id.currency_id", |
|||
help="Currency Details") |
|||
bid_offer = fields.Monetary(string="Bid Offer", |
|||
currency_field='currency_id', |
|||
help="Offered amount") |
|||
status = fields.Char(string="Status", readonly=True, |
|||
help="Current Status of bid") |
|||
product_id = fields.Many2one(related='auction_id.product_id', |
|||
string='Product', help="Product details") |
@ -0,0 +1,44 @@ |
|||
"""subscribers class and its functions""" |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Mruthul Raj (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from odoo import fields, models |
|||
|
|||
|
|||
class BargainSubscribers(models.Model): |
|||
"""Model for adding the subscriber details """ |
|||
_name = 'bargain.subscribers' |
|||
_inherit = ['mail.thread', 'mail.activity.mixin'] |
|||
_description = "Subscriber details" |
|||
|
|||
subscriber_id = fields.Many2one('res.partner', required=True, |
|||
help="Subscribers id will be here ") |
|||
name = fields.Char(related='subscriber_id.name', string='Name', |
|||
readonly=False, help="Subscribers name", |
|||
required=True) |
|||
email = fields.Char(related='subscriber_id.email', string='Email', |
|||
readonly=False, help="Subscribers email") |
|||
auction_id = fields.Many2one('website.bargain', string='Auction', |
|||
required=True, help="Auction details") |
|||
subscribe_time = fields.Datetime(string='Subscribe On', |
|||
default=fields.Datetime.today(), |
|||
readonly=True, |
|||
help="Time of subscription") |
@ -0,0 +1,37 @@ |
|||
"""website bargains template and its functions""" |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Mruthul Raj (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from odoo import fields, models |
|||
|
|||
|
|||
class BargainTemplate(models.Model): |
|||
"""Model for auction template""" |
|||
|
|||
_name = 'bargain.template' |
|||
_inherit = ['mail.thread', 'mail.activity.mixin'] |
|||
_description = "Bargain Template" |
|||
|
|||
name = fields.Char(string='Template Name', help="Name of the template") |
|||
product_id = fields.Many2one('product.template', |
|||
domain=[('is_published', '=', True)], |
|||
required=True, |
|||
help="Choose the product from the list") |
@ -0,0 +1,32 @@ |
|||
"""Product template inherit """ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Mruthul Raj (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from odoo import fields, models |
|||
|
|||
|
|||
class ProductTemplateInherit(models.Model): |
|||
"""Model to add a new boolean field to product template""" |
|||
_inherit = 'product.template' |
|||
|
|||
is_auction = fields.Boolean(string='Auction On', readonly=True, |
|||
help="If auction is on this field will be true" |
|||
) |
@ -0,0 +1,301 @@ |
|||
"""Auction main page""" |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Mruthul Raj (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from datetime import timedelta |
|||
from odoo import api, fields, models, _ |
|||
from odoo.exceptions import ValidationError |
|||
|
|||
|
|||
class WebsiteBargain(models.Model): |
|||
"""This is the main class of website bargain where all the details are |
|||
stored in this model |
|||
_onchange_template_id: |
|||
function for automatically add the auction name |
|||
_check_end_date: |
|||
function to validate the end date if it is higher than the start |
|||
date |
|||
_check_extend_time: |
|||
function to validate extended time weather it is greater than end |
|||
time and after saving will send notification to subscribers if |
|||
enabled |
|||
action_confirm: |
|||
button function to confirm auction and will make product as |
|||
published |
|||
action_reset_to_draft: |
|||
button function to reset the auction to draft |
|||
action_run_auction: |
|||
button function to start auction manually |
|||
action_complete: |
|||
button function to end auction manually |
|||
action_close: |
|||
button function to close auction |
|||
send_email_notification: |
|||
Function for sending auction notification for admin |
|||
before ending if enabled |
|||
auction_auto_start: |
|||
Cron function for auction auto start when its start |
|||
time and also will send notification to customers about auction |
|||
""" |
|||
_name = 'website.bargain' |
|||
_description = "Website Bargain" |
|||
_inherit = ['mail.thread', 'mail.activity.mixin'] |
|||
|
|||
website_id = fields.Many2one('website', string='Website', required=True, |
|||
help="Add website here to put auction") |
|||
template_id = fields.Many2one('bargain.template', string='Template', |
|||
help="add already created templates of " |
|||
"auction with products") |
|||
auction_manager_id = fields.Many2one('res.users', string="Auction Manager", |
|||
help="Set suction manager here", |
|||
required=True) |
|||
product_id = fields.Many2one(related='template_id.product_id', store=True, |
|||
string='Product', readonly=False, |
|||
help="Select the product", required=True) |
|||
name = fields.Char(string='Auction Name', help="Auctions name") |
|||
currency_id = fields.Many2one('res.currency', 'Currency', |
|||
default=lambda |
|||
self: self.env.user.company_id.currency_id.id, |
|||
required=True, |
|||
help="if you select this " |
|||
"currency bidding will " |
|||
"be on that currency itself") |
|||
initial_price = fields.Monetary(string='Initial Price', |
|||
currency_field='currency_id', |
|||
required=True, |
|||
help="Minimum amount required to bid") |
|||
is_buy_now = fields.Boolean(string='Provide buy now button', |
|||
help='Enable a button for buying instantly') |
|||
price_buy_now = fields.Monetary(string='Buy Now Price', |
|||
currency_field='currency_id', |
|||
help="Price of the product if its" |
|||
" immediately buying") |
|||
start_time = fields.Datetime(string='Start Date Time', required=True, |
|||
default=fields.Datetime.today(), |
|||
help="Auction start time") |
|||
end_time = fields.Datetime(string='End Date Time', required=True, |
|||
help="Auction start time") |
|||
extend_time = fields.Datetime(string="Extended Time", |
|||
help="By setting days you can " |
|||
"extend the auction") |
|||
state = fields.Selection( |
|||
[('draft', "Draft"), ('confirmed', "Confirmed"), |
|||
('running', "Running"), |
|||
('closed', "Closed"), ('finished', "Finished"), |
|||
('soldout', "Sold Out")], default='draft') |
|||
bargain_information_ids = fields.One2many('bargain.information', |
|||
'auction_id', readonly=True) |
|||
bargain_subscribers_ids = fields.One2many('bargain.subscribers', |
|||
'auction_id') |
|||
is_activate = fields.Boolean(string='Activate', |
|||
help='this will activate ' |
|||
'notification for the admins') |
|||
notify_on = fields.Integer(string='Notify before', default='5', |
|||
help="Set notification time here") |
|||
notify_selection = fields.Selection( |
|||
[('days', "Days"), ('hours', "Hours"), ('minutes', "Minutes"), |
|||
('seconds', "Seconds")], default='minutes') |
|||
is_notification_send = fields.Boolean(string='Notification Send', |
|||
help='If notification send manually ' |
|||
'you can enable this field ' |
|||
'to restrict ' |
|||
'sending notification before ' |
|||
'the time added') |
|||
is_winner_notification = fields.Boolean( |
|||
string='Send Notification to Winner', |
|||
help='Enable this option to send notification to the winner') |
|||
is_loser_notification = fields.Boolean(string='Send Notification to Loser', |
|||
help='Enable this option to send ' |
|||
'notification to the losers') |
|||
is_subscriber_start_notification = fields.Boolean(string='Bidding Start', |
|||
help="Send subscribers " |
|||
"the bidding start " |
|||
"notification") |
|||
is_extend_auction_notification = fields.Boolean(string='Auction Extended', |
|||
help="Send subscribers the" |
|||
"bidding extended " |
|||
"notification") |
|||
is_new_bid_notification = fields.Boolean(string='New Bid Placed', |
|||
help="Send subscribers " |
|||
"notifications if new bids" |
|||
" are placed") |
|||
is_bid_end_notification = fields.Boolean(string='Auction Finished', |
|||
help="Send subscribers " |
|||
"notifications if bidding " |
|||
"is over") |
|||
product_img = fields.Binary(related="product_id.image_1920") |
|||
product_description = fields.Text(related="product_id.description_sale", |
|||
string="Auction Product Description") |
|||
|
|||
@api.onchange('template_id', 'product_id') |
|||
def _onchange_template_id(self): |
|||
"""summary: |
|||
function to add name automatically""" |
|||
if self.product_id: |
|||
self.name = f"Auction for {self.product_id.name}" |
|||
|
|||
@api.constrains('end_time', 'start_time') |
|||
def _check_end_date(self): |
|||
""" |
|||
Summary: |
|||
start and end date validation function |
|||
""" |
|||
if self.end_time <= self.start_time: |
|||
raise ValidationError( |
|||
_('End time should be greater than start time')) |
|||
|
|||
@api.constrains('extend_time') |
|||
def _check_extend_time(self): |
|||
"""Summary: |
|||
function to validate extended time weather it is greater than |
|||
end time and after saving will send notification to subscribers |
|||
if enabled""" |
|||
if self.extend_time: |
|||
if self.extend_time <= self.end_time: |
|||
raise ValidationError( |
|||
_('This time is not greater than the old time(' + str( |
|||
self.end_time) + ')')) |
|||
if self.is_extend_auction_notification: |
|||
template_id = self.env.ref( |
|||
'website_bargain.email_template_auction_extended') |
|||
email_to = '' |
|||
for subscriber in self.bargain_subscribers_ids: |
|||
email_to += subscriber.email + ',' |
|||
template_id.email_to = email_to |
|||
template_id.send_mail(self.id, force_send=True) |
|||
|
|||
def action_confirm(self): |
|||
""" |
|||
Summary: |
|||
button function to confirm auction and will |
|||
make product as published |
|||
""" |
|||
if self.search([('product_id', '=', self.product_id.id), |
|||
('state', '=', 'running')]): |
|||
raise ValidationError( |
|||
_('Already an auction is running for this product please' |
|||
' close it to continue')) |
|||
if self.end_time <= fields.Datetime.today(): |
|||
raise ValidationError(_('End time is already over')) |
|||
self.product_id.is_published = True |
|||
self.product_id.website_id = self.website_id |
|||
self.write({'state': 'confirmed'}) |
|||
|
|||
def action_reset_to_draft(self): |
|||
""" |
|||
Summary: |
|||
button function to reset the auction to draft |
|||
""" |
|||
self.product_id.is_auction = False |
|||
self.write({'state': 'draft'}) |
|||
|
|||
def action_run_auction(self): |
|||
""" |
|||
Summary: |
|||
button function to start auction manually |
|||
""" |
|||
if self.search([('product_id', '=', self.product_id.id), |
|||
('state', '=', 'running')]): |
|||
raise ValidationError( |
|||
_('Already an auction is running for this product ' |
|||
'please close it to continue')) |
|||
self.product_id.is_auction = True |
|||
self.write({'state': 'running'}) |
|||
|
|||
def action_complete(self): |
|||
""" |
|||
Summary: |
|||
button function to end auction manually |
|||
""" |
|||
self.product_id.is_auction = False |
|||
self.product_id.is_published = False |
|||
self.write({'state': 'finished'}) |
|||
|
|||
def action_close(self): |
|||
""" |
|||
Summary: |
|||
button function to close auction |
|||
""" |
|||
self.product_id.is_auction = False |
|||
self.product_id.is_published = False |
|||
self.write({'state': 'closed'}) |
|||
|
|||
def send_email_notification(self): |
|||
""" |
|||
Summary: |
|||
Function for sending auction notification for admin e ending if |
|||
enabled |
|||
""" |
|||
# Get the email template for the admin notification |
|||
template_id = self.env.ref( |
|||
'website_bargain.admin_email_template') |
|||
# Find all running auctions that have notification enabled and have |
|||
# not been sent yet |
|||
auctions = self.search([('state', '=', 'running'), |
|||
('is_activate', '=', True), |
|||
('notify_on', '>', 0), |
|||
('is_notification_send', '=', False)]) |
|||
# Loop through the auctions that need to be notified |
|||
for auction in auctions: |
|||
# Map the time unit to a string for timedelta |
|||
time_unit_map = {'days': 'days', 'hours': 'hours', |
|||
'minutes': 'minutes', 'seconds': 'seconds'} |
|||
time_unit = time_unit_map.get(auction.notify_selection) |
|||
# Check if it's time to send the notification |
|||
if time_unit: |
|||
next_notification = auction.end_time - timedelta( |
|||
**{time_unit: auction.notify_on}) |
|||
if next_notification <= fields.Datetime.today(): |
|||
# Send the notification email and set the flag to True |
|||
template_id.send_mail(auction.id, force_send=True) |
|||
auction.is_notification_send = True |
|||
|
|||
def auction_auto_start(self): |
|||
""" |
|||
Summary: |
|||
Cron function for auction auto start when its start |
|||
time and also will send notification to customers about auction |
|||
""" |
|||
# Get all confirmed auctions |
|||
auctions = self.search([('state', '=', 'confirmed')]) |
|||
# Get the email template for auction start notification |
|||
template_id = self.env.ref( |
|||
'website_bargain.email_template_auction_start') |
|||
# Get the emails of all the bidders and sale order partners |
|||
bidders = self.env['bargain.information'].search([]).mapped( |
|||
'bidder_id.email') |
|||
sale_orders_partner = self.env['sale.order'].search( |
|||
[('state', '=', 'sale')]).mapped('partner_id.email') |
|||
# Loop through the auctions and check if any auction's start time has arrived |
|||
for auction in auctions: |
|||
if auction.start_time <= fields.Datetime.today(): |
|||
# Set the product as an auction and update the website |
|||
auction.product_id.is_auction = True |
|||
auction.product.website_id = auction.website_id |
|||
auction.write({'state': 'running'}) |
|||
# Send email notifications to all the bidders and sale order partners |
|||
email_to = "" |
|||
for partner in sale_orders_partner: |
|||
email_to += partner + ',' |
|||
for bidder in bidders: |
|||
email_to += bidder + ',' |
|||
template_id.email_to = email_to |
|||
template_id.send_mail(auction.id, force_send=True) |
|
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: 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: 33 KiB |
After Width: | Height: | Size: 74 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 186 KiB |
After Width: | Height: | Size: 95 KiB |
After Width: | Height: | Size: 252 KiB |
After Width: | Height: | Size: 160 KiB |
After Width: | Height: | Size: 162 KiB |
After Width: | Height: | Size: 312 KiB |
After Width: | Height: | Size: 286 KiB |
After Width: | Height: | Size: 188 KiB |
After Width: | Height: | Size: 140 KiB |
After Width: | Height: | Size: 172 KiB |
After Width: | Height: | Size: 122 KiB |
After Width: | Height: | Size: 97 KiB |
After Width: | Height: | Size: 11 KiB |
@ -0,0 +1,695 @@ |
|||
<div style="background-color: #714B67; height: 810px; width: 100%; padding: 15px; position: relative;"> |
|||
<!-- TITLE BAR --> |
|||
<div class="d-flex align-items-center justify-content-between" |
|||
style="border-bottom: 1px solid #875A7B; padding: 15px; display: flex; justify-content: space-between; align-items: center;"> |
|||
<img src="assets/misc/cybrosys-logo.png" width="42" height="42" |
|||
style="width: 42px; height: 42px;"/> |
|||
<div> |
|||
<div |
|||
style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;" |
|||
class="mr-2"> |
|||
<i class="fa fa-check mr-1"></i>Community |
|||
</div> |
|||
<div |
|||
style="color: #017E84; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;" |
|||
class="mr-2"> |
|||
<i class="fa fa-check mr-1"></i>Odoo.sh |
|||
</div> |
|||
<div |
|||
style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;" |
|||
class="mr-2"> |
|||
<i class="fa fa-check mr-1"></i>Enterprise |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- END OF TITLE BAR --> |
|||
<div class="container"> |
|||
<div class="row"> |
|||
<div class="col-sm-12 col-md-12 col-lg-12"> |
|||
<!-- APP HERO --> |
|||
<h1 style="color: #FFFFFF; font-weight: bolder; font-size: 50px; text-align: center; margin-top: 50px;"> |
|||
Product Bidding In ECommerce</h1> |
|||
<p style="color:#FFFFFF; padding: 8px 15px; text-align: center; font-size: 24px;"> |
|||
Bid For Products In Odoo </p> |
|||
<!-- END OF APP HERO --> |
|||
<img src="assets/screenshots/hero.gif" class="img-responsive" |
|||
style="width: 100%; margin-left: auto; margin-right: auto;"/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- NAVIGATION SECTION --> |
|||
<div class="d-flex align-items-center" |
|||
style="border-bottom: 2px solid #714B67; padding: 15px 0px; margin-top: 300px;"> |
|||
<div class="d-flex justify-content-center align-items-center mr-2" |
|||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> |
|||
<img src="assets/misc/compass.png"/> |
|||
</div> |
|||
<h2 class="mt-2" |
|||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
|||
Explore This |
|||
Module</h2> |
|||
</div> |
|||
<div class="row my-4" style="font-family: 'Montserrat', sans-serif;"> |
|||
<div class="col-sm-12 col-md-6 my-3"> |
|||
<a href="#overview"> |
|||
<div class="d-flex justify-content-between align-items-center" |
|||
style="background-color: #f5f5f5; padding: 30px; width: 100%;"> |
|||
<div> |
|||
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Overview</span> |
|||
<span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">Learn |
|||
more about this |
|||
module</span> |
|||
</div> |
|||
<img src="assets/misc/right-arrow.png" width="36" height="36"/> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-sm-12 col-md-6 my-3"> |
|||
<a href="#features"> |
|||
<div class="d-flex justify-content-between align-items-center" |
|||
style="background-color: #f5f5f5; padding: 30px; width: 100%;"> |
|||
<div> |
|||
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Features</span> |
|||
<span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">View |
|||
features of this |
|||
module</span> |
|||
</div> |
|||
<img src="assets/misc/right-arrow.png" width="36" height="36"/> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-sm-12 col-md-6 my-3"> |
|||
<a href="#screenshots"> |
|||
<div class="d-flex justify-content-between align-items-center" |
|||
style="background-color: #f5f5f5; padding: 30px; width: 100%;"> |
|||
<div> |
|||
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Screenshots</span> |
|||
<span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">View |
|||
screenshots for this |
|||
module</span> |
|||
</div> |
|||
<img src="assets/misc/right-arrow.png" width="36" height="36"/> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<!-- END OF NAVIGATION SECTION --> |
|||
|
|||
<!-- OVERVIEW SECTION --> |
|||
<div class="d-flex align-items-center" |
|||
style="border-bottom: 2px solid #714B67; padding: 15px 0px;" |
|||
id="overview"> |
|||
<div class="d-flex justify-content-center align-items-center mr-2" |
|||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> |
|||
<img src="assets/misc/pie-chart.png"/> |
|||
</div> |
|||
<h2 class="mt-2" |
|||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
|||
Overview |
|||
</h2> |
|||
</div> |
|||
<div class="row" |
|||
style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;"> |
|||
<div class="col-sm-12 py-4"> |
|||
This module provides a bidding system where customers can place their |
|||
bids on |
|||
products, and the highest bidder wins the auction. This module |
|||
integrates seamlessly with the website sale module of Odoo, and it is |
|||
highly configurable to meet the specific needs of each business. |
|||
Additionally, it provides several features such as starting and ending |
|||
dates for auctions, buy now option, and real-time updates for bids. |
|||
</div> |
|||
</div> |
|||
<!-- END OF OVERVIEW SECTION --> |
|||
|
|||
<!-- FEATURES SECTION --> |
|||
<div class="d-flex align-items-center" |
|||
style="border-bottom: 2px solid #714B67; padding: 15px 0px;" |
|||
id="features"> |
|||
<div class="d-flex justify-content-center align-items-center mr-2" |
|||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> |
|||
<img src="assets/misc/features.png"/> |
|||
</div> |
|||
<h2 class="mt-2" |
|||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
|||
Features |
|||
</h2> |
|||
</div> |
|||
<div class="row" |
|||
style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;"> |
|||
<div class="col-sm-12 col-md-6"> |
|||
<div class="d-flex align-items-center" |
|||
style="margin-top: 40px; margin-bottom: 40px"> |
|||
<img src="assets/misc/check-box.png" class="mr-2"/> |
|||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Timer On Product Until End Of Auction.</span> |
|||
</div> |
|||
<div class="d-flex align-items-center" |
|||
style="margin-top: 30px; margin-bottom: 30px"> |
|||
<img src="assets/misc/check-box.png" class="mr-2"/> |
|||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Subscription Available.</span> |
|||
</div> |
|||
<div class="d-flex align-items-center" |
|||
style="margin-top: 30px; margin-bottom: 30px"> |
|||
<img src="assets/misc/check-box.png" class="mr-2"/> |
|||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Different Email Notifications.</span> |
|||
</div> |
|||
<div class="d-flex align-items-center" |
|||
style="margin-top: 30px; margin-bottom: 30px"> |
|||
<img src="assets/misc/check-box.png" class="mr-2"/> |
|||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Option To See Bidders.</span> |
|||
</div> |
|||
</div> |
|||
<div class="d-flex align-items-center" |
|||
style="margin-top: 30px; margin-bottom: 30px"> |
|||
<img src="assets/misc/check-box.png" class="mr-2"/> |
|||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Option For Buy Now.</span> |
|||
</div> |
|||
</div> |
|||
<div class="col-sm-12 col-md-6"> |
|||
<div class="d-flex align-items-center" |
|||
style="margin-top: 30px; margin-bottom: 30px"> |
|||
<img src="assets/misc/check-box.png" class="mr-2"/> |
|||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Available in Odoo 16.0</span> |
|||
</div> |
|||
</div> |
|||
<!-- END OF FEATURES SECTION --> |
|||
|
|||
<!-- SCREENSHOTS SECTION --> |
|||
<div class="d-flex align-items-center" |
|||
style="border-bottom: 2px solid #714B67; padding: 15px 0px;" |
|||
id="screenshots"> |
|||
<div class="d-flex justify-content-center align-items-center mr-2" |
|||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> |
|||
<img src="assets/misc/pictures.png"/> |
|||
</div> |
|||
<h2 class="mt-2" |
|||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
|||
Screenshots |
|||
</h2> |
|||
</div> |
|||
<div class="row"> |
|||
<div class="col-sm-12"> |
|||
|
|||
<div style="display: block; margin: 30px auto;"> |
|||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> |
|||
Auction Home Page |
|||
</h3> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
Website -> |
|||
Auction |
|||
->Auctions |
|||
Here created auction can be seen .</p> |
|||
<img src="assets/screenshots/1.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
Create a Auction and click CONFIRM.</p> |
|||
<img src="assets/screenshots/2.png" class="img-thumbnail"> |
|||
</div> |
|||
|
|||
<div style="display: block; margin: 30px auto;"> |
|||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> |
|||
Run Auction |
|||
</h3> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
Auction will automatically start at the Start Date Time.If you |
|||
want to run manually just click on RUN AUCTION Button</p> |
|||
<img src="assets/screenshots/3.png" |
|||
class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> |
|||
Product inProduct List |
|||
</h3> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
Customes can see AUCTION ON on that product.</p> |
|||
<img src="assets/screenshots/4.png" |
|||
class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> |
|||
Product in Website |
|||
</h3> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
This will be the product view in website.</p> |
|||
<img src="assets/screenshots/5.png" |
|||
class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> |
|||
Subscribers </h3> |
|||
<img src="assets/screenshots/6.png" |
|||
class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> |
|||
Bidders </h3> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
This will be the bidders view in website.</p> |
|||
<img src="assets/screenshots/7.png" |
|||
class="img-thumbnail"> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
View in backend.</p> |
|||
<img src="assets/screenshots/bidders_backend.png" |
|||
class="img-thumbnail"> |
|||
</div> |
|||
|
|||
</div> |
|||
</div> |
|||
<!-- END OF SCREENSHOTS SECTION --> |
|||
|
|||
<div class="d-flex align-items-center" |
|||
style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> |
|||
<div class="d-flex justify-content-center align-items-center mr-2" |
|||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> |
|||
<img src="assets/misc/categories.png"/> |
|||
</div> |
|||
<h2 class="mt-2" |
|||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
|||
Related |
|||
Products |
|||
</h2> |
|||
</div> |
|||
<div class="row"> |
|||
<div class="col-sm-12"> |
|||
<div id="demo1" class="row carousel slide" data-ride="carousel"> |
|||
<!-- The slideshow --> |
|||
<div class="carousel-inner" style="padding: 30px;"> |
|||
<div class="carousel-item" style="min-height: 198.656px;"> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" |
|||
style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/16.0/odoo_website_helpdesk/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-radius: 0px;" |
|||
src="assets/modules/1.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" |
|||
style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/16.0/customer_geolocation/#" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-radius: 0px;" |
|||
src="assets/modules/2.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" |
|||
style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/16.0/website_product_attachments/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-radius: 0px;" |
|||
src="assets/modules/3.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div class="carousel-item active" |
|||
style="min-height: 198.656px;"> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" |
|||
style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/16.0/animated_snippet/#" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-radius: 0px;" |
|||
src="assets/modules/4.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" |
|||
style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/16.0/education_student_portal/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-radius: 0px;" |
|||
src="assets/modules/5.jpg"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" |
|||
style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/16.0/website_pdf_preview_snippet/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-radius: 0px;" |
|||
src="assets/modules/6.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- Left and right controls --> |
|||
<a class="carousel-control-prev" href="#demo1" data-slide="prev" |
|||
style="width:35px; color:#000"> <span |
|||
class="carousel-control-prev-icon"><i |
|||
class="fa fa-chevron-left" |
|||
style="font-size:24px"></i></span> |
|||
</a> <a class="carousel-control-next" href="#demo1" |
|||
data-slide="next" style="width:35px; color:#000"> |
|||
<span class="carousel-control-next-icon"><i |
|||
class="fa fa-chevron-right" |
|||
style="font-size:24px"></i></span> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- END OF RELATED PRODUCTS --> |
|||
|
|||
<!-- OUR SERVICES --> |
|||
|
|||
<div class="d-flex align-items-center" |
|||
style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> |
|||
<div class="d-flex justify-content-center align-items-center mr-2" |
|||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> |
|||
<img src="assets/misc/star.png"/> |
|||
</div> |
|||
<h2 class="mt-2" |
|||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
|||
Our Services |
|||
</h2> |
|||
</div> |
|||
|
|||
<div class="container my-5"> |
|||
<div class="row"> |
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #1dd1a1 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/cogs.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Customization</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #ff6b6b !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/wrench.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Implementation</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #6462CD !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/lifebuoy.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Support</h6> |
|||
</div> |
|||
|
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #ffa801 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/user.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Hire |
|||
Odoo |
|||
Developer</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #54a0ff !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/puzzle.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Integration</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #6d7680 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/update.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Migration</h6> |
|||
</div> |
|||
|
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #786fa6 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/consultation.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Consultancy</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #f8a5c2 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/training.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Implementation</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #e6be26 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/license.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Licensing Consultancy</h6> |
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
<!-- END OF OUR SERVICES --> |
|||
|
|||
<!-- OUR INDUSTRIES --> |
|||
|
|||
<div class="d-flex align-items-center" |
|||
style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> |
|||
<div class="d-flex justify-content-center align-items-center mr-2" |
|||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> |
|||
<img src="assets/misc/corporate.png"/> |
|||
</div> |
|||
<h2 class="mt-2" |
|||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
|||
Our |
|||
Industries |
|||
</h2> |
|||
</div> |
|||
|
|||
<div class="container my-5"> |
|||
<div class="row"> |
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="assets/icons/trading-black.png" |
|||
class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Trading |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Easily procure |
|||
and |
|||
sell your products</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="assets/icons/pos-black.png" |
|||
class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
POS |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Easy |
|||
configuration |
|||
and convivial experience</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="assets/icons/education-black.png" |
|||
class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Education |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
A platform for |
|||
educational management</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="assets/icons/manufacturing-black.png" |
|||
class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Manufacturing |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Plan, track and |
|||
schedule your operations</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="assets/icons/ecom-black.png" |
|||
class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
E-commerce & Website |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Mobile |
|||
friendly, |
|||
awe-inspiring product pages</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="assets/icons/service-black.png" |
|||
class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Service Management |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Keep track of |
|||
services and invoice</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="assets/icons/restaurant-black.png" |
|||
class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Restaurant |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Run your bar or |
|||
restaurant methodically</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="assets/icons/hotel-black.png" |
|||
class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Hotel Management |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
An |
|||
all-inclusive |
|||
hotel management application</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- END OF OUR INDUSTRIES --> |
|||
|
|||
<!-- SUPPORT --> |
|||
<div class="d-flex align-items-center" |
|||
style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> |
|||
<div class="d-flex justify-content-center align-items-center mr-2" |
|||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> |
|||
<img src="assets/misc/customer-support.png"/> |
|||
</div> |
|||
<h2 class="mt-2" |
|||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
|||
Support |
|||
</h2> |
|||
</div> |
|||
<div class="container mt-5"> |
|||
<div class="row"> |
|||
<div class="col-sm-12 col-md-6"> |
|||
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;"> |
|||
<div class="mr-4 d-flex justify-content-center align-items-center" |
|||
style="background-color: #714B67; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;"> |
|||
<img src="assets/misc/support.png" height="48" width="48" |
|||
style="width: 42px; height: 42px;"/> |
|||
</div> |
|||
<div> |
|||
<h4>Need Help?</h4> |
|||
<p style="line-height: 100%;">Got questions or need help? |
|||
Get in touch.</p> |
|||
<a href="mailto:odoo@cybrosys.com"> |
|||
<p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;"> |
|||
odoo@cybrosys.com</p> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-sm-12 col-md-6"> |
|||
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;"> |
|||
<div class="mr-4 d-flex justify-content-center align-items-center" |
|||
style="background-color: #2AC44D; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;"> |
|||
<img src="assets/misc/whatsapp.png" height="52" width="52" |
|||
style="width: 52px; height: 52px;"/> |
|||
</div> |
|||
<div> |
|||
<h4>WhatsApp</h4> |
|||
<p style="line-height: 100%;">Say hi to us on WhatsApp!</p> |
|||
<a href="https://api.whatsapp.com/send?phone=918606827707"> |
|||
<p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;"> |
|||
+91 86068 |
|||
27707</p> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="row"> |
|||
<div class="col-sm-12 my-5 d-flex justify-content-center align-items-center"> |
|||
<img src="assets/misc/logo.png" width="144" height="31" |
|||
style="width:144px; height: 31px; margin-top: 40px;"/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- END OF SUPPORT --> |
@ -0,0 +1,66 @@ |
|||
p { |
|||
font - size: 16 px; |
|||
line - height: 1.5; |
|||
} |
|||
#subscribe_bid { |
|||
color: #007bff; |
|||
text-decoration:none; |
|||
font-weight:bold; |
|||
} |
|||
#subscribe_bid:hover{ |
|||
cursor:pointer; |
|||
transform:scale(1.2); |
|||
} |
|||
|
|||
#bidder_information{ |
|||
width:100%; |
|||
border-collapse:collapse; |
|||
} |
|||
#bidder_information th,td{ |
|||
padding:8px; |
|||
text-align:left; |
|||
border-bottom:1px solid #ddd; |
|||
} |
|||
#bidder_information thead th{ |
|||
position:sticky; |
|||
top:0; |
|||
background-color:#f5f5f5; |
|||
} |
|||
#bidder_information tbody{ |
|||
height:200px; |
|||
overflow-y:scroll; |
|||
} |
|||
#auction_bidders{ |
|||
padding-left:60px; |
|||
color: #007bff; |
|||
} |
|||
#auction_bidders:hover{ |
|||
cursor:pointer; |
|||
transform:scale(1.2); |
|||
} |
|||
#bid_amount{ |
|||
max-width:10rem; |
|||
font-size:16px; |
|||
} |
|||
.auction_timer{ |
|||
border: 2px solid #ccc; |
|||
border-radius:6px; |
|||
padding:20px; |
|||
display: inline-block; |
|||
background:#dbdbdb4a; |
|||
} |
|||
.auction_timer:hover{ |
|||
transform:scale(1.2); |
|||
} |
|||
#timer{ |
|||
font-size: 24px; |
|||
font-weight: bold; |
|||
color: #333; |
|||
background-color: #f5f5f5; |
|||
} |
|||
.auction_min_amount{ |
|||
padding: 10px; |
|||
} |
|||
.alert { |
|||
display: none; |
|||
} |
@ -0,0 +1,246 @@ |
|||
/** @odoo-module **/ |
|||
import { WebsiteSale } from 'website_sale.website_sale' |
|||
var rpc = require('web.rpc'); |
|||
var ajax = require('web.ajax'); |
|||
/**This is a JavaScript code written for the Odoo e-commerce platform. |
|||
It extends the functionality of the WebsiteSale module by adding an auction |
|||
feature, allowing customers to bid on products, and setting up a timer to track |
|||
the duration of the auction.**/ |
|||
WebsiteSale.include({ |
|||
/**The start function initializes the auction timer when the page is loaded. |
|||
It first checks if there are any ongoing auctions and hides the |
|||
"add to cart" button if the product is being auctioned. Then, it retrieves |
|||
the product and auction IDs from the input fields, sends an AJAX request to |
|||
the server to fetch the auction details, and calculates the time remaining |
|||
until the auction ends. If the auction has ended, the function redirects |
|||
the user to the shop page, and if not, it sets up an interval to update |
|||
the timer every second.**/ |
|||
start: function() { |
|||
/** function to add timer and check the time **/ |
|||
this._super(...arguments); |
|||
var modal_title = this.$('#modal_title')[0] |
|||
var modal_message = this.$('#modal_message')[0] |
|||
let auctionText = this.$('#modal_message')[0] |
|||
if (auctionText) { |
|||
$.each($('.o_wsale_product_btn'), (key, values) => { |
|||
if (values.nextElementSibling.innerHTML == 'AUCTION ON') { |
|||
values.style.display = "none" |
|||
} |
|||
}) |
|||
} |
|||
let product_id = this.$('input[name="auction_product_id"]').val(); |
|||
let auction_id = this.$('input[name="auction_id"]').val(); |
|||
let timerId; // variable to hold the ID of the interval timer
|
|||
if (product_id) { |
|||
let product_product_id = this.$('input[name="product_product_id"]').val() |
|||
ajax.jsonRpc('/auction/timer', 'call', { |
|||
'product_id': product_id, |
|||
'auction_id': auction_id |
|||
}).then((data) => { |
|||
if (new Date() > new Date(data['end_time'])) { |
|||
if (data['extend_time']) { |
|||
if (new Date() > new Date(data['extend_time'])) { |
|||
ajax.jsonRpc('/auction/close', 'call', { |
|||
'product_id': product_id, |
|||
'auction_id': auction_id |
|||
}).then(() => { |
|||
ajax.jsonRpc('/shop/sale/order', 'call', { |
|||
'product_product_id': product_product_id, |
|||
'product_id': product_id, |
|||
'auction_id': auction_id |
|||
}) |
|||
}) |
|||
window.location.href = '/shop' |
|||
} |
|||
} else { |
|||
ajax.jsonRpc('/auction/close', 'call', { |
|||
'product_id': product_id, |
|||
'auction_id': auction_id |
|||
}).then(() => { |
|||
ajax.jsonRpc('/shop/sale/order', 'call', { |
|||
'product_product_id': product_product_id, |
|||
'product_id': product_id, |
|||
'auction_id': auction_id |
|||
}) |
|||
}) |
|||
window.location.href = '/shop' |
|||
} |
|||
} else { |
|||
timerId = setInterval(function() { |
|||
var time_key = data['extend_time'] ? 'extend_time' : 'end_time' |
|||
var time_remaining = new Date(data[time_key]) - new Date() |
|||
var days = Math.floor(time_remaining / (1000 * 60 * 60 * 24)); |
|||
var hours = Math.floor((time_remaining / (1000 * 60 * 60)) % 24); |
|||
var minutes = Math.floor((time_remaining / (1000 * 60)) % 60); |
|||
var seconds = Math.floor((time_remaining / 1000) % 60); |
|||
if (document.getElementById('timer')) { |
|||
document.getElementById('timer').innerHTML = days + "d." + " " + hours + "h." + " " + minutes + "m." + " " + seconds + "s." |
|||
} |
|||
if (time_remaining <= 0) { |
|||
clearInterval(timerId); |
|||
} |
|||
}, 1000); |
|||
var time_key = data['extend_time'] ? 'extend_time' : 'end_time' |
|||
var time_remaining = new Date(data[time_key]) - new Date() |
|||
if (time_remaining <= 0) { |
|||
window.location.href = '/shop'; |
|||
} |
|||
} |
|||
}) |
|||
} |
|||
}, |
|||
events: { |
|||
/** Click event for subscribe button**/ |
|||
'click #subscribe_bid': '_clickSubscribe', |
|||
|
|||
/**Click event for add to cart and buy now buttons**/ |
|||
'click #add_to_cart, .o_we_buy_now, #products_grid .o_wsale_product_btn .a-submit': 'async _onClickAdd', |
|||
|
|||
/**Click event for place bid button**/ |
|||
'click #place_bid_button': '_placeBid', |
|||
|
|||
/**Click event for hide modal button**/ |
|||
'click #hide_modal': '_hideModal', |
|||
|
|||
/**Click event for buy now button**/ |
|||
'click .js_add_cart': '_buyNow' |
|||
}, |
|||
/** Function to hide auction messages after 5 seconds **/ |
|||
timeout: function() { |
|||
setTimeout(function() { |
|||
document.getElementById('auction_messages').style.display = "none" |
|||
}, 5000) |
|||
}, |
|||
/** Function to handle subscription to auction updates **/ |
|||
_clickSubscribe: function() { |
|||
// Get product and auction IDs
|
|||
let product_id = this.$('input[name="auction_product_id"]').val() |
|||
let auction_id = this.$('input[name="auction_id"]').val(); |
|||
|
|||
// Get subscribe button and auction messages elements
|
|||
var bellIcon = document.getElementById('subscribe_bid'); |
|||
var messages = document.getElementById('auction_messages') |
|||
|
|||
// If button says "Subscribe", subscribe user to auction updates
|
|||
if (bellIcon.innerHTML == 'Subscribe') { |
|||
bellIcon.style.color = 'red' |
|||
bellIcon.classList.remove('fa-bell-o') |
|||
bellIcon.classList.add('fa-bell') |
|||
bellIcon.innerHTML = 'Unsubscribe' |
|||
ajax.jsonRpc('/subscribe/bid', 'call', { |
|||
'text': 'subscribe', |
|||
'product_id': product_id, |
|||
'auction_id': auction_id |
|||
}).then((data) => { |
|||
messages.innerHTML = data |
|||
messages.classList.remove('alert-warning') |
|||
messages.classList.add('alert-success') |
|||
messages.style.display = "block" |
|||
this.timeout() |
|||
}) |
|||
} |
|||
/** Otherwise, unsubscribe user from auction updates **/ |
|||
else { |
|||
bellIcon.style.color = '#007bff' |
|||
bellIcon.classList.remove('fa-bell') |
|||
bellIcon.classList.add('fa-bell-o') |
|||
bellIcon.innerHTML = 'Subscribe' |
|||
ajax.jsonRpc('/subscribe/bid', 'call', { |
|||
'text': 'unsubscribe', |
|||
'auction_id': auction_id |
|||
}).then((data) => { |
|||
messages.classList.add('alert-warning') |
|||
messages.innerHTML = data |
|||
messages.style.display = "block" |
|||
this.timeout() |
|||
}) |
|||
} |
|||
}, |
|||
/** Function to handle adding products to cart **/ |
|||
_onClickAdd: function(ev) { |
|||
ev.preventDefault(); |
|||
var def = () => { |
|||
this.getCartHandlerOptions(ev); |
|||
return this._handleAdd($(ev.currentTarget).closest('form')); |
|||
}; |
|||
if ($('.js_add_cart_variants').children().length) { |
|||
return this._getCombinationInfo(ev).then(() => { |
|||
return !$(ev.target).closest('.js_product').hasClass("css_not_available") ? def() : Promise.resolve(); |
|||
}); |
|||
} |
|||
return def(); |
|||
}, |
|||
/** Function to submit form when adding products to cart **/ |
|||
_submitForm: function() { |
|||
const params = this.rootProduct; |
|||
const $product = $('#product_detail'); |
|||
const productTrackingInfo = $product.data('product-tracking-info'); |
|||
if (productTrackingInfo) { |
|||
productTrackingInfo.quantity = params.quantity; |
|||
$product.trigger('add_to_cart_event', [productTrackingInfo]); |
|||
} |
|||
params.add_qty = params.quantity; |
|||
params.product_custom_attribute_values = JSON.stringify(params.product_custom_attribute_values); |
|||
params.no_variant_attribute_values = JSON.stringify(params.no_variant_attribute_values); |
|||
delete params.quantity; |
|||
return this.addToCart(params); |
|||
}, |
|||
_placeBid: function() { |
|||
/** Function to place a bid |
|||
Get the bid amount and minimum amount from the page **/ |
|||
var bid_amount = parseFloat(this.$('input[id="bid_amount"]').val()) |
|||
var min_amount = parseFloat(this.$('#min_amount')[0].innerHTML) |
|||
let product_id = this.$('input[name="auction_product_id"]').val() |
|||
let auction_id = this.$('input[name="auction_id"]').val(); |
|||
var messages = this.$('#auction_messages')[0] |
|||
if (min_amount >= bid_amount) { |
|||
modal_title.innerHTML = "Warning!" |
|||
modal_message.innerHTML = "Please check the minimum bid amount" |
|||
this.$('#modal_product_warning').modal('show') |
|||
} else { |
|||
ajax.jsonRpc('/place_bid', 'call', { |
|||
'bid_amount': bid_amount, |
|||
'product_id': product_id, |
|||
'auction_id': auction_id |
|||
}).then((data) => { |
|||
if (data){ |
|||
messages.innerHTML = data['bid_placed'] |
|||
messages.style.display = "block"; |
|||
this.timeout() |
|||
window.location.reload() |
|||
|
|||
} |
|||
else { |
|||
modal_title.innerHTML = "Same amount placed" |
|||
modal_message.innerHTML = "You have already placed this amount. Please reconsider your bid amount" |
|||
this.$('#modal_product_warning').modal('show') |
|||
} |
|||
}) |
|||
} |
|||
}, |
|||
/**Click event for hide modal button**/ |
|||
_hideModal: function() { |
|||
this.$('#modal_product_warning').modal('hide') |
|||
}, |
|||
_buyNow: function() { |
|||
/** function for buy now button **/ |
|||
let product_id = this.$('input[name="auction_product_id"]').val() |
|||
let product_template_id = this.$('input[name="product_product_id"]').val() |
|||
let auction_id = this.$('input[name="auction_id"]').val(); |
|||
ajax.jsonRpc('/buy/now', 'call', { |
|||
product_id: parseInt(product_template_id), |
|||
'product_id': product_template_id, |
|||
'auction_id': auction_id, |
|||
'auction_product_id': product_id, |
|||
'add_qty': 1 |
|||
}).then(function(data) {}) |
|||
ajax.jsonRpc('/auction/close', 'call', { |
|||
'product_id': product_id, |
|||
'auction_id': auction_id, |
|||
}) |
|||
modal_title.innerHTML = "Success" |
|||
modal_message.innerHTML = "You will get a email please confirm and pay now you will be redirected to home page" |
|||
$('#modal_product_warning').modal('show') |
|||
window.location.href = '/shop' |
|||
}, |
|||
}) |
@ -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,52 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<!-- Define a form view for the "bargain.subscribers" model --> |
|||
<record id="bargain_subscribers_view_form" model="ir.ui.view"> |
|||
<field name="name">bargain.subscribers.view.form</field> |
|||
<field name="model">bargain.subscribers</field> |
|||
<field name="arch" type="xml"> |
|||
<form> |
|||
<sheet> |
|||
<group> |
|||
<group> |
|||
<field name="subscriber_id"/> |
|||
<field name="name"/> |
|||
<field name="email"/> |
|||
</group> |
|||
<group> |
|||
<field name="auction_id"/> |
|||
<field name="subscribe_time"/> |
|||
</group> |
|||
</group> |
|||
</sheet> |
|||
<!-- Add a chatter to the form view for messaging and activities --> |
|||
<div class="oe_chatter"> |
|||
<field name="message_follower_ids"/> |
|||
<field name="activity_ids"/> |
|||
<field name="message_ids" |
|||
options="{'post_refresh':'recipients'}"/> |
|||
</div> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
<!-- Define a tree view for the "bargain.subscribers" model --> |
|||
<record id="bargain_subscribers_view_tree" model="ir.ui.view"> |
|||
<field name="name">bargain.subscribers.view.tree</field> |
|||
<field name="model">bargain.subscribers</field> |
|||
<field name="arch" type="xml"> |
|||
<tree> |
|||
<field name="subscriber_id"/> |
|||
<field name="name"/> |
|||
<field name="email"/> |
|||
<field name="auction_id"/> |
|||
<field name="subscribe_time"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
<!-- Define an action to open the "bargain.subscribers" model --> |
|||
<record id="bargain_subscribers_action" model="ir.actions.act_window"> |
|||
<field name="name">Bargain Subscribers</field> |
|||
<field name="res_model">bargain.subscribers</field> |
|||
<field name="view_mode">tree,form</field> |
|||
</record> |
|||
</odoo> |
@ -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,153 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<!-- Form view for website.bargain model --> |
|||
<record id="website_bargain_view_form" model="ir.ui.view"> |
|||
<field name="name">website.bargain.view.form</field> |
|||
<field name="model">website.bargain</field> |
|||
<field name="arch" type="xml"> |
|||
<form> |
|||
<header> |
|||
<button name="action_confirm" type="object" |
|||
string="Confirm" class="oe_highlight" |
|||
attrs="{'invisible':['|',('state','=',True),('state','not in',['draft'])]}"/> |
|||
<button name="action_reset_to_draft" type="object" |
|||
string="Reset to draft" class="oe_highlight" |
|||
attrs="{'invisible' :['|',('state','=',True),('state','in',['draft','finished','closed'])]}"/> |
|||
<button name="action_run_auction" type="object" |
|||
string="Run Auction" class="oe_highlight" |
|||
attrs="{'invisible':['|',('state','=',True),('state','not in',['confirmed'])]}"/> |
|||
<button name="action_complete" type="object" |
|||
string="Completed" class="oe_highlight" |
|||
attrs="{'invisible':['|',('state','=',True),('state','not in',['running','extended'])]}"/> |
|||
<button name="action_close" type="object" string="Closed" |
|||
class="oe_highlight" |
|||
attrs="{'invisible':['|',('state','=',True),('state','not in',['running','extended','finished'])]}"/> |
|||
<field name="state" widget="statusbar"/> |
|||
</header> |
|||
<sheet> |
|||
<group class="mt-4"> |
|||
<field name="website_id" |
|||
attrs="{'readonly':[('state','!=','draft')]}"/> |
|||
<field name="auction_manager_id" |
|||
attrs="{'readonly':[('state','!=','draft')]}"/> |
|||
<field name="template_id" |
|||
attrs="{'readonly':[('state','!=','draft')]}"/> |
|||
<field name="product_id" |
|||
attrs="{'readonly':[('state','!=','draft')]}"/> |
|||
<field name="name" |
|||
attrs="{'readonly':[('state','!=','draft')]}"/> |
|||
</group> |
|||
<group> |
|||
<group name="price_configuration" |
|||
string="Price Configuration"> |
|||
<field name="currency_id" position="attributes" |
|||
attrs="{'readonly':[('state','!=','draft')]}"/> |
|||
<field name="initial_price" widget="monetary" |
|||
attrs="{'readonly':[('state','!=','draft')]}" |
|||
force_save="1"/> |
|||
<field name="is_buy_now" |
|||
attrs="{'readonly':[('state','!=','draft')]}"/> |
|||
<field name="price_buy_now" widget="monetary" |
|||
force_save="1" |
|||
attrs="{'invisible':[('is_buy_now','=',False)]}"/> |
|||
</group> |
|||
<group name="time_configuration" |
|||
string="TIME CONFIGURATION"> |
|||
<field name="start_time" |
|||
attrs="{'readonly':[('state','!=','draft')]}"/> |
|||
<field name="end_time" |
|||
attrs="{'readonly':[('state','!=','draft')]}"/> |
|||
<field name="extend_time" |
|||
attrs="{'readonly':[('state','in',['finished','closed'])]}"/> |
|||
</group> |
|||
</group> |
|||
<notebook> |
|||
<page name="bidder_information" |
|||
string="Bidder Information" sequence="2"> |
|||
<div> |
|||
<h4>Bidder Information</h4> |
|||
</div> |
|||
<field name="bargain_information_ids"/> |
|||
</page> |
|||
<page name="subscribers" string="Subscribers" |
|||
sequence="3"> |
|||
<div> |
|||
<h4>Subscribers</h4> |
|||
</div> |
|||
<field name="bargain_subscribers_ids"/> |
|||
</page> |
|||
<page name="notification" string="Notification" |
|||
sequence="4"> |
|||
<group> |
|||
<group string="Notification to admin"> |
|||
<field name="is_activate"/> |
|||
<label for="notify_on" |
|||
string="Notify before" |
|||
attrs="{'invisible':[('is_activate','=',False)]}"/> |
|||
<div class="o_checkbox_optional_field" |
|||
attrs="{'invisible':[('is_activate','=',False)]}"> |
|||
<field name="notify_on" |
|||
class="oe_inline"/> |
|||
<div class="oe_inline"> |
|||
<field name="notify_selection"/> |
|||
</div> |
|||
</div> |
|||
<field name="is_notification_send" |
|||
attrs="{'invisible':[('is_activate','=',False)]}"/> |
|||
</group> |
|||
<group string="Miscellaneous Notification Settings"> |
|||
<field name="is_winner_notification"/> |
|||
<field name="is_loser_notification"/> |
|||
</group> |
|||
<group string="Subscriber Notification"> |
|||
<field name="is_subscriber_start_notification"/> |
|||
<field name="is_extend_auction_notification"/> |
|||
<field name="is_new_bid_notification"/> |
|||
<field name="is_bid_end_notification"/> |
|||
</group> |
|||
</group> |
|||
</page> |
|||
<page name="product_info" string="Product Info"> |
|||
<group string="Product Information"> |
|||
<field name="product_img" widget="image" |
|||
style="padding: 0px;" nolabel="1"/> |
|||
</group> |
|||
<group> |
|||
<field name="product_id" |
|||
string="Auction Product Name"/> |
|||
<field name="product_description"/> |
|||
</group> |
|||
</page> |
|||
</notebook> |
|||
</sheet> |
|||
<div class="oe_chatter"> |
|||
<field name="message_follower_ids"/> |
|||
<field name="activity_ids"/> |
|||
<field name="message_ids" |
|||
options="{'post_refres':'recipients'}"/> |
|||
</div> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
<!-- Tree view for website.bargain model --> |
|||
<record id="website_bargain_view_tree" model="ir.ui.view"> |
|||
<field name="name">website.bargain.view.tree</field> |
|||
<field name="model">website.bargain</field> |
|||
<field name="arch" type="xml"> |
|||
<tree> |
|||
<field name="name"/> |
|||
<field name="product_id"/> |
|||
<field name="start_time"/> |
|||
<field name="end_time"/> |
|||
<field name="extend_time" optional="hide"/> |
|||
<field name="state"/> |
|||
<field name="website_id" optional="hide"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
<record id="website_bargain_action" model="ir.actions.act_window"> |
|||
<field name="name">Website Bargain</field> |
|||
<field name="res_model">website.bargain</field> |
|||
<field name="view_mode">tree,form</field> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,277 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<template id="website_product_view" inherit_id="website_sale.product"> |
|||
<xpath expr="//div[@id='product_details']" position="replace"> |
|||
<t t-if="product.is_auction"> <!-- Conditionally render elements based on the "is_auction" attribute of the product object --> |
|||
<!-- Create hidden input fields with values from the product and auction objects --> |
|||
<t t-if="request.env.user.is_public"> |
|||
<div t-attf-class="col-lg-#{image_cols[1]} mt-md-4" |
|||
id="product_details"> |
|||
<h1 itemprop="name" t-field="product.name"> |
|||
Product |
|||
Name |
|||
</h1> |
|||
Please <a href="/web/login">sign in</a> to participate |
|||
</div> |
|||
</t> |
|||
<t t-else=""> |
|||
<input type="hidden" class="product_id" |
|||
name="product_product_id" |
|||
t-att-value="product_variant.id"/> |
|||
<input type="hidden" name="auction_product_id" |
|||
t-att-value="product.id"/> |
|||
<!-- Iterate over the auction objects --> |
|||
<t t-foreach="auction" t-as="bid"> |
|||
<!-- Check if the auction is running, matches the current product, and matches the current website --> |
|||
<t t-if="(bid['state']=='running') and (bid['product_id'][0]==product.id) and (website.id == bid['website_id'][0])"> |
|||
<input type="hidden" class="auction" |
|||
name="auction_id" t-att-value="bid['id']"/> |
|||
<!-- Create a div to display details about the product and auction --> |
|||
<div t-attf-class="col-lg-#{image_cols[1]} mt-md-4" |
|||
id="product_details"> |
|||
<h1 itemprop="name" t-field="product.name"> |
|||
Product |
|||
Name |
|||
</h1> |
|||
<span id="auction_messages" |
|||
class="alert alert-info"/> |
|||
<div class="auction_timer"> |
|||
Auction will end in |
|||
<h3 id="timer">---</h3> |
|||
Till |
|||
<!-- Display either the extended time or the end time of the auction --> |
|||
<t t-if="bid['extend_time']"> |
|||
<t t-esc="bid['extend_time']"/> |
|||
</t> |
|||
<t t-else=""> |
|||
<t t-esc="bid['end_time']"/> |
|||
</t> |
|||
</div> |
|||
<div class="auction_min_amount"> |
|||
Min bid amount |
|||
<t t-esc="bid['currency_id'][1] "/> |
|||
<strong id="min_amount" |
|||
t-esc="bid['initial_price']"/> |
|||
</div> |
|||
<input type="number" id="bid_amount" step="any" |
|||
required="1"/> |
|||
<button type="button" class="btn btn-primary" |
|||
id="place_bid_button">Place bid |
|||
</button> |
|||
<p class="subscribe"> |
|||
<i class="fa fa-bell-o o_notification_icon" |
|||
id="subscribe_bid">Subscribe |
|||
</i> |
|||
<i class="fa fa-users" id="auction_bidders"> |
|||
<a t-attf-href="/bidders/{{ slug(product) }}"> |
|||
Bidders |
|||
</a> |
|||
</i> |
|||
</p> |
|||
<!-- Create a modal to display warnings or messages about the auction --> |
|||
<div class="modal fade" |
|||
id="modal_product_warning" |
|||
tableindex="-1" role="dialog"> |
|||
<div class="modal-dialog" role="document"> |
|||
<div class="modal-content"> |
|||
<div class="modal-header"> |
|||
<h4 class="modal-title" |
|||
id="modal_title"/> |
|||
</div> |
|||
<div class="modal-body"> |
|||
<p class="message" |
|||
id="modal_message"/> |
|||
|
|||
</div> |
|||
<div class="modal-footer"> |
|||
<button type="button" |
|||
id="hide_modal" |
|||
class="btn btn-default" |
|||
data-dismiss="modal"> |
|||
Close |
|||
</button> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- Display a "buy now" option if the auction allows it --> |
|||
<t t-if="bid['is_buy_now']"> |
|||
<div> |
|||
or |
|||
<br/> |
|||
<a class="btn btn-primary js_add_cart" |
|||
data-productiid="1">Buy Now |
|||
</a> |
|||
For just |
|||
<t t-esc="bid['currency_id'][1]"/> |
|||
<t t-esc="bid['price_buy_now']"/> |
|||
</div> |
|||
</t> |
|||
</div> |
|||
<div id="o_product_terms_and_share" |
|||
class="d-flex justify-content-between flex-column flex-md-row align-items-md-end mb-3"> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<t t-else=""> <!-- start of else block --> |
|||
<div t-attf-class="col-lg-#{image_cols[1]} mt-md-4" |
|||
id="product_details"> |
|||
<t t-set="base_url" |
|||
t-value="product.get_base_url()"/> <!-- set base URL --> |
|||
<h1 itemprop="name" t-field="product.name">Product Name |
|||
</h1> <!-- display product name --> |
|||
<span itemprop="url" style="display:none;" |
|||
t-esc="base_url + product.website_url"/> <!-- set URL for product --> |
|||
<span itemprop="image" style="display:none;" |
|||
t-esc="base_url + website.image_url(product, 'image_1920')"/> <!-- set image for product --> |
|||
<t t-if="is_view_active('website_sale.product_comment')"> <!-- check if product comments are active --> |
|||
<a href="#o_product_page_reviews" |
|||
class="o_product_page_reviews_link text-decoration-none"> <!-- link to product reviews section --> |
|||
<t t-call="portal_rating.rating_widget_stars_static"> <!-- display product rating --> |
|||
<t t-set="rating_avg" |
|||
t-value="product.rating_avg"/> <!-- set product rating average --> |
|||
<t t-set="trans_text_plural">%s reviews</t> |
|||
<t t-set="trans_text_singular">%s review</t> |
|||
<t t-set="rating_count" |
|||
t-value="(trans_text_plural if product.rating_count > 1 else trans_text_singular) % product.rating_count"/> <!-- set product rating count --> |
|||
</t> |
|||
</a> |
|||
</t> |
|||
<p t-field="product.description_sale" |
|||
class="text-muted my-2" |
|||
placeholder="A short description that will also appear on documents."/> <!-- display product description --> |
|||
<form t-if="product._is_add_to_cart_possible()" |
|||
action="/shop/cart/update" |
|||
method="POST"> <!-- add to a cart form --> |
|||
<input type="hidden" name="csrf_token" |
|||
t-att-value="request.csrf_token()"/> <!-- add CSRF token for security --> |
|||
<div class="js_product js_main_product mb-3"> |
|||
<div> |
|||
<t t-call="website_sale.product_price"/> <!-- display product price --> |
|||
<small t-if="combination_info['base_unit_price']" |
|||
class="ms-1 text-muted o_base_unit_price_wrapper d-none" |
|||
groups="website_sale.group_show_uom_price"> |
|||
<t t-call='website_sale.base_unit_price'/> <!-- display product unit price --> |
|||
</small> |
|||
</div> |
|||
<t t-placeholder="select"> |
|||
<input type="hidden" class="product_id" |
|||
name="product_id" |
|||
t-att-value="product_variant.id"/> |
|||
<input type="hidden" |
|||
class="product_template_id" |
|||
name="product_template_id" |
|||
t-att-value="product.id"/> |
|||
<input t-if="product.public_categ_ids.ids" |
|||
type="hidden" |
|||
class="product_category_id" |
|||
name="product_category_id" |
|||
t-att-value="product.public_categ_ids.ids[0]"/> |
|||
<input t-if="product.product_tag_ids.ids" |
|||
type="hidden" |
|||
class="product_tag_id" |
|||
name="product_tag_id" |
|||
t-att-value="product.product_tag_ids.ids[0]"/> |
|||
<t t-if="combination" |
|||
t-call="sale.variants"> <!-- display product variants --> |
|||
<t t-set="ul_class" |
|||
t-valuef="flex-column"/> |
|||
<t t-set="parent_combination" |
|||
t-value="None"/> |
|||
</t> |
|||
<t t-else=""> |
|||
<ul class="d-none js_add_cart_variants mb-0" |
|||
t-att-data-attribute_exclusions="{'exclusions: []'}"/> |
|||
</t> |
|||
</t> |
|||
<p t-if="True" |
|||
class="css_not_available_msg alert alert-warning"> |
|||
This |
|||
combination does not exist. |
|||
</p> |
|||
<!-- Define a div element with an id of "o_wsale_cta_wrapper" and some classes --> |
|||
<div id="o_wsale_cta_wrapper" |
|||
class="d-flex flex-wrap align-items-center"> |
|||
<!-- Define some variables in the template --> |
|||
<t t-set="hasQuantities" t-value="false"/> |
|||
<t t-set="hasBuyNow" t-value="false"/> |
|||
<t t-set="ctaSizeBig" |
|||
t-value="not hasQuantities or not hasBuyNow"/> |
|||
|
|||
<!-- Define a div element with an id of "add_to_cart_wrap" and some classes --> |
|||
<div id="add_to_cart_wrap" |
|||
t-attf-class="{{'d-none' if combination_info['prevent_zero_price_sale'] else 'd-inline-flex'}} align-items-center mb-2 me-auto"> |
|||
<!-- Define an anchor element with an id of "add_to_cart" and some classes --> |
|||
<a role="button" id="add_to_cart" |
|||
t-attf-class="btn btn-primary js_check_product a-submit flex-grow-1 #{'btn-lg' if ctaSizeBig else ''}" |
|||
href="#"> |
|||
<!-- Define an icon element with the FontAwesome class "fa fa-shopping-cart" --> |
|||
<i class="fa fa-shopping-cart me-2"/> |
|||
<!-- Define a span element with bold text --> |
|||
<span style="font-weight: bold">ADD TO |
|||
CART |
|||
</span> |
|||
</a> |
|||
</div> |
|||
<!-- Define a div element with an id of "product_option_block" and some classes --> |
|||
<div id="product_option_block" |
|||
class="d-flex flex-wrap w-100"/> |
|||
</div> |
|||
|
|||
<div id="contact_us_wrapper" |
|||
t-attf-class="{{'d-flex' if combination_info['prevent_zero_price_sale'] else 'd-none'}} oe_structure oe_structure_solo #{_div_classes}"> |
|||
<section class="s_text_block" |
|||
data-snippet="s_text_block" |
|||
data-name="Text"> |
|||
<div class="container"> |
|||
<a t-att-href="website.contact_us_button_url" |
|||
class="btn btn-primary btn_cta"> |
|||
Contact Us |
|||
</a> |
|||
</div> |
|||
</section> |
|||
</div> |
|||
</div> |
|||
</form> |
|||
<!-- If the product is not active, show a warning message --> |
|||
<p t-elif="not product.active" class="alert alert-warning"> |
|||
This product is no longer available. |
|||
</p> |
|||
<!-- If the product has no valid combination, show a warning message --> |
|||
<p t-else="" class="alert alert-warning"> |
|||
This product has no valid combination. |
|||
</p> |
|||
<!-- Display the single value attributes of the product --> |
|||
<div id="product_attributes_simple"> |
|||
<!-- Prepare single value attributes for display --> |
|||
<t t-set="single_value_attributes" |
|||
t-value="product.valid_product_template_attribute_line_ids._prepare_single_value_for_display()"/> |
|||
<!-- Display the attributes in a table format --> |
|||
<table t-attf-class="table table-sm text-muted {{'' if single_value_attributes else 'd-none'}}"> |
|||
<t t-foreach="single_value_attributes" |
|||
t-as="attribute"> |
|||
<tr> |
|||
<td> |
|||
<span t-field="attribute.name"/>: |
|||
<!-- Display the attribute values --> |
|||
<t t-foreach="single_value_attributes[attribute]" |
|||
t-as="ptal"> |
|||
<span t-field="ptal.product_template_value_ids._only_active().name"/> |
|||
<t t-if="not ptal_last">,</t> |
|||
</t> |
|||
</td> |
|||
</tr> |
|||
</t> |
|||
</table> |
|||
</div> |
|||
<!-- Display the product terms and share section --> |
|||
<div id="o_product_terms_and_share" |
|||
class="d-flex justify-content-between flex-column flex-md-row align-items-md-end mb-3"> |
|||
</div> |
|||
</div> |
|||
</t> |
|||
</xpath> |
|||
</template> |
|||
</odoo> |
@ -0,0 +1,41 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<!-- This template is used to modify the product page on the Odoo e-commerce website. --> |
|||
<template id="website_shop_auction" |
|||
inherit_id="website_sale.products_item"> |
|||
<!-- Replace the existing div with class "product_price" --> |
|||
<xpath expr="//div[hasclass('product_price')]" position="replace"> |
|||
<!-- If the product is an auction, display "AUCTION ON" --> |
|||
<t t-if="product.is_auction"> |
|||
<span id="auction_on">AUCTION ON</span> |
|||
</t> |
|||
<!-- If the product is not an auction, display the regular price --> |
|||
<t t-else=""> |
|||
<div class="product_price" itemprop="offers" |
|||
itemscope="itemscope" itemtype="http://schema.org/Offer"> |
|||
<t t-if="'base_price' in template_price_vals"> |
|||
<del t-attf-class="text-muted me-1 h6 mb-0" |
|||
style="white-space: nowrap;"> |
|||
<!-- Display the original price with a strikethrough --> |
|||
<em class="small" |
|||
t-esc="template_price_vals['base_price']" |
|||
t-options="{'widget': 'monetary', 'display_currency': website.currency_id}"/> |
|||
</del> |
|||
</t> |
|||
<!-- Display the reduced price, or the text "Contact us for price" if the price is zero --> |
|||
<span class="h6 mb-0" |
|||
t-if="template_price_vals['price_reduce'] or not website.prevent_zero_price_sale" |
|||
t-esc="template_price_vals['price_reduce']" |
|||
t-options="{'widget': 'monetary', 'display_currency': website.currency_id}"/> |
|||
<span class="h6 mb-0" t-else="" |
|||
t-field="website.prevent_zero_price_sale_text"/> |
|||
<!-- Set the price and currency information for the schema.org metadata --> |
|||
<span itemprop="price" style="display:none;" |
|||
t-esc="template_price_vals['price_reduce']"/> |
|||
<span itemprop="priceCurrency" style="display:none;" |
|||
t-esc="website.currency_id.name"/> |
|||
</div> |
|||
</t> |
|||
</xpath> |
|||
</template> |
|||
</odoo> |