refactor sales tasks and split them up

pull/3/head
lance 5 years ago
parent 0da090270f
commit e13d551824

@ -0,0 +1,42 @@
from django.conf import settings
from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.urls import reverse
class EmailTemplate:
def __init__(self, item, scenario, role):
context = {
'sale': item,
'site_name': settings.SITE_NAME,
'site_url': settings.SITE_URL,
'sale_path': reverse('get_sale', args=[item.id])
}
subject = render_to_string(
template_name=f'sales/notify/{scenario}/{role}/subject.txt',
context=context,
request=None
)
body = render_to_string(
template_name=f'sales/notify/{scenario}/{role}/body.txt',
context=context,
request=None
)
self.subject = ''.join(subject.splitlines())
self.body = body
self.role = role
self.item = item
def send(self):
if self.role == 'buyer':
to_address = self.item.bid.bidder.email
else:
to_address = self.item.item.owner.email
res = send_mail(
self.subject,
self.body,
settings.DEFAULT_FROM_EMAIL,
[to_address]
)
return res

@ -0,0 +1 @@
from sales.tasks import notifications, payments, cleanup

@ -0,0 +1,12 @@
import logging
from huey import crontab
from huey.contrib.djhuey import periodic_task
logger = logging.getLogger('django.server')
@periodic_task(crontab(minute='0', hour='*/12'))
def close_completed_items_sales():
item_sales = ItemSale.objects.filter(platform_paid=True, sale_finalized=True)
for sale in item_sales:
logger.info(f'[INFO] Deleting item #{sale.item.id} and all accompanying bids, sales, meta, etc.')
sale.item.delete()

@ -0,0 +1,54 @@
import logging
from huey import crontab
from huey.contrib.djhuey import periodic_task
from core.helpers.email_template import EmailTemplate
from core.models import UserShippingAddress
from sales.models import ItemSale
logger = logging.getLogger('django.server')
@periodic_task(crontab(minute='*'))
def notify_buyer_of_pending_sale():
item_sales = ItemSale.objects.filter(buyer_notified=False, sale_cancelled=False)
for sale in item_sales:
logger.info(f'[INFO] Sale #{sale.id} just created, notifying buyer.')
email_template = EmailTemplate(
item=sale,
scenario='sale_created',
role='buyer'
)
email_template.send()
sale.buyer_notified = True
sale.save()
@periodic_task(crontab(minute='*'))
def notify_seller_of_funds_received():
item_sales = ItemSale.objects.filter(seller_notified=False, buyer_notified=True).filter(payment_received=True)
for sale in item_sales:
logger.info(f'[INFO] Funds received from buyer for sale #{sale.id}, notifying seller.')
email_template = EmailTemplate(
item=sale,
scenario='funds_received',
role='seller'
)
email_template.send()
sale.seller_notified = True
sale.save()
@periodic_task(crontab(minute='*'))
def notify_buyer_of_shipment_confirmation():
item_sales = ItemSale.objects.filter(item_shipped=True).filter(buyer_notified_of_shipment=False)
for sale in item_sales:
logger.info(f'[INFO] Item shipped for sale #{sale.id}, notifying buyer.')
email_template = EmailTemplate(
item=sale,
scenario='item_shipped',
role='buyer'
)
email_template.send()
bidder_profile = UserShippingAddress.objects.get(user=sale.bid.bidder)
bidder_profile.delete()
logger.info(f'[INFO] Buyer shipping info wiped for sale #{sale.id}')
sale.buyer_notified_of_shipment = True
sale.save()

@ -3,110 +3,17 @@ from decimal import Decimal
from huey import crontab from huey import crontab
from huey.contrib.djhuey import periodic_task from huey.contrib.djhuey import periodic_task
from django.conf import settings from django.conf import settings
from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.urls import reverse
from core.monero import AuctionWallet from core.monero import AuctionWallet
from core.models import UserShippingAddress
from sales.models import ItemSale from sales.models import ItemSale
logger = logging.getLogger('django.server') logger = logging.getLogger('django.server')
class EmailTemplate: @periodic_task(crontab(minute='*/3'))
def __init__(self, item, scenario, role):
context = {
'sale': item,
'site_name': settings.SITE_NAME,
'site_url': settings.SITE_URL,
'sale_path': reverse('get_sale', args=[item.id])
}
subject = render_to_string(
template_name=f'sales/notify/{scenario}/{role}/subject.txt',
context=context,
request=None
)
body = render_to_string(
template_name=f'sales/notify/{scenario}/{role}/body.txt',
context=context,
request=None
)
self.subject = ''.join(subject.splitlines())
self.body = body
self.role = role
self.item = item
def send(self):
if self.role == 'buyer':
to_address = self.item.bid.bidder.email
else:
to_address = self.item.item.owner.email
res = send_mail(
self.subject,
self.body,
settings.DEFAULT_FROM_EMAIL,
[to_address]
)
return res
### Notifications
@periodic_task(crontab(minute='*'))
def notify_buyer_of_pending_sale():
item_sales = ItemSale.objects.filter(buyer_notified=False, sale_cancelled=False)
for sale in item_sales:
logger.info(f'[INFO] Sale #{sale.id} just created, notifying buyer.')
email_template = EmailTemplate(
item=sale,
scenario='sale_created',
role='buyer'
)
email_template.send()
sale.buyer_notified = True
sale.save()
@periodic_task(crontab(minute='*'))
def notify_seller_of_funds_received():
item_sales = ItemSale.objects.filter(seller_notified=False, buyer_notified=True).filter(payment_received=True)
for sale in item_sales:
logger.info(f'[INFO] Funds received from buyer for sale #{sale.id}, notifying seller.')
email_template = EmailTemplate(
item=sale,
scenario='funds_received',
role='seller'
)
email_template.send()
sale.seller_notified = True
sale.save()
@periodic_task(crontab(minute='*'))
def notify_buyer_of_shipment_confirmation():
item_sales = ItemSale.objects.filter(item_shipped=True).filter(buyer_notified_of_shipment=False)
for sale in item_sales:
logger.info(f'[INFO] Item shipped for sale #{sale.id}, notifying buyer.')
email_template = EmailTemplate(
item=sale,
scenario='item_shipped',
role='buyer'
)
email_template.send()
bidder_profile = UserShippingAddress.objects.get(user=sale.bid.bidder)
bidder_profile.delete()
logger.info(f'[INFO] Buyer shipping info wiped for sale #{sale.id}')
sale.buyer_notified_of_shipment = True
sale.save()
### Payments
@periodic_task(crontab(minute='*'))
def poll_for_buyer_escrow_payments(): def poll_for_buyer_escrow_payments():
aw = AuctionWallet() aw = AuctionWallet()
if aw.connected is False: if aw.connected is False:
logging.error('Auction wallet is not connected. Quitting.') logging.error('[ERROR] Auction wallet is not connected. Quitting.')
return False return False
item_sales = ItemSale.objects.filter(payment_received=False) item_sales = ItemSale.objects.filter(payment_received=False)
@ -121,12 +28,11 @@ def poll_for_buyer_escrow_payments():
sale.save() sale.save()
@periodic_task(crontab(minute='*/3'))
@periodic_task(crontab(minute='*'))
def pay_sellers_on_sold_items(): def pay_sellers_on_sold_items():
aw = AuctionWallet() aw = AuctionWallet()
if aw.connected is False: if aw.connected is False:
logging.error('Auction wallet is not connected. Quitting.') logging.error('[ERROR] Auction wallet is not connected. Quitting.')
return False return False
item_sales = ItemSale.objects.filter(item_received=True, payment_received=True).filter(seller_paid=False) item_sales = ItemSale.objects.filter(item_received=True, payment_received=True).filter(seller_paid=False)
@ -142,7 +48,6 @@ def pay_sellers_on_sold_items():
sale.item.payout_address, Decimal(.01), relay=False sale.item.payout_address, Decimal(.01), relay=False
) )
new_total = sale_total - float(_tx[0].fee) new_total = sale_total - float(_tx[0].fee)
logger.info(f'[INFO] Sending {new_total} XMR from wallet account #{sale.escrow_account_index} to item owner\'s payout address for sale #{sale.id}.') logger.info(f'[INFO] Sending {new_total} XMR from wallet account #{sale.escrow_account_index} to item owner\'s payout address for sale #{sale.id}.')
# Make the transaction with network fee removed # Make the transaction with network fee removed
tx = sale_account.transfer( tx = sale_account.transfer(
@ -172,7 +77,7 @@ def pay_sellers_on_sold_items():
def pay_platform_on_sold_items(): def pay_platform_on_sold_items():
aw = AuctionWallet() aw = AuctionWallet()
if aw.connected is False: if aw.connected is False:
logging.error('Auction wallet is not connected. Quitting.') logging.error('[ERROR] Auction wallet is not connected. Quitting.')
return False return False
aof = settings.PLATFORM_WALLET_ADDRESS aof = settings.PLATFORM_WALLET_ADDRESS
@ -201,18 +106,11 @@ def pay_platform_on_sold_items():
else: else:
logger.warning(f'[WARNING] Not enough unlocked funds available in account #{sale.escrow_account_index} for sale #{sale.id}.') logger.warning(f'[WARNING] Not enough unlocked funds available in account #{sale.escrow_account_index} for sale #{sale.id}.')
@periodic_task(crontab(minute='0', hour='*/12'))
def close_completed_items_sales():
item_sales = ItemSale.objects.filter(platform_paid=True, sale_finalized=True)
for sale in item_sales:
logger.info(f'[INFO] Deleting item #{sale.item.id} and all accompanying bids, sales, meta, etc.')
sale.item.delete()
@periodic_task(crontab(minute='*')) @periodic_task(crontab(minute='*'))
def closed_cancelled_sales(): def closed_cancelled_sales():
aw = AuctionWallet() aw = AuctionWallet()
if aw.connected is False: if aw.connected is False:
logging.error('Auction wallet is not connected. Quitting.') logging.error('[ERROR] Auction wallet is not connected. Quitting.')
return False return False
item_sales = ItemSale.objects.filter(sale_cancelled=True) item_sales = ItemSale.objects.filter(sale_cancelled=True)