from django.core.exceptions import ValidationError from django.db.models.signals import m2m_changed, post_save, post_delete from django.dispatch import receiver from .models import TradeOffer from cards.models import Card from trades.models import TradeOfferHaveCard, TradeOfferWantCard, TradeAcceptance def check_trade_offer_rarity(instance): combined_cards = list(instance.have_cards.all()) + list(instance.want_cards.all()) # Use the normalized rarity from each card rarities = {card.normalized_rarity for card in combined_cards} if len(rarities) > 1: raise ValidationError("All cards in a trade offer must have the same rarity.") @receiver(m2m_changed, sender=TradeOffer.have_cards.through) def validate_have_cards_rarity(sender, instance, action, **kwargs): if action == "post_add": check_trade_offer_rarity(instance) @receiver(m2m_changed, sender=TradeOffer.want_cards.through) def validate_want_cards_rarity(sender, instance, action, **kwargs): if action == "post_add": check_trade_offer_rarity(instance) ACTIVE_STATES = [ TradeAcceptance.AcceptanceState.ACCEPTED, TradeAcceptance.AcceptanceState.SENT, TradeAcceptance.AcceptanceState.RECEIVED, TradeAcceptance.AcceptanceState.THANKED_BY_INITIATOR, TradeAcceptance.AcceptanceState.THANKED_BY_ACCEPTOR, TradeAcceptance.AcceptanceState.THANKED_BY_BOTH, ] def update_qty_for_trade_offer(trade_offer, card, side): if side == 'have': count = TradeAcceptance.objects.filter( trade_offer=trade_offer, requested_card=card, state__in=ACTIVE_STATES ).count() TradeOfferHaveCard.objects.filter( trade_offer=trade_offer, card=card ).update(qty_accepted=count) if count >= TradeOfferHaveCard.objects.filter(trade_offer=trade_offer, card=card).first().quantity: trade_offer.is_closed = True trade_offer.save(update_fields=["is_closed"]) elif side == 'want': count = TradeAcceptance.objects.filter( trade_offer=trade_offer, offered_card=card, state__in=ACTIVE_STATES ).count() TradeOfferWantCard.objects.filter( trade_offer=trade_offer, card=card ).update(qty_accepted=count) if count >= TradeOfferWantCard.objects.filter(trade_offer=trade_offer, card=card).first().quantity: trade_offer.is_closed = True trade_offer.save(update_fields=["is_closed"]) def update_all_qty(instance): trade_offer = instance.trade_offer update_qty_for_trade_offer(trade_offer, instance.requested_card, 'have') update_qty_for_trade_offer(trade_offer, instance.offered_card, 'want') @receiver(post_save, sender=TradeAcceptance) def trade_acceptance_post_save(sender, instance, **kwargs): update_all_qty(instance) @receiver(post_delete, sender=TradeAcceptance) def trade_acceptance_post_delete(sender, instance, **kwargs): update_all_qty(instance)