Fix create trade offer flow and other related bugs

This commit is contained in:
badblocks 2025-03-26 11:38:02 -07:00
parent f3a1366269
commit 65ca344582
40 changed files with 867 additions and 278 deletions

View file

@ -1,13 +1,16 @@
from django.db import models
from django.core.exceptions import ValidationError
from django.db.models import Q, Count, Prefetch, F, Sum
from django.db.models import Q, Count, Prefetch, F, Sum, Max
import hashlib
from cards.models import Card
from accounts.models import FriendCode
from datetime import timedelta
from django.utils import timezone
class TradeOfferManager(models.Manager):
def get_queryset(self):
queryset = super().get_queryset().select_related(
qs = super().get_queryset().select_related(
"initiated_by__user",
).prefetch_related(
"trade_offer_have_cards__card",
@ -16,8 +19,11 @@ class TradeOfferManager(models.Manager):
"acceptances__requested_card",
"acceptances__offered_card",
"acceptances__accepted_by__user",
).order_by("-updated_at")
return queryset
)
cutoff = timezone.now() - timedelta(days=28)
qs = qs.filter(created_at__gte=cutoff)
return qs.order_by("-updated_at")
class TradeOffer(models.Model):
objects = TradeOfferManager()
@ -57,6 +63,29 @@ class TradeOffer(models.Model):
self.hash = hashlib.md5((str(self.id) + "z").encode("utf-8")).hexdigest()[:8] + "z"
super().save(update_fields=["hash"])
def update_rarity_fields(self):
"""
Recalculates and updates the rarity_level and rarity_icon fields based on
the associated have_cards and want_cards.
Enforces that all cards in the trade offer share the same rarity.
Uses the first card's rarity details to update both fields.
"""
# Gather all cards from both sides.
cards = list(self.have_cards.all()) + list(self.want_cards.all())
if not cards:
return
# Enforce same rarity across all cards.
rarity_levels = {card.rarity_level for card in cards}
if len(rarity_levels) > 1:
raise ValidationError("All cards in a trade offer must have the same rarity.")
first_card = cards[0]
if self.rarity_level != first_card.rarity_level or self.rarity_icon != first_card.rarity_icon:
self.rarity_level = first_card.rarity_level
self.rarity_icon = first_card.rarity_icon
# Use super().save() here to avoid recursion.
super(TradeOffer, self).save(update_fields=["rarity_level", "rarity_icon"])
class TradeOfferHaveCard(models.Model):
"""
Through model for TradeOffer.have_cards.
@ -70,12 +99,20 @@ class TradeOfferHaveCard(models.Model):
)
card = models.ForeignKey("cards.Card", on_delete=models.PROTECT, db_index=True)
quantity = models.PositiveIntegerField(default=1)
# New field to track number of accepted cards for this entry.
qty_accepted = models.PositiveIntegerField(default=0, editable=False)
def __str__(self):
return f"{self.card.name} x{self.quantity} (Accepted: {self.qty_accepted})"
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
self.trade_offer.update_rarity_fields()
def delete(self, *args, **kwargs):
trade_offer = self.trade_offer
super().delete(*args, **kwargs)
trade_offer.update_rarity_fields()
class Meta:
unique_together = ("trade_offer", "card")
@ -91,12 +128,20 @@ class TradeOfferWantCard(models.Model):
)
card = models.ForeignKey("cards.Card", on_delete=models.PROTECT)
quantity = models.PositiveIntegerField(default=1)
# New field for tracking accepted count.
qty_accepted = models.PositiveIntegerField(default=0, editable=False)
def __str__(self):
return f"{self.card.name} x{self.quantity} (Accepted: {self.qty_accepted})"
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
self.trade_offer.update_rarity_fields()
def delete(self, *args, **kwargs):
trade_offer = self.trade_offer
super().delete(*args, **kwargs)
trade_offer.update_rarity_fields()
class Meta:
unique_together = ("trade_offer", "card")