Added logic to handle IntegrityError by generating unique human-readable IDs for orders during creation. This ensures no duplicate order entries are created in case of integrity constraints.
119 lines
4.8 KiB
Python
119 lines
4.8 KiB
Python
import logging
|
|
from datetime import timedelta
|
|
|
|
from django.db import IntegrityError
|
|
from django.db.models.signals import post_save
|
|
from django.dispatch import receiver
|
|
from django.utils.crypto import get_random_string
|
|
from django.utils.http import urlsafe_base64_decode
|
|
from django.utils.timezone import now
|
|
from django.utils.translation import gettext_lazy as _
|
|
from sentry_sdk import capture_exception
|
|
|
|
from core.models import Category, Order, Product, PromoCode, Wishlist
|
|
from core.utils import generate_human_readable_id, resolve_translations_for_elasticsearch
|
|
from core.utils.emailing import send_order_created_email, send_order_finished_email
|
|
from evibes.utils.misc import create_object
|
|
from vibes_auth.models import User
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@receiver(post_save, sender=User)
|
|
def create_order_on_user_creation_signal(instance, created, **kwargs):
|
|
if created:
|
|
try:
|
|
Order.objects.create(user=instance, status="PENDING")
|
|
except IntegrityError:
|
|
human_readable_id = generate_human_readable_id()
|
|
while True:
|
|
if Order.objects.filter(human_readable_id=human_readable_id).exists():
|
|
human_readable_id = generate_human_readable_id()
|
|
continue
|
|
Order.objects.create(user=instance, status="PENDING", human_readable_id=human_readable_id)
|
|
break
|
|
|
|
|
|
@receiver(post_save, sender=User)
|
|
def create_wishlist_on_user_creation_signal(instance, created, **kwargs):
|
|
if created:
|
|
Wishlist.objects.create(user=instance)
|
|
|
|
|
|
@receiver(post_save, sender=User)
|
|
def create_promocode_on_user_referring(instance, created, **kwargs):
|
|
try:
|
|
if created and instance.attributes.get("referrer", ""):
|
|
referrer_uuid = urlsafe_base64_decode(instance.attributes.get("referrer", ""))
|
|
referrer = User.objects.get(uuid=referrer_uuid)
|
|
code = f"WELCOME-{get_random_string(6)}"
|
|
PromoCode.objects.create(
|
|
user=referrer,
|
|
code=code if len(code) <= 20 else code[:20],
|
|
discount_percent=10,
|
|
start_time=now(),
|
|
end_time=now() + timedelta(days=30),
|
|
)
|
|
except Exception as e:
|
|
capture_exception(e)
|
|
logger.error(_(f"error during promocode creation: {e!s}"))
|
|
|
|
|
|
@receiver(post_save, sender=Order)
|
|
def process_order_changes(instance, created, **kwargs):
|
|
if not created:
|
|
if instance.status != "PENDING":
|
|
pending_orders = Order.objects.filter(user=instance.user, status="PENDING")
|
|
|
|
if not pending_orders.exists():
|
|
try:
|
|
Order.objects.create(user=instance.user, status="PENDING")
|
|
except IntegrityError:
|
|
human_readable_id = generate_human_readable_id()
|
|
while True:
|
|
if Order.objects.filter(human_readable_id=human_readable_id).exists():
|
|
human_readable_id = generate_human_readable_id()
|
|
continue
|
|
Order.objects.create(user=instance, status="PENDING", human_readable_id=human_readable_id)
|
|
break
|
|
|
|
if instance.status == "CREATED":
|
|
if not instance.is_whole_digital:
|
|
send_order_created_email.delay(instance.uuid)
|
|
instance.status = "DELIVERING"
|
|
instance.save()
|
|
for order_product in instance.order_products.filter(status="DELIVERING"):
|
|
if not order_product.product.is_digital:
|
|
continue
|
|
try:
|
|
vendor_name = (
|
|
order_product.product.stocks.filter(price=order_product.buy_price).first().vendor.name.lower()
|
|
)
|
|
|
|
vendor = create_object(f"core.vendors.{vendor_name}", f"{vendor_name.title()}Vendor")
|
|
|
|
vendor.buy_order_product(order_product)
|
|
|
|
except Exception as e:
|
|
order_product.add_error(f"Failed to buy {order_product.uuid}. Reason: {e}...")
|
|
|
|
instance.finalize()
|
|
|
|
if instance.order_products.filter(status="FAILED").count() == instance.order_products.count():
|
|
instance.status = "FAILED"
|
|
instance.save()
|
|
|
|
if instance.status == "FINISHED":
|
|
send_order_finished_email.delay(instance.uuid)
|
|
|
|
|
|
@receiver(post_save, sender=Product)
|
|
def update_product_name_lang(instance, created, **kwargs):
|
|
resolve_translations_for_elasticsearch(instance, "name")
|
|
resolve_translations_for_elasticsearch(instance, "description")
|
|
|
|
|
|
@receiver(post_save, sender=Category)
|
|
def update_category_name_lang(instance, created, **kwargs):
|
|
resolve_translations_for_elasticsearch(instance, "name")
|
|
resolve_translations_for_elasticsearch(instance, "description")
|