From c6f18d9a888436097ff9aabc7cd6fd812e40fab4 Mon Sep 17 00:00:00 2001 From: lalanza808 Date: Fri, 10 Jan 2020 22:59:40 -0800 Subject: [PATCH] setup logging and refactor tasks --- sales/tasks.py | 192 +++++++++++++----------------- web/static/css/style.css | 2 +- web/templates/sales/get_sale.html | 11 +- 3 files changed, 93 insertions(+), 112 deletions(-) diff --git a/sales/tasks.py b/sales/tasks.py index 28e0f0c..d95c1d5 100644 --- a/sales/tasks.py +++ b/sales/tasks.py @@ -1,3 +1,4 @@ +import logging from decimal import Decimal from huey import crontab from huey.contrib.djhuey import periodic_task @@ -10,6 +11,8 @@ from core.models import UserShippingAddress from sales.models import ItemSale +logger = logging.getLogger('django.server') + class EmailTemplate: def __init__(self, item, scenario, role): context = { @@ -48,116 +51,116 @@ class EmailTemplate: return res -@periodic_task(crontab(minute='*/3')) +### 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' ) - sent = email_template.send() - if sent == 1: - sale.buyer_notified = True - sale.save() - return True - else: - return False + email_template.send() + sale.buyer_notified = True + sale.save() -@periodic_task(crontab(minute='*/3')) -def notify_buyer_of_shipment_confirmation(): - item_sales = ItemSale.objects.filter(item_shipped=True).filter(buyer_notified_of_shipment=False) +@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='item_shipped', - role='buyer' + scenario='funds_received', + role='seller' ) - sent = email_template.send() - if sent == 1: - sale.buyer_notified_of_shipment = True - sale.save() - bidder_profile = UserShippingAddress.objects.get(user=sale.bid.bidder) - bidder_profile.delete() - return True - else: - return False + email_template.send() + sale.seller_notified = True + sale.save() -@periodic_task(crontab(minute='*/3')) -def notify_seller_of_shipment_receipt(): - item_sales = ItemSale.objects.filter(item_shipped=True, item_received=False).filter(seller_notified_of_receipt=False) +@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' ) - sent = email_template.send() - if sent == 1: - sale.seller_notified_of_receipt = True - sale.save() - return True - else: - return False + 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() -@periodic_task(crontab(minute='*/5')) -def notify_seller_of_funds_received(): - item_sales = ItemSale.objects.filter(seller_notified=False, buyer_notified=True).filter(payment_received=True) + +### Payments + +@periodic_task(crontab(minute='*')) +def poll_for_buyer_escrow_payments(): + aw = AuctionWallet() + if aw.connected is False: + logging.error('Auction wallet is not connected. Quitting.') + return False + + item_sales = ItemSale.objects.filter(payment_received=False) for sale in item_sales: - email_template = EmailTemplate( - item=sale, - scenario='funds_received', - role='seller' - ) - sent = email_template.send() - if sent == 1: - sale.seller_notified = True - sale.save() - return True - else: - return False + logger.info(f'[INFO] Polling escrow address #{sale.escrow_account_index} for sale #{sale.id} for new funds.') + sale_account = aw.wallet.accounts[sale.escrow_account_index] + balance = sale_account.balances()[1] + sale.received_payment_xmr = balance + if balance >= Decimal(sale.expected_payment_xmr): + logger.info(f'[INFO] Found payment of {sale.received_payment_xmr} XMR for sale #{sale.id}.') + sale.payment_received = True + + sale.save() + -@periodic_task(crontab(minute='*/10')) +@periodic_task(crontab(minute='*/5')) def pay_sellers_on_sold_items(): aw = AuctionWallet() if aw.connected is False: + logging.error('Auction wallet is not connected. Quitting.') return False item_sales = ItemSale.objects.filter(item_received=True, payment_received=True).filter(seller_paid=False) for sale in item_sales: - try: - print(f'sending agreed payment, {sale.agreed_price_xmr} XMR, from account index #{sale.escrow_account_index} to {sale.item.owner.username} for sale #{sale.id} ({sale.item.name})') - sale_account = aw.wallet.accounts[sale.escrow_account_index] - if sale_account.balances()[1] > Decimal(0.0): + logger.info(f'[INFO] Sending {sale.agreed_price_xmr} XMR from wallet account #{sale.escrow_account_index} to item owner\'s payout address for sale #{sale.id}.') + sale_account = aw.wallet.accounts[sale.escrow_account_index] + if sale_account.balances()[1] > Decimal(sale.agreed_price_xmr): + try: aw.wallet.accounts[sale.escrow_account_index].transfer( - sale.item.payout_address, sale.agreed_price_xmr, relay=True + sale.item.payout_address, sale.agreed_price_xmr ) sale.seller_paid = True sale.escrow_complete = True sale.save() - else: - print('not enough funds here to transfer. try later') - return False - except Exception as e: - print('unable to make payment: ', e) - return False - - email_template = EmailTemplate( - item=sale, - scenario='sale_completed', - role='seller' - ) - - if sale.seller_notified_of_payout is False: + except Exception as e: + logger.error(f'[ERROR] Unable to pay seller for sale #{sale.id}: ') + else: + logger.warning(f'[WARNING] Not enough unlocked funds available in account #{sale.escrow_account_index} for sale #{sale.id}.') + + if sale.seller_paid and sale.seller_notified_of_payout is False: + email_template = EmailTemplate( + item=sale, + scenario='sale_completed', + role='seller' + ) sent = email_template.send() sale.seller_notified_of_payout = True sale.save() -@periodic_task(crontab(hour='*/3')) +@periodic_task(crontab(minute='0', hour='*')) def pay_platform_on_sold_items(): aw = AuctionWallet() if aw.connected is False: + logging.error('Auction wallet is not connected. Quitting.') return False aof = settings.PLATFORM_WALLET_ADDRESS @@ -166,68 +169,43 @@ def pay_platform_on_sold_items(): item_sales = ItemSale.objects.filter(escrow_complete=True, seller_paid=True, item_received=True).filter(platform_paid=False) for sale in item_sales: + logger.info(f'[INFO] Paying platform fees for sale #{sale.id} to wallet {aof}.') sale_account = aw.wallet.accounts[sale.escrow_account_index] - try: - if sale_account.balances()[1] >= Decimal(0.0): - print(f'paying out platform wallet, {aof}, remaining funds in account #{sale.escrow_account_index} for sale #{sale.id}') + if sale_account.balances()[1] >= Decimal(0.0): + try: aw.wallet.accounts[sale.escrow_account_index].sweep_all(aof) sale.platform_paid = True sale.sale_finalized = True sale.save() return True - else: - print('not enough funds here to sweep. try later') - return False - except Exception as e: - print('unable to sweep funds: ', e) - return False - - -@periodic_task(crontab(minute='*/3')) -def poll_for_buyer_escrow_payments(): - aw = AuctionWallet() - if aw.connected is False: - return False - - item_sales = ItemSale.objects.filter(payment_received=False) - for sale in item_sales: - sale_account = aw.wallet.accounts[sale.escrow_account_index] - - sale.received_payment_xmr = sale_account.balance() - - if sale_account.balance() >= Decimal(str(sale.expected_payment_xmr)): - sale.payment_received = True - - sale.save() - - if settings.DEBUG: - print('[+] Sale: #{} - Balance: {} - Payment Received: {}'.format( - sale.id, sale.received_payment_xmr, sale.payment_received - )) + except Exception as e: + logger.error(f'[ERROR] Unable to pay platform for sale #{sale.id} - trying again') + else: + logger.warning(f'[WARNING] Not enough unlocked funds available in account #{sale.escrow_account_index} for sale #{sale.id}.') -@periodic_task(crontab(hour='*/8')) +@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: - print(f'deleting item #{sale.item.id} and all accompanying bids, sales, meta') + logger.info(f'[INFO] Deleting item #{sale.item.id} and all accompanying bids, sales, meta, etc.') sale.item.delete() -@periodic_task(crontab(minute='*/6')) +@periodic_task(crontab(minute='*')) def closed_cancelled_sales(): aw = AuctionWallet() if aw.connected is False: + logging.error('Auction wallet is not connected. Quitting.') return False item_sales = ItemSale.objects.filter(sale_cancelled=True) for sale in item_sales: - print(f'deleting sale #{sale.id} and transferring back any sent funds to the buyer') + logger.info(f'[INFO] Deleting sale #{sale.id} and transferring back any sent funds to the buyer.') sale_account = aw.wallet.accounts[sale.escrow_account_index] - if sale_account.balance() > Decimal(0.0): + if sale_account.balances()[0] > Decimal(0.0): try: sale_account.sweep_all(sale.bid.return_address) sale.delete() except Exception as e: - print('unable to sweep all: ', e) - return False + logger.error(f'[ERROR] Unable to return funds to use for sale #{sale.id}.') else: sale.delete() diff --git a/web/static/css/style.css b/web/static/css/style.css index 392dac0..5230dd5 100644 --- a/web/static/css/style.css +++ b/web/static/css/style.css @@ -1144,7 +1144,7 @@ New color: fd4e05 box-sizing: border-box; } -.sale-qrcode { +.center { display: block; margin: 0 auto; } diff --git a/web/templates/sales/get_sale.html b/web/templates/sales/get_sale.html index c243d99..45ac242 100644 --- a/web/templates/sales/get_sale.html +++ b/web/templates/sales/get_sale.html @@ -17,7 +17,7 @@

Expected Payment (XMR): {{ sale.expected_payment_xmr }}

Escrow Address: {{ sale.escrow_address }}

- +

Need a Wallet?

@@ -53,11 +53,13 @@ When it does arrive please click the button below to confirm.

Stay tuned for updates and thanks for using {{ site_meta.name }}!

- +

+

Click here when you have received your package:

Confirm Item Received

+
{% elif sale.item_received %}

Hey {{ sale.bid.bidder.username }},

It sounds like your order was successful. The seller will be sent their funds from the transaction out of the escrow wallet. You are good to go!

@@ -97,7 +99,8 @@

State: {{ shipping_address.state }}

Country: {{ shipping_address.country }}

Zip: {{ shipping_address.zip }}

-

If you have shipped the item please confirm by clicking this button:

+
+

If you have shipped the item, and only if you have shipped the item, please confirm by clicking this button:

Confirm Item Shipped

{% else %}
@@ -108,7 +111,7 @@

Hello {{ sale.item.owner.username }},

You've shipped the item, now you need to wait for the buyer to confirm they received it on their end.

Stay tuned for updates and thanks for using {{ site_meta.name }}!

- + {% elif sale.item_received %}

Hey {{ sale.item.owner.username }},

The buyer confirmed receipt of their shipment which means things worked out. It's time for you to get paid!