import uuid from datetime import timedelta from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager from django.db import models from django.db.models.signals import post_save from django.dispatch import receiver from django.urls import reverse from django.utils import timezone class UserManager(BaseUserManager): def create_user(self, email): user = self.model(email=email) user.set_unusable_password() user.save(using=self._db) return user def create_superuser(self, email, password): user = self.model(email=email, is_staff=True, is_superuser=True) user.set_password(password) user.save(using=self._db) return user class LoginToken(models.Model): email = models.EmailField() uid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) class User(AbstractBaseUser): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) email = models.EmailField(unique=True) username = models.CharField(max_length=35, unique=True, null=True, blank=True) searchable = models.BooleanField(default=False) palette = models.CharField(max_length=32, default="palette-default") stripe_customer_id = models.CharField(max_length=255, null=True, blank=True) is_staff = models.BooleanField(default=False) is_superuser = models.BooleanField(default=False) objects = UserManager() REQUIRED_FIELDS = [] USERNAME_FIELD = "email" def has_perm(self, perm, obj=None): return self.is_superuser def has_module_perms(self, app_label): return self.is_superuser class Wallet(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="wallet") writs = models.IntegerField(default=0) esteem = models.IntegerField(default=0) def tooltip_name(self): return "Wallet" def tooltip_description(self): return f"{self.writs} writs ยท {self.esteem} esteem" def tooltip_shoptalk(self): return None def tooltip_expiry(self): return None def tooltip_text(self): return f"{self.tooltip_name()}: {self.tooltip_description()}" class Token(models.Model): COIN = "coin" FREE = "Free" TITHE = "tithe" PASS = "pass" TOKEN_TYPE_CHOICES = [ (COIN, "Coin-on-a-String"), (FREE, "Free Token"), (TITHE, "Tithe Token"), (PASS, "Backstage Pass"), ] user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="tokens") token_type = models.CharField(max_length=8, choices=TOKEN_TYPE_CHOICES) expires_at = models.DateTimeField(null=True, blank=True) current_room = models.ForeignKey( "epic.Room", null=True, blank=True, on_delete=models.SET_NULL, related_name="coin_tokens" ) next_ready_at = models.DateTimeField(null=True, blank=True) def tooltip_name(self): return self.get_token_type_display() def tooltip_description(self): if self.token_type in (self.COIN, self.FREE): return "Admit 1 Entry" if self.token_type == self.PASS: return "Admit All Entry" if self.token_type == self.TITHE: return "+ Writ bonus" return "" def tooltip_expiry(self): if self.token_type in (self.COIN, self.PASS): if self.token_type == self.COIN and self.next_ready_at: return f"Ready {self.next_ready_at.strftime('%Y-%m-%d')}" return "no expiry" if self.expires_at: return f"Expires {self.expires_at.strftime('%Y-%m-%d')}" return "" def tooltip_room_html(self): if not self.current_room_id: return "" url = reverse("epic:gatekeeper", kwargs={"room_id": self.current_room_id}) return f'{self.current_room.name}' def tooltip_shoptalk(self): if self.token_type == self.COIN: return "\u2026and another after that, and another after that\u2026" if self.token_type == self.PASS: return "\u2018Entry fee\u2019? Pal, do you know who you\u2019re talking to?" return None def tooltip_text(self): text = f"{self.tooltip_name()}: {self.tooltip_description()}" if self.tooltip_shoptalk(): text += f" ({self.tooltip_shoptalk()})" text += f" \u2014 {self.tooltip_expiry()}" return text class PaymentMethod(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="payment_methods") stripe_pm_id = models.CharField(max_length=255) last4 = models.CharField(max_length=4) brand = models.CharField(max_length=32) def __str__(self): return f"{self.brand} ....{self.last4}" @receiver(post_save, sender=User) def create_wallet_and_tokens(sender, instance, created, **kwargs): if not created: return Wallet.objects.create(user=instance, writs=144) Token.objects.create(user=instance, token_type=Token.COIN) Token.objects.create( user=instance, token_type=Token.FREE, expires_at=timezone.now() + timedelta(days=7), ) if instance.is_staff: Token.objects.create(user=instance, token_type=Token.PASS)