You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
353 lines
17 KiB
353 lines
17 KiB
# -*- coding: utf-8 -*-
|
|
#############################################################################
|
|
#
|
|
# Cybrosys Technologies Pvt. Ltd.
|
|
#
|
|
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
|
|
#
|
|
# You can modify it under the terms of the GNU LESSER
|
|
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
|
#
|
|
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
|
# (LGPL v3) along with this program.
|
|
# If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
#############################################################################
|
|
from odoo import fields, http
|
|
from odoo.addons.website_sale.controllers.main import WebsiteSale
|
|
from odoo.http import request
|
|
|
|
|
|
class WebsiteAuction(WebsiteSale):
|
|
"""This class enables is used to view the timer and related functions
|
|
of bidding,buy now and other routes
|
|
_prepare_product_values(self, product, category, search, **kwargs):
|
|
This function is inbuilt function in website sale and its
|
|
supered here and pass auction values in this function
|
|
auction_timer(self, auction_id):
|
|
This function gets the auction id and pass auction timing
|
|
details to website
|
|
buy_now(self, auction_id, product_id):
|
|
Its the function for button in buy now,in this function a new
|
|
sale order is created and send to the customer through email
|
|
def auction_close(self, auction_id):
|
|
Function gets the auction id and move the auction stage to
|
|
finished and make the product unavailable from website
|
|
winner_sale_order(self, auction_id, **post):
|
|
Makes a sale order to the winner and id notifications are
|
|
enabled it will send a email to the winners or losers
|
|
subscribe(self, auction_id, **post):
|
|
Used to add subscribers from website to database
|
|
place_bid(self, auction_id, **post):
|
|
When place bid button is triggered it will call this function
|
|
and the bidders details will be added to database and
|
|
if enabled it will send notification to subscribers
|
|
bidders(self, product_id):
|
|
Route to pass bidders details to website
|
|
bid_cancel(self, bidders):
|
|
Function to cancel the bid"""
|
|
|
|
def _prepare_product_values(self, product, category, search, **kwargs):
|
|
"""Summary:
|
|
Function is used to pass auction details by supering
|
|
this function because its already defined it websitesale
|
|
Args:
|
|
product:pass the object product
|
|
category:pass the category if enabled
|
|
kwargs:used to pass variable to function
|
|
Return:
|
|
Values is updated with auction and current website and
|
|
passed to website sale"""
|
|
values = super()._prepare_product_values(product, category, search,
|
|
**kwargs)
|
|
current_website = request.website
|
|
auction = request.env['website.bargain'].sudo().search_read([])
|
|
values.update({
|
|
'auction': auction,
|
|
'website': current_website
|
|
})
|
|
return values
|
|
|
|
@http.route('/auction/timer', type='json', auth='user', csrf=False)
|
|
def auction_timer(self, auction_id):
|
|
"""Summary:
|
|
Function to pass timer details from auction like start
|
|
time,end time,extended time
|
|
Args:
|
|
auction_id:used to get auction id from website
|
|
Return:
|
|
Values which include start_time,end time,extended
|
|
time and state id"""
|
|
auction = request.env['website.bargain'].sudo().browse(int(auction_id))
|
|
values = {
|
|
'start_time': auction.start_time,
|
|
'end_time': fields.Datetime.context_timestamp(auction,
|
|
auction.end_time),
|
|
'state': auction.state,
|
|
}
|
|
if auction.extend_time:
|
|
values['extend_time'] = fields.Datetime.context_timestamp(auction,
|
|
auction.extend_time)
|
|
return values
|
|
|
|
@http.route('/auction/close', type='json', auth='user', csrf=False)
|
|
def auction_close(self, auction_id):
|
|
"""Summary:
|
|
Function to close auction when a customer buys
|
|
a product instantly or the auction is ended
|
|
Args:
|
|
auction_id: used to get auction id from website
|
|
Return:
|
|
a string auction ended to website"""
|
|
auction = request.env['website.bargain'].sudo().browse(int(auction_id))
|
|
auction.product_id.is_auction = False
|
|
auction.product_id.is_published = False
|
|
auction.write({'state': 'finished'})
|
|
return "auction ended"
|
|
|
|
@http.route('/place_bid', type='json', auth='user', csrf=False)
|
|
def place_bid(self, auction_id, **post):
|
|
"""Summary:
|
|
When place bid button is clicked it will trigger this function
|
|
and will add bidders details to backend and will send
|
|
notification to the subscribers if its enabled
|
|
Args:
|
|
auction_id:used to get auction id from website
|
|
post:used to get bid amount from frontend
|
|
Return:
|
|
A message bid placed and suction details"""
|
|
bid_amount = post.get('bid_amount')
|
|
auction = request.env['website.bargain'].sudo().browse(int(auction_id))
|
|
bidder_total = auction.bargain_information_ids.search_count(
|
|
[('bidder_id', '=', request.env.user.partner_id.id),
|
|
('bid_offer', '=', bid_amount)])
|
|
if bidder_total >= 1:
|
|
return False
|
|
else:
|
|
auction.bargain_information_ids.sudo().create({
|
|
'bidder_id': request.env.user.partner_id.id,
|
|
'auction_id': auction.id,
|
|
'bid_offer': bid_amount,
|
|
'status': 'Bid Placed'
|
|
})
|
|
if auction.is_subscriber_start_notification and not auction.is_send_mail:
|
|
data = 'Bidding has started for ' + auction.name + '. Please check our website for more details.'
|
|
subscribers = ""
|
|
for record in auction.bargain_subscribers_ids:
|
|
subscribers += record.subscriber_id.email + ','
|
|
email_values = {'email_from': auction.auction_manager_id.email,
|
|
'subject': 'Bidding Started for ' + auction.name,
|
|
'email_to': subscribers, 'body_html': data}
|
|
request.env['mail.mail'].sudo().create(email_values).send()
|
|
auction.is_send_mail = True
|
|
auction.write({'is_send_mail': True})
|
|
|
|
if auction.is_new_bid_notification:
|
|
data = 'A new bid has been placed with amount ' + str(
|
|
bid_amount) + ',on ' \
|
|
+ auction.name + ',by ' + request.env.user.partner_id.name \
|
|
+ 'please check into ' \
|
|
'our website'
|
|
subscribers = " "
|
|
for record in auction.bargain_subscribers_ids:
|
|
subscribers += record.subscriber_id.email + ','
|
|
email_values = {'email_from': auction.auction_manager_id.email,
|
|
'subject': 'New Bid Placed on ' + auction.name,
|
|
'email_to': subscribers, 'body_html': data}
|
|
request.env['mail.mail'].sudo().create(email_values).send()
|
|
values = ({
|
|
'bid_placed': 'Bid Placed',
|
|
'auction': auction
|
|
})
|
|
|
|
return values
|
|
|
|
@http.route('/bidders/<model("product.template"):product_id>', type='http',
|
|
auth='user', csrf=False, website=True)
|
|
def bidders(self, product_id):
|
|
"""
|
|
This method is used to fetch the details of the bidders participating in
|
|
an auction and render them on the website.
|
|
Args:
|
|
product_id: A product template model object.
|
|
Returns:
|
|
A rendered HTML template with information about the bidders in the
|
|
auction."""
|
|
auction = request.env['website.bargain'].sudo().search(
|
|
[('product_id', '=', product_id.id), ('state', '=', 'running')])
|
|
bidders_information = request.env['bargain.information'].sudo().search(
|
|
[('auction_id', '=', auction.id)],
|
|
order='bid_offer desc')
|
|
values = ({
|
|
'bidders_information': bidders_information,
|
|
'product_id': product_id,
|
|
})
|
|
return request.render('website_bargain.bidders_information', values)
|
|
|
|
@http.route('/bid/cancel/<model("bargain.information"):bidders>',
|
|
type='http', auth='user', csrf='false')
|
|
def bid_cancel(self, bidders):
|
|
"""This function is for cancel the bid
|
|
Args:
|
|
bidders:Bidders name will be getting here
|
|
Returns:It returns previous page"""
|
|
bidders.status = 'cancelled'
|
|
previous_web_url = request.httprequest.headers.get('referer')
|
|
return request.redirect(previous_web_url)
|
|
|
|
@http.route('/shop/sale/order', type='json', auth='public', website=True,
|
|
csrf=False)
|
|
def winner_sale_order(self, auction_id, **post):
|
|
"""
|
|
This route creates a draft sale order for the winner of an auction
|
|
and sends notifications for winning and losing.
|
|
Args:
|
|
auction_id: the ID of the auction obtained from the frontend
|
|
post: used to get data of product from frontend
|
|
Returns:
|
|
True"""
|
|
# Get the ID of the product from the post data
|
|
product_product_id = post.get('product_product_id')
|
|
# Find the auction with the given ID
|
|
auction = request.env['website.bargain'].sudo().browse(int(auction_id))
|
|
auction.write({'state': 'finished'})
|
|
if auction.is_bid_end_notification:
|
|
data = 'Bidding has ended for ' + auction.name + '. Thank you for participating.'
|
|
subscribers = ""
|
|
for record in auction.bargain_subscribers_ids:
|
|
subscribers += record.subscriber_id.email + ','
|
|
email_values = {'email_from': auction.auction_manager_id.email,
|
|
'subject': 'Bidding Ended for ' + auction.name,
|
|
'email_to': subscribers, 'body_html': data}
|
|
request.env['mail.mail'].sudo().create(email_values).send()
|
|
# Find the highest bidder for the auction
|
|
bid_record = auction.bargain_information_ids.filtered(
|
|
lambda r: r.status == 'Bid Placed').sorted(
|
|
key=lambda r: r.bid_offer)[-1]
|
|
# Create a draft sale order for the winner
|
|
sale_order = request.env['sale.order'].sudo().create({
|
|
'partner_id': bid_record.bidder_id.id,
|
|
'state': 'draft',
|
|
})
|
|
# Add the product to the sale order and set the price to the bid offer
|
|
sale_order.sudo().write({
|
|
'order_line': [(0, 0, {
|
|
'product_id': int(product_product_id),
|
|
'product_uom_qty': 1,
|
|
'price_unit': bid_record.bid_offer,
|
|
'name': 'auction won',
|
|
})]
|
|
})
|
|
mail_compose_message = request.env['mail.compose.message']
|
|
so_mcm_vals = sale_order.sudo().action_quotation_send().get('context',
|
|
{})
|
|
compose_msg = mail_compose_message.sudo().with_context(
|
|
so_mcm_vals).create({})
|
|
compose_msg.sudo().action_send_mail()
|
|
# Send a notification email to the winner and/or losers, if enabled
|
|
if auction.is_winner_notification:
|
|
data = "You have won in " + auction.name + " Kindly pay now and" \
|
|
" collect the product " \
|
|
"from our website"
|
|
email_values = {
|
|
'email_from': auction.auction_manager_id.email,
|
|
'subject': 'Won ' + auction.name,
|
|
'email_to': bid_record.bidder_id.email,
|
|
'body_html': data
|
|
}
|
|
request.env['mail.mail'].sudo().create(email_values).send()
|
|
if auction.is_loser_notification:
|
|
data = "You have lost in " + auction.name + "Better luck next time"\
|
|
" thank you for your " \
|
|
"effort and time"
|
|
email_to = ''
|
|
for record in auction.bargain_information_ids:
|
|
if record.bidder_id.id != bid_record.bidder_id.id:
|
|
email_to += record.bidder_id.email + ','
|
|
email_values = {
|
|
'email_from': auction.auction_manager_id.email,
|
|
'subject': 'Lost ' + auction.name,
|
|
'email_to': email_to,
|
|
'body_html': data
|
|
}
|
|
request.env['mail.mail'].sudo().create(email_values).send()
|
|
return True
|
|
|
|
@http.route('/subscribe/bid', type='json', auth='user', csrf=False)
|
|
def subscribe(self, auction_id, **post):
|
|
"""
|
|
Endpoint to manage subscription to an auction
|
|
auction_id: integer ID of the auction being subscribed to/unsubscribed
|
|
text: string indicating whether the user is subscribing or
|
|
unsubscribing ('subscribe' or 'unsubscribe')
|
|
return: string message indicating success or failure of
|
|
subscription/unsubscription action
|
|
"""
|
|
text = post.get('text')
|
|
auction = request.env['website.bargain'].sudo().browse(int(auction_id))
|
|
if text == 'subscribe':
|
|
if request.env.user.partner_id in \
|
|
auction.bargain_subscribers_ids.subscriber_id:
|
|
return 'You have already subscribed'
|
|
auction.bargain_subscribers_ids.sudo().create({
|
|
'subscriber_id': request.env.user.partner_id.id,
|
|
'auction_id': auction.id,
|
|
'is_subscribed': True
|
|
})
|
|
return 'You have been successfully subscribed to this auction'
|
|
elif text == 'unsubscribe':
|
|
auction.bargain_subscribers_ids.sudo().search(
|
|
[('subscriber_id', '=', request.env.user.partner_id.id),
|
|
('auction_id', '=', auction.id)]).unlink()
|
|
return 'Unsubscribed successfully'
|
|
|
|
@http.route('/subscribe/status', type='json', auth='user', csrf=False)
|
|
def subscribe_status(self, auction_id, **post):
|
|
"""
|
|
Controller method to handle subscription to an auction.
|
|
"""
|
|
auction = request.env['website.bargain'].sudo().browse(int(auction_id))
|
|
is_subscribed = False
|
|
for subscriber in auction.bargain_subscribers_ids:
|
|
if subscriber.subscriber_id == request.env.user.partner_id:
|
|
is_subscribed = subscriber.is_subscribed
|
|
break
|
|
|
|
return is_subscribed
|
|
|
|
@http.route('/buy/now', type='json', auth='public', website=True,
|
|
csrf=False)
|
|
def buy_now(self, auction_id, product_id):
|
|
"""
|
|
Args:
|
|
auction_id: the ID of the auction obtained from the frontend
|
|
product_id: the ID of the product used to get data from the frontend
|
|
"""
|
|
# Find the auction with the given ID
|
|
auction = request.env['website.bargain'].sudo().browse(int(auction_id))
|
|
# Create a draft sale order for the winner
|
|
sale_order = request.env['sale.order'].sudo().create({
|
|
'partner_id': request.env.user.partner_id.id,
|
|
'state': 'draft',
|
|
})
|
|
sale_order.sudo().write({
|
|
'order_line': [(0, 0, {
|
|
'product_id': int(product_id),
|
|
'product_uom_qty': 1,
|
|
'name': '(auction won)' + auction.name,
|
|
'price_unit': auction.price_buy_now,
|
|
})]
|
|
})
|
|
# Send a notification email to the winner
|
|
mail_compose_message = request.env['mail.compose.message']
|
|
so_mcm_vals = sale_order.sudo().action_quotation_send().get('context',
|
|
{})
|
|
compose_msg = mail_compose_message.sudo().with_context(
|
|
so_mcm_vals).create({})
|
|
compose_msg.sudo().action_send_mail()
|
|
|