import logging import stripe from io import BytesIO from django.db.models.signals import post_save from django.dispatch import receiver from django.db import models from django.conf import settings from . import OrderStatus, TransactionStatus from .models import ( Product, ProductVariant, Order, OrderLine, Transaction, TrackingNumber ) from .tasks import ( send_order_confirmation_email, send_order_shipped_email ) logger = logging.getLogger(__name__) stripe.api_key = settings.STRIPE_API_KEY def format_order_lines(lines): for line in lines: yield { 'variant': str(line.variant), 'customer_note': line.customer_note, 'quantity': line.quantity, 'unit_price': str(line.unit_price) } @receiver(post_save, sender=Order, dispatch_uid="order_created") def order_created(sender, instance, created, **kwargs): if created: logger.info("Order was created") Transaction.objects.create(order=instance) @receiver(post_save, sender=Transaction, dispatch_uid="transaction_created") def transaction_created(sender, instance, created, **kwargs): if created: logger.info("Transaction was created") elif instance.status == TransactionStatus.COMPLETED and not instance.confirmation_email_sent: # TODO: change order to order.values() order = { 'order_id': instance.order.pk, 'email': instance.order.customer.email, 'full_name': instance.order.customer.get_full_name(), 'subtotal_amount': str(instance.order.subtotal_amount), 'coupon_amount': str(instance.order.coupon_amount), 'shipping_total': str(instance.order.shipping_total), 'total_amount': str(instance.order.total_amount), 'shipping_address': { 'first_name': instance.order.shipping_first_name, 'last_name': instance.order.shipping_last_name, 'street_address_1': instance.order.shipping_street_address_1, 'street_address_2': instance.order.shipping_street_address_2, 'city': instance.order.shipping_city, 'state': instance.order.shipping_state, 'postal_code': instance.order.shipping_postal_code }, 'line_items': list( format_order_lines(instance.order.lines.all()) ) } send_order_confirmation_email.delay(order) instance.confirmation_email_sent = True instance.save() @receiver(post_save, sender=TrackingNumber, dispatch_uid="trackingnumber_postsave") def trackingnumber_postsave(sender, instance, created, **kwargs): if created: logger.info("TrackingNumber was created") data = { 'order_id': instance.order.pk, 'email': instance.order.customer.email, 'full_name': instance.order.customer.get_full_name(), 'tracking_id': instance.tracking_id } send_order_shipped_email.delay(data) def get_order_status(total_quantity_fulfilled, total_quantity_ordered): if total_quantity_fulfilled >= total_quantity_ordered: return OrderStatus.FULFILLED elif total_quantity_fulfilled > 0: return OrderStatus.PARTIALLY_FULFILLED else: return OrderStatus.UNFULFILLED @receiver(post_save, sender=OrderLine, dispatch_uid="order_line_post_save") def order_line_post_save(sender, instance, created, **kwargs): if not created: order = Order.objects.with_fulfillment().filter( pk=instance.order.pk )[0] order.status = get_order_status( order.total_quantity_fulfilled, order.total_quantity_ordered ) order.save() # order.update( # status=models.Case( # models.When(models.lookups.GreaterThan(models.F('total_quantity_fulfilled'), models.F('total_quantity_ordered')), # then=models.Value(OrderStatus.FULFILLED)), # models.When(models.lookups.GreaterThan(models.F('total_quantity_fulfilled'), 0), # then=models.Value(OrderStatus.PARTIALLY_FULFILLED)), # default=models.Value(OrderStatus.UNFULFILLED) # ) # )