@ -0,0 +1,45 @@ |
|||||
|
.. image:: https://img.shields.io/badge/license-LGPL--3-green.svg |
||||
|
:target: https://www.gnu.org/licenses/lgpl-3.0-standalone.html |
||||
|
:alt: License: LGPL-3 |
||||
|
|
||||
|
Product Bidding In ECommerce |
||||
|
============================ |
||||
|
This module helps you to add auction in website sale. |
||||
|
|
||||
|
Configuration |
||||
|
============= |
||||
|
* No additional configurations needed |
||||
|
|
||||
|
Company |
||||
|
------- |
||||
|
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ |
||||
|
|
||||
|
License |
||||
|
------- |
||||
|
Lesser General Public License, Version 3 (LGPL v3). |
||||
|
(http://www.gnu.org/licenses/lgpl-3.0-standalone.html) |
||||
|
|
||||
|
Credits |
||||
|
------- |
||||
|
* Developers: (V17) Anfas Faisal K, Contact:odoo@cybrosys.com |
||||
|
(V18) Ranjith R, Contact:odoo@cybrosys.com |
||||
|
|
||||
|
Contacts |
||||
|
-------- |
||||
|
* Mail Contact : odoo@cybrosys.com |
||||
|
* Website : https://cybrosys.com |
||||
|
|
||||
|
Bug Tracker |
||||
|
----------- |
||||
|
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. |
||||
|
|
||||
|
Maintainer |
||||
|
========== |
||||
|
.. image:: https://cybrosys.com/images/logo.png |
||||
|
:target: https://cybrosys.com |
||||
|
This module is maintained by Cybrosys Technologies. |
||||
|
For support and more information, please visit `Our Website <https://cybrosys.com/>`__ |
||||
|
|
||||
|
Further information |
||||
|
=================== |
||||
|
HTML Description: `<static/description/index.html>`__ |
@ -0,0 +1,23 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 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 . import controllers |
||||
|
from . import models |
@ -0,0 +1,60 @@ |
|||||
|
# -*- 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/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
{ |
||||
|
'name': 'Product Bidding In ECommerce', |
||||
|
'version': '18.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) 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 . import website_bargain |
@ -0,0 +1,353 @@ |
|||||
|
# -*- 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() |
@ -0,0 +1,21 @@ |
|||||
|
<?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> |
||||
|
</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> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,104 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8" ?> |
||||
|
<odoo> |
||||
|
<!-- Email template for admin notification --> |
||||
|
<record id="admin_email_template" model="mail.template"> |
||||
|
<field name="name">Auction: Admin Notification Email</field> |
||||
|
<field name="model_id" ref="website_bargain.model_website_bargain"/> |
||||
|
<field name="email_from">{{ |
||||
|
(object.auction_manager_id.partner_id.email) }} |
||||
|
</field> |
||||
|
<field name="email_to">{{ |
||||
|
(object.auction_manager_id.partner_id.email) }} |
||||
|
</field> |
||||
|
<field name="subject">{{ (object.name) }} end time is near</field> |
||||
|
<field name="body_html" type="html"> |
||||
|
<div style="margin: 0px; padding: 0px;"> |
||||
|
<p style="margin: 0px; padding: 0px; font-size: 13px"> |
||||
|
Dear |
||||
|
<t t-if="object.auction_manager_id.name"> |
||||
|
<t t-out="object.auction_manager_id.name"/> |
||||
|
</t> |
||||
|
<br/> |
||||
|
<br/> |
||||
|
This mail is a reminder that |
||||
|
<t t-if="object.name"> |
||||
|
<span style="font-weight:bold;" t-out="object.name"> |
||||
|
Auction |
||||
|
</span> |
||||
|
</t> |
||||
|
will end at |
||||
|
<t t-if="object.end_time"> |
||||
|
<span style="font-weight:bold;" |
||||
|
t-out="object.end_time">End Time |
||||
|
</span> |
||||
|
</t> |
||||
|
.So if its need to be |
||||
|
extended kindly reminding you to extend it fast. |
||||
|
</p> |
||||
|
</div> |
||||
|
</field> |
||||
|
</record> |
||||
|
<!-- Email template for auction start notification --> |
||||
|
<record id="email_template_auction_start" model="mail.template"> |
||||
|
<field name="name">Auction: Auction Start Notification Email</field> |
||||
|
<field name="model_id" ref="website_bargain.model_website_bargain"/> |
||||
|
<field name="email_from">{{ |
||||
|
(object.auction_manager_id.partner_id.email) }} |
||||
|
</field> |
||||
|
<field name="subject">{{ (object.name) }} has started</field> |
||||
|
<field name="body_html" type="html"> |
||||
|
<div style="margin: 0px; padding: 0px;"> |
||||
|
<p style="margin: 0px; padding: 0px; font-size: 13px"> |
||||
|
Dear Sir/Madam |
||||
|
<br/> |
||||
|
<br/> |
||||
|
This mail is a reminder that |
||||
|
<t t-if="object.name"> |
||||
|
<span style="font-weight:bold;" t-out="object.name"> |
||||
|
Auction |
||||
|
</span> |
||||
|
</t> |
||||
|
has started |
||||
|
<t t-if="object.start_time"> |
||||
|
<span style="font-weight:bold;" |
||||
|
t-out="object.end_time">Start Time Time |
||||
|
</span> |
||||
|
</t> |
||||
|
.Place your bids and win the auction. |
||||
|
</p> |
||||
|
</div> |
||||
|
</field> |
||||
|
</record> |
||||
|
<!-- Email template for auction extended notification --> |
||||
|
<record id="email_template_auction_extended" model="mail.template"> |
||||
|
<field name="name">Auction: Auction Extend Notification Email |
||||
|
</field> |
||||
|
<field name="model_id" ref="website_bargain.model_website_bargain"/> |
||||
|
<field name="email_from">{{ |
||||
|
(object.auction_manager_id.partner_id.email) }} |
||||
|
</field> |
||||
|
<field name="subject">{{ (object.name) }} has extended</field> |
||||
|
<field name="body_html" type="html"> |
||||
|
<div style="margin: 0px; padding: 0px;"> |
||||
|
<p style="margin: 0px; padding: 0px; font-size: 13px"> |
||||
|
Dear Sir/Madam |
||||
|
<br/> |
||||
|
<br/> |
||||
|
This mail is a reminder that |
||||
|
<t t-if="object.name"> |
||||
|
<span style="font-weight:bold;" t-out="object.name"> |
||||
|
Auction |
||||
|
</span> |
||||
|
</t> |
||||
|
has extended |
||||
|
<t t-if="object.extend_time"> |
||||
|
<span style="font-weight:bold;" |
||||
|
t-out="object.extend_time">Extended Time Time |
||||
|
</span> |
||||
|
</t> |
||||
|
.Place your bids and win the auction. |
||||
|
</p> |
||||
|
</div> |
||||
|
</field> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,7 @@ |
|||||
|
## Module <website_bargain> |
||||
|
|
||||
|
#### 19.02.2025 |
||||
|
#### Version 18.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) 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 . import bargain_information |
||||
|
from . import bargain_subscribers |
||||
|
from . import bargain_template |
||||
|
from . import product_template |
||||
|
from . import website_bargain |
@ -0,0 +1,44 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 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, models |
||||
|
|
||||
|
|
||||
|
class BargainInformation(models.Model): |
||||
|
"""Class for adding bidder details to the database""" |
||||
|
_name = 'bargain.information' |
||||
|
_rec_name = 'auction_id' |
||||
|
_description = "Bidder Details" |
||||
|
_inherit = ['mail.thread', 'mail.activity.mixin'] |
||||
|
|
||||
|
bidder_id = fields.Many2one('res.partner', string='Bidder', required=True, |
||||
|
help="Bidders details") |
||||
|
auction_id = fields.Many2one('website.bargain', string='Auction', |
||||
|
required=True, help="Auction Details") |
||||
|
currency_id = fields.Many2one(related="auction_id.currency_id", |
||||
|
help="Currency Details") |
||||
|
bid_offer = fields.Monetary(string="Bid Offer", |
||||
|
currency_field='currency_id', |
||||
|
help="Offered amount") |
||||
|
status = fields.Char(string="Status", readonly=True, |
||||
|
help="Current Status of bid") |
||||
|
product_id = fields.Many2one(related='auction_id.product_id', |
||||
|
string='Product', help="Product details") |
@ -0,0 +1,45 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 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, models |
||||
|
|
||||
|
|
||||
|
class BargainSubscribers(models.Model): |
||||
|
"""Model for adding the subscriber details """ |
||||
|
_name = 'bargain.subscribers' |
||||
|
_inherit = ['mail.thread', 'mail.activity.mixin'] |
||||
|
_description = "Subscriber details" |
||||
|
|
||||
|
subscriber_id = fields.Many2one('res.partner', required=True, |
||||
|
help="Subscribers id will be here ") |
||||
|
name = fields.Char(related='subscriber_id.name', string='Name', |
||||
|
readonly=False, help="Subscribers name", |
||||
|
required=True) |
||||
|
email = fields.Char(related='subscriber_id.email', string='Email', |
||||
|
readonly=False, help="Subscribers email") |
||||
|
auction_id = fields.Many2one('website.bargain', string='Auction', |
||||
|
required=True, help="Auction details") |
||||
|
subscribe_time = fields.Datetime(string='Subscribe On', |
||||
|
default=fields.Datetime.today(), |
||||
|
readonly=True, |
||||
|
help="Time of subscription") |
||||
|
is_subscribed = fields.Boolean(string="Is Subscribed", |
||||
|
help="Check if Subscribed or not") |
@ -0,0 +1,36 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 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, models |
||||
|
|
||||
|
|
||||
|
class BargainTemplate(models.Model): |
||||
|
"""Model for auction template""" |
||||
|
|
||||
|
_name = 'bargain.template' |
||||
|
_inherit = ['mail.thread', 'mail.activity.mixin'] |
||||
|
_description = "Bargain Template" |
||||
|
|
||||
|
name = fields.Char(string='Template Name', help="Name of the template") |
||||
|
product_id = fields.Many2one('product.template', |
||||
|
domain=[('is_published', '=', True)], |
||||
|
required=True, |
||||
|
help="Choose the product from the list") |
@ -0,0 +1,31 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 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, models |
||||
|
|
||||
|
|
||||
|
class ProductTemplateInherit(models.Model): |
||||
|
"""Model to add a new boolean field to product template""" |
||||
|
_inherit = 'product.template' |
||||
|
|
||||
|
is_auction = fields.Boolean(string='Auction On', readonly=True, |
||||
|
help="If auction is on this field will be true" |
||||
|
) |
@ -0,0 +1,301 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 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 datetime import timedelta |
||||
|
from odoo import api, fields, models, _ |
||||
|
from odoo.exceptions import ValidationError |
||||
|
|
||||
|
|
||||
|
class WebsiteBargain(models.Model): |
||||
|
"""This is the main class of website bargain where all the details are |
||||
|
stored in this model |
||||
|
_onchange_template_id: |
||||
|
function for automatically add the auction name |
||||
|
_check_end_date: |
||||
|
function to validate the end date if it is higher than the start |
||||
|
date |
||||
|
_check_extend_time: |
||||
|
function to validate extended time weather it is greater than end |
||||
|
time and after saving will send notification to subscribers if |
||||
|
enabled |
||||
|
action_confirm: |
||||
|
button function to confirm auction and will make product as |
||||
|
published |
||||
|
action_reset_to_draft: |
||||
|
button function to reset the auction to draft |
||||
|
action_run_auction: |
||||
|
button function to start auction manually |
||||
|
action_complete: |
||||
|
button function to end auction manually |
||||
|
action_close: |
||||
|
button function to close auction |
||||
|
send_email_notification: |
||||
|
Function for sending auction notification for admin |
||||
|
before ending if enabled |
||||
|
auction_auto_start: |
||||
|
Cron function for auction auto start when its start |
||||
|
time and also will send notification to customers about auction |
||||
|
""" |
||||
|
_name = 'website.bargain' |
||||
|
_description = "Website Bargain" |
||||
|
_inherit = ['mail.thread', 'mail.activity.mixin'] |
||||
|
|
||||
|
website_id = fields.Many2one('website', string='Website', required=True, |
||||
|
help="Add website here to put auction") |
||||
|
template_id = fields.Many2one('bargain.template', string='Template', |
||||
|
help="add already created templates of " |
||||
|
"auction with products") |
||||
|
auction_manager_id = fields.Many2one('res.users', string="Auction Manager", |
||||
|
help="Set suction manager here", |
||||
|
required=True) |
||||
|
product_id = fields.Many2one(related='template_id.product_id', store=True, |
||||
|
string='Product', readonly=False, |
||||
|
help="Select the product", required=True) |
||||
|
name = fields.Char(string='Auction Name', help="Auctions name") |
||||
|
currency_id = fields.Many2one('res.currency', 'Currency', |
||||
|
default=lambda |
||||
|
self: self.env.user.company_id.currency_id.id, |
||||
|
required=True, |
||||
|
help="if you select this " |
||||
|
"currency bidding will " |
||||
|
"be on that currency itself") |
||||
|
initial_price = fields.Monetary(string='Initial Price', |
||||
|
currency_field='currency_id', |
||||
|
required=True, |
||||
|
help="Minimum amount required to bid") |
||||
|
is_buy_now = fields.Boolean(string='Provide buy now button', |
||||
|
help='Enable a button for buying instantly') |
||||
|
price_buy_now = fields.Monetary(string='Buy Now Price', |
||||
|
currency_field='currency_id', |
||||
|
help="Price of the product if its" |
||||
|
" immediately buying") |
||||
|
start_time = fields.Datetime(string='Start Date Time', required=True, |
||||
|
default=fields.Datetime.today(), |
||||
|
help="Auction start time") |
||||
|
end_time = fields.Datetime(string='End Date Time', required=True, |
||||
|
help="Auction start time") |
||||
|
extend_time = fields.Datetime(string="Extended Time", |
||||
|
help="By setting days you can " |
||||
|
"extend the auction") |
||||
|
state = fields.Selection( |
||||
|
[('draft', "Draft"), ('confirmed', "Confirmed"), |
||||
|
('running', "Running"), |
||||
|
('closed', "Closed"), ('finished', "Finished")], default='draft') |
||||
|
bargain_information_ids = fields.One2many('bargain.information', |
||||
|
'auction_id', readonly=True) |
||||
|
bargain_subscribers_ids = fields.One2many('bargain.subscribers', |
||||
|
'auction_id') |
||||
|
is_activate = fields.Boolean(string='Activate', |
||||
|
help='this will activate ' |
||||
|
'notification for the admins') |
||||
|
notify_on = fields.Integer(string='Notify before', default='5', |
||||
|
help="Set notification time here") |
||||
|
notify_selection = fields.Selection( |
||||
|
[('days', "Days"), ('hours', "Hours"), ('minutes', "Minutes"), |
||||
|
('seconds', "Seconds")], default='minutes') |
||||
|
is_notification_send = fields.Boolean(string='Notification Send', |
||||
|
help='If notification send manually ' |
||||
|
'you can enable this field ' |
||||
|
'to restrict ' |
||||
|
'sending notification before ' |
||||
|
'the time added') |
||||
|
is_winner_notification = fields.Boolean( |
||||
|
string='Send Notification to Winner', |
||||
|
help='Enable this option to send notification to the winner') |
||||
|
is_loser_notification = fields.Boolean(string='Send Notification to Loser', |
||||
|
help='Enable this option to send ' |
||||
|
'notification to the losers') |
||||
|
is_subscriber_start_notification = fields.Boolean(string='Bidding Start', |
||||
|
help="Send subscribers " |
||||
|
"the bidding start " |
||||
|
"notification") |
||||
|
is_send_mail = fields.Boolean(string='Bidding Started Mail Sent', |
||||
|
help='If Bidding mail has been sent to customer') |
||||
|
is_extend_auction_notification = fields.Boolean(string='Auction Extended', |
||||
|
help="Send subscribers the" |
||||
|
"bidding extended " |
||||
|
"notification") |
||||
|
is_new_bid_notification = fields.Boolean(string='New Bid Placed', |
||||
|
help="Send subscribers " |
||||
|
"notifications if new bids" |
||||
|
" are placed") |
||||
|
is_bid_end_notification = fields.Boolean(string='Auction Finished', |
||||
|
help="Send subscribers " |
||||
|
"notifications if bidding " |
||||
|
"is over") |
||||
|
product_img = fields.Binary(related="product_id.image_1920") |
||||
|
product_description = fields.Text(related="product_id.description_sale", |
||||
|
string="Auction Product Description") |
||||
|
|
||||
|
@api.onchange('template_id', 'product_id') |
||||
|
def _onchange_template_id(self): |
||||
|
"""summary: |
||||
|
function to add name automatically""" |
||||
|
if self.product_id: |
||||
|
self.name = f"Auction for {self.product_id.name}" |
||||
|
|
||||
|
@api.constrains('end_time', 'start_time') |
||||
|
def _check_end_date(self): |
||||
|
""" |
||||
|
Summary: |
||||
|
start and end date validation function |
||||
|
""" |
||||
|
if self.end_time <= self.start_time: |
||||
|
raise ValidationError( |
||||
|
_('End time should be greater than start time')) |
||||
|
|
||||
|
@api.constrains('extend_time') |
||||
|
def _check_extend_time(self): |
||||
|
"""Summary: |
||||
|
function to validate extended time weather it is greater than |
||||
|
end time and after saving will send notification to subscribers |
||||
|
if enabled""" |
||||
|
if self.extend_time: |
||||
|
if self.extend_time <= self.end_time: |
||||
|
raise ValidationError( |
||||
|
_('This time is not greater than the old time(' + str( |
||||
|
self.end_time) + ')')) |
||||
|
if self.is_extend_auction_notification: |
||||
|
template_id = self.env.ref( |
||||
|
'website_bargain.email_template_auction_extended') |
||||
|
email_to = '' |
||||
|
for subscriber in self.bargain_subscribers_ids: |
||||
|
email_to += subscriber.email + ',' |
||||
|
template_id.email_to = email_to |
||||
|
template_id.send_mail(self.id, force_send=True) |
||||
|
|
||||
|
def action_confirm(self): |
||||
|
""" |
||||
|
Summary: |
||||
|
button function to confirm auction and will |
||||
|
make product as published |
||||
|
""" |
||||
|
if self.search([('product_id', '=', self.product_id.id), |
||||
|
('state', '=', 'running')]): |
||||
|
raise ValidationError( |
||||
|
_('Already an auction is running for this product please' |
||||
|
' close it to continue')) |
||||
|
if self.end_time <= fields.Datetime.today(): |
||||
|
raise ValidationError(_('End time is already over')) |
||||
|
self.product_id.is_published = True |
||||
|
self.product_id.website_id = self.website_id |
||||
|
self.write({'state': 'confirmed'}) |
||||
|
|
||||
|
def action_reset_to_draft(self): |
||||
|
""" |
||||
|
Summary: |
||||
|
button function to reset the auction to draft |
||||
|
""" |
||||
|
self.product_id.is_auction = False |
||||
|
self.write({'state': 'draft'}) |
||||
|
|
||||
|
def action_run_auction(self): |
||||
|
""" |
||||
|
Summary: |
||||
|
button function to start auction manually |
||||
|
""" |
||||
|
if self.search([('product_id', '=', self.product_id.id), |
||||
|
('state', '=', 'running')]): |
||||
|
raise ValidationError( |
||||
|
_('Already an auction is running for this product ' |
||||
|
'please close it to continue')) |
||||
|
self.product_id.is_auction = True |
||||
|
self.write({'state': 'running'}) |
||||
|
|
||||
|
def action_complete(self): |
||||
|
""" |
||||
|
Summary: |
||||
|
button function to end auction manually |
||||
|
""" |
||||
|
self.product_id.is_auction = False |
||||
|
self.product_id.is_published = False |
||||
|
self.write({'state': 'finished'}) |
||||
|
|
||||
|
def action_close(self): |
||||
|
""" |
||||
|
Summary: |
||||
|
button function to close auction |
||||
|
""" |
||||
|
self.product_id.is_auction = False |
||||
|
self.product_id.is_published = False |
||||
|
self.write({'state': 'closed'}) |
||||
|
|
||||
|
def send_email_notification(self): |
||||
|
""" |
||||
|
Summary: |
||||
|
Function for sending auction notification for admin e ending if |
||||
|
enabled |
||||
|
""" |
||||
|
# Get the email template for the admin notification |
||||
|
template_id = self.env.ref( |
||||
|
'website_bargain.admin_email_template') |
||||
|
# Find all running auctions that have notification enabled and have |
||||
|
# not been sent yet |
||||
|
auctions = self.search([('state', '=', 'running'), |
||||
|
('is_activate', '=', True), |
||||
|
('notify_on', '>', 0), |
||||
|
('is_notification_send', '=', False)]) |
||||
|
# Loop through the auctions that need to be notified |
||||
|
for auction in auctions: |
||||
|
# Map the time unit to a string for timedelta |
||||
|
time_unit_map = {'days': 'days', 'hours': 'hours', |
||||
|
'minutes': 'minutes', 'seconds': 'seconds'} |
||||
|
time_unit = time_unit_map.get(auction.notify_selection) |
||||
|
# Check if it's time to send the notification |
||||
|
if time_unit: |
||||
|
next_notification = auction.end_time - timedelta( |
||||
|
**{time_unit: auction.notify_on}) |
||||
|
if next_notification <= fields.Datetime.today(): |
||||
|
# Send the notification email and set the flag to True |
||||
|
template_id.send_mail(auction.id, force_send=True) |
||||
|
auction.is_notification_send = True |
||||
|
|
||||
|
def auction_auto_start(self): |
||||
|
""" |
||||
|
Summary: |
||||
|
Cron function for auction auto start when its start |
||||
|
time and also will send notification to customers about auction |
||||
|
""" |
||||
|
# Get all confirmed auctions |
||||
|
auctions = self.search([('state', '=', 'confirmed')]) |
||||
|
# Get the email template for auction start notification |
||||
|
template_id = self.env.ref( |
||||
|
'website_bargain.email_template_auction_start') |
||||
|
# Get the emails of all the bidders and sale order partners |
||||
|
bidders = self.env['bargain.information'].search([]).mapped( |
||||
|
'bidder_id.email') |
||||
|
sale_orders_partner = self.env['sale.order'].search( |
||||
|
[('state', '=', 'sale')]).mapped('partner_id.email') |
||||
|
# Loop through the auctions and check if any auction's start time has arrived |
||||
|
for auction in auctions: |
||||
|
if auction.start_time <= fields.Datetime.today(): |
||||
|
# Set the product as an auction and update the website |
||||
|
auction.product_id.is_auction = True |
||||
|
auction.product.website_id = auction.website_id |
||||
|
auction.write({'state': 'running'}) |
||||
|
# Send email notifications to all the bidders and sale order partners |
||||
|
email_to = "" |
||||
|
for partner in sale_orders_partner: |
||||
|
email_to += partner + ',' |
||||
|
for bidder in bidders: |
||||
|
email_to += bidder + ',' |
||||
|
template_id.email_to = email_to |
||||
|
template_id.send_mail(auction.id, force_send=True) |
|
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 628 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 210 KiB |
After Width: | Height: | Size: 209 KiB |
After Width: | Height: | Size: 109 KiB |
After Width: | Height: | Size: 495 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 624 B |
After Width: | Height: | Size: 136 KiB |
After Width: | Height: | Size: 214 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 929 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 542 B |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 733 B |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 738 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 600 B |
After Width: | Height: | Size: 673 B |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 462 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 926 B |
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 800 B |
After Width: | Height: | Size: 905 B |
After Width: | Height: | Size: 189 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 627 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 988 B |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 875 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 767 KiB |
After Width: | Height: | Size: 138 KiB |
After Width: | Height: | Size: 760 KiB |
After Width: | Height: | Size: 92 KiB |
After Width: | Height: | Size: 697 KiB |
After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 93 KiB |
After Width: | Height: | Size: 162 KiB |
After Width: | Height: | Size: 152 KiB |
After Width: | Height: | Size: 163 KiB |
After Width: | Height: | Size: 384 KiB |
After Width: | Height: | Size: 337 KiB |
After Width: | Height: | Size: 172 KiB |
After Width: | Height: | Size: 345 KiB |
After Width: | Height: | Size: 188 KiB |
After Width: | Height: | Size: 176 KiB |
After Width: | Height: | Size: 605 KiB |