Initial working version with minor bugs
This commit is contained in:
parent
f946e4933a
commit
71b3993326
83 changed files with 34485 additions and 173 deletions
72
trades/models.py
Normal file
72
trades/models.py
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
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"])
|
||||
Loading…
Add table
Add a link
Reference in a new issue