pkmntrade.club/trades/models.py

72 lines
2.9 KiB
Python

from django.db import models
import hashlib # <-- import hashlib for computing md5
from cards.models import Card
from friend_codes.models import FriendCode
class TradeOffer(models.Model):
id = models.AutoField(primary_key=True)
hash = models.CharField(max_length=8, editable=False)
initiated_by = models.ForeignKey("friend_codes.FriendCode", on_delete=models.PROTECT, related_name='initiated_by')
accepted_by = models.ForeignKey("friend_codes.FriendCode", on_delete=models.PROTECT, null=True, blank=True, related_name='accepted_by')
want_cards = models.ManyToManyField("cards.Card", related_name='trade_offers_want')
have_cards = models.ManyToManyField("cards.Card", related_name='trade_offers_have')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class State(models.TextChoices):
INITIATED = 'INITIATED', 'Initiated'
ACCEPTED = 'ACCEPTED', 'Accepted'
SENT = 'SENT', 'Sent'
RECEIVED = 'RECEIVED', 'Received'
state = models.CharField(
max_length=10,
choices=State.choices,
default=State.INITIATED,
)
def __str__(self):
return f"Want: {', '.join([x.name for x in self.want_cards.all()])} -> Have: {', '.join([x.name for x in self.have_cards.all()])}"
def update_state(self, new_state):
"""
Explicitly update the trade state to new_state if allowed.
Allowed transitions:
- INITIATED -> ACCEPTED
- ACCEPTED -> SENT
- SENT -> RECEIVED
Raises:
ValueError: If the new_state is not allowed.
"""
allowed_transitions = {
self.State.INITIATED: self.State.ACCEPTED,
self.State.ACCEPTED: self.State.SENT,
self.State.SENT: self.State.RECEIVED
}
# Check that new_state is one of the defined State choices
if new_state not in [choice[0] for choice in self.State.choices]:
raise ValueError(f"'{new_state}' is not a valid state.")
# If the current state is already final, no further transition is allowed.
if self.state not in allowed_transitions:
raise ValueError(f"No transitions allowed from the final state '{self.state}'.")
# Verify that the desired new_state is the valid transition for the current state.
if allowed_transitions[self.state] != new_state:
raise ValueError(f"Transition from {self.state} to {new_state} is not allowed.")
self.state = new_state
# Save all changes so that any in-memory modifications (like accepted_by) are persisted.
self.save() # Changed from self.save(update_fields=["state"])
def save(self, *args, **kwargs):
# Determine if the object is being created (i.e. it doesn't yet have a pk)
is_new = self.pk is None
super().save(*args, **kwargs)
# Once the object has a pk, compute and save the hash if it hasn't been set yet.
if is_new and not self.hash:
self.hash = hashlib.md5(str(self.id).encode('utf-8')).hexdigest()[:8]
super().save(update_fields=["hash"])