37769-vm/core/models.py
2026-01-24 06:32:35 +00:00

161 lines
6.0 KiB
Python

from django.db import models
from django.utils.text import slugify
from django.contrib.auth.models import User
class Tenant(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField(unique=True, blank=True)
description = models.TextField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.name)
super().save(*args, **kwargs)
def __str__(self):
return self.name
class TenantUserRole(models.Model):
ROLE_CHOICES = [
('system_admin', 'System Administrator'),
('campaign_admin', 'Campaign Administrator'),
('campaign_staff', 'Campaign Staff'),
]
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='tenant_roles')
tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, related_name='user_roles')
role = models.CharField(max_length=20, choices=ROLE_CHOICES)
class Meta:
unique_together = ('user', 'tenant', 'role')
def __str__(self):
return f"{self.user.username} - {self.tenant.name} ({self.role})"
class InteractionType(models.Model):
tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, related_name='interaction_types')
name = models.CharField(max_length=100)
class Meta:
unique_together = ('tenant', 'name')
def __str__(self):
return f"{self.name} ({self.tenant.name})"
class DonationMethod(models.Model):
tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, related_name='donation_methods')
name = models.CharField(max_length=100)
class Meta:
unique_together = ('tenant', 'name')
def __str__(self):
return f"{self.name} ({self.tenant.name})"
class ElectionType(models.Model):
tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, related_name='election_types')
name = models.CharField(max_length=100)
class Meta:
unique_together = ('tenant', 'name')
def __str__(self):
return f"{self.name} ({self.tenant.name})"
class Voter(models.Model):
SUPPORT_CHOICES = [
('unknown', 'Unknown'),
('supporting', 'Supporting'),
('not_supporting', 'Not Supporting'),
]
YARD_SIGN_CHOICES = [
('none', 'None'),
('wants', 'Wants a yard sign'),
('has', 'Has a yard sign'),
]
tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, related_name='voters')
voter_id = models.CharField(max_length=50, blank=True)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
# Separated address fields
street_address = models.CharField(max_length=255, blank=True)
city = models.CharField(max_length=100, blank=True)
state = models.CharField(max_length=50, blank=True)
zip_code = models.CharField(max_length=20, blank=True)
latitude = models.DecimalField(max_digits=9, decimal_places=6, null=True, blank=True)
longitude = models.DecimalField(max_digits=9, decimal_places=6, null=True, blank=True)
phone = models.CharField(max_length=20, blank=True)
email = models.EmailField(blank=True)
district = models.CharField(max_length=100, blank=True)
precinct = models.CharField(max_length=100, blank=True)
registration_date = models.DateField(null=True, blank=True)
candidate_support = models.CharField(max_length=20, choices=SUPPORT_CHOICES, default='unknown')
yard_sign = models.CharField(max_length=20, choices=YARD_SIGN_CHOICES, default='none')
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.first_name} {self.last_name}"
class VotingRecord(models.Model):
voter = models.ForeignKey(Voter, on_delete=models.CASCADE, related_name='voting_records')
election_date = models.DateField()
election_description = models.CharField(max_length=255)
primary_party = models.CharField(max_length=100, blank=True)
def __str__(self):
return f"{self.voter} - {self.election_description}"
class Event(models.Model):
tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, related_name='events')
date = models.DateField()
event_type = models.CharField(max_length=100)
description = models.TextField(blank=True)
def __str__(self):
return f"{self.event_type} on {self.date}"
class EventParticipation(models.Model):
event = models.ForeignKey(Event, on_delete=models.CASCADE, related_name='participations')
voter = models.ForeignKey(Voter, on_delete=models.CASCADE, related_name='event_participations')
def __str__(self):
return f"{self.voter} at {self.event}"
class Donation(models.Model):
voter = models.ForeignKey(Voter, on_delete=models.CASCADE, related_name='donations')
date = models.DateField()
method = models.ForeignKey(DonationMethod, on_delete=models.SET_NULL, null=True)
amount = models.DecimalField(max_digits=10, decimal_places=2)
def __str__(self):
return f"{self.voter} - {self.amount} on {self.date}"
class Interaction(models.Model):
voter = models.ForeignKey(Voter, on_delete=models.CASCADE, related_name='interactions')
type = models.ForeignKey(InteractionType, on_delete=models.SET_NULL, null=True)
date = models.DateField()
description = models.CharField(max_length=255)
notes = models.TextField(blank=True)
def __str__(self):
return f"{self.voter} - {self.type} on {self.date}"
class VoterLikelihood(models.Model):
LIKELIHOOD_CHOICES = [
('not_likely', 'Not Likely'),
('somewhat_likely', 'Somewhat Likely'),
('very_likely', 'Very Likely'),
]
voter = models.ForeignKey(Voter, on_delete=models.CASCADE, related_name='likelihoods')
election_type = models.ForeignKey(ElectionType, on_delete=models.CASCADE)
likelihood = models.CharField(max_length=20, choices=LIKELIHOOD_CHOICES)
class Meta:
unique_together = ('voter', 'election_type')
def __str__(self):
return f"{self.voter} - {self.election_type}: {self.get_likelihood_display()}"