96 lines
3.7 KiB
Python
96 lines
3.7 KiB
Python
from django.db import models
|
|
from django.urls import reverse
|
|
|
|
class Voter(models.Model):
|
|
CANDIDATE_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'),
|
|
]
|
|
LIKELIHOOD_CHOICES = [(i, str(i)) for i in range(1, 6)]
|
|
|
|
voter_id = models.CharField(max_length=50, unique=True)
|
|
first_name = models.CharField(max_length=100)
|
|
last_name = models.CharField(max_length=100)
|
|
address = models.TextField()
|
|
phone = models.CharField(max_length=20, blank=True, null=True)
|
|
email = models.EmailField(blank=True, null=True)
|
|
|
|
# Demographics
|
|
district = models.CharField(max_length=100, blank=True, null=True)
|
|
precinct = models.CharField(max_length=100, blank=True, null=True)
|
|
registration_date = models.DateField(blank=True, null=True)
|
|
|
|
# Engagement
|
|
likelihood_to_vote = models.IntegerField(choices=LIKELIHOOD_CHOICES, default=3)
|
|
candidate_support = models.CharField(max_length=20, choices=CANDIDATE_SUPPORT_CHOICES, default='unknown')
|
|
yard_sign_status = models.CharField(max_length=20, choices=YARD_SIGN_CHOICES, default='none')
|
|
|
|
# Geocode (Optional for map integration later)
|
|
latitude = models.DecimalField(max_digits=9, decimal_places=6, blank=True, null=True)
|
|
longitude = models.DecimalField(max_digits=9, decimal_places=6, blank=True, null=True)
|
|
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
updated_at = models.DateTimeField(auto_now=True)
|
|
|
|
class Meta:
|
|
ordering = ['last_name', 'first_name']
|
|
|
|
def __str__(self):
|
|
return f"{self.first_name} {self.last_name} ({self.voter_id})"
|
|
|
|
def get_absolute_url(self):
|
|
return reverse('voter_detail', kwargs={'pk': self.pk})
|
|
|
|
class VotingRecord(models.Model):
|
|
voter = models.ForeignKey(Voter, on_delete=models.CASCADE, related_name='voting_records')
|
|
election_date = models.DateField()
|
|
description = models.CharField(max_length=255)
|
|
primary_party = models.CharField(max_length=50, blank=True, null=True)
|
|
|
|
def __str__(self):
|
|
return f"{self.voter.last_name} - {self.election_date}"
|
|
|
|
class Donation(models.Model):
|
|
METHOD_CHOICES = [
|
|
('Cash', 'Cash'),
|
|
('Check', 'Check'),
|
|
('Credit/Debit', 'Credit/Debit'),
|
|
]
|
|
voter = models.ForeignKey(Voter, on_delete=models.CASCADE, related_name='donations')
|
|
donation_date = models.DateField()
|
|
amount = models.DecimalField(max_digits=10, decimal_places=2)
|
|
method = models.CharField(max_length=20, choices=METHOD_CHOICES, default='Check')
|
|
|
|
def __str__(self):
|
|
return f"{self.voter.last_name} - ${self.amount} ({self.method})"
|
|
|
|
class VoterContact(models.Model):
|
|
CONTACT_TYPE_CHOICES = [
|
|
('Phone', 'Phone'),
|
|
('Door Visit', 'Door Visit'),
|
|
('Mail', 'Mail'),
|
|
]
|
|
voter = models.ForeignKey(Voter, on_delete=models.CASCADE, related_name='contacts')
|
|
contact_type = models.CharField(max_length=20, choices=CONTACT_TYPE_CHOICES)
|
|
contact_date = models.DateTimeField()
|
|
description = models.CharField(max_length=255)
|
|
notes = models.TextField(blank=True, null=True)
|
|
|
|
def __str__(self):
|
|
return f"{self.voter.last_name} - {self.contact_type} on {self.contact_date.date()}"
|
|
|
|
class EventParticipation(models.Model):
|
|
voter = models.ForeignKey(Voter, on_delete=models.CASCADE, related_name='event_participations')
|
|
event_date = models.DateField()
|
|
event_type = models.CharField(max_length=100)
|
|
description = models.TextField(blank=True, null=True)
|
|
|
|
def __str__(self):
|
|
return f"{self.voter.last_name} - {self.event_type} on {self.event_date}"
|