37769-vm/core/forms.py
2026-02-03 13:35:39 +00:00

393 lines
18 KiB
Python

from django import forms
from django.contrib.auth.models import User
from .models import Voter, Interaction, Donation, VoterLikelihood, InteractionType, DonationMethod, ElectionType, Event, EventParticipation, EventType, Tenant, ParticipationStatus, Volunteer, VolunteerEvent, VolunteerRole, ScheduledCall
class VoterForm(forms.ModelForm):
class Meta:
model = Voter
fields = [
'first_name', 'last_name', 'nickname', 'birthdate', 'address_street', 'city', 'state', 'prior_state',
'zip_code', 'county', 'neighborhood', 'latitude', 'longitude',
'phone', 'phone_type', 'secondary_phone', 'secondary_phone_type', 'email', 'voter_id', 'district', 'precinct',
'registration_date', 'is_targeted', 'door_visit', 'candidate_support', 'yard_sign', 'window_sticker', 'notes'
]
widgets = {
'birthdate': forms.DateInput(attrs={'type': 'date'}),
'registration_date': forms.DateInput(attrs={'type': 'date'}),
'latitude': forms.TextInput(attrs={'class': 'form-control bg-light'}),
'longitude': forms.TextInput(attrs={'class': 'form-control bg-light'}),
'notes': forms.Textarea(attrs={'rows': 3}),
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for name, field in self.fields.items():
if name in ['latitude', 'longitude']:
continue
if isinstance(field.widget, forms.CheckboxInput):
field.widget.attrs.update({'class': 'form-check-input'})
else:
field.widget.attrs.update({'class': 'form-control'})
self.fields['candidate_support'].widget.attrs.update({'class': 'form-select'})
self.fields['yard_sign'].widget.attrs.update({'class': 'form-select'})
self.fields['window_sticker'].widget.attrs.update({'class': 'form-select'})
self.fields['phone_type'].widget.attrs.update({'class': 'form-select'})
self.fields['secondary_phone_type'].widget.attrs.update({'class': 'form-select'})
class AdvancedVoterSearchForm(forms.Form):
MONTH_CHOICES = [
('', 'Any Month'),
(1, 'January'), (2, 'February'), (3, 'March'), (4, 'April'),
(5, 'May'), (6, 'June'), (7, 'July'), (8, 'August'),
(9, 'September'), (10, 'October'), (11, 'November'), (12, 'December')
]
first_name = forms.CharField(required=False)
last_name = forms.CharField(required=False)
address = forms.CharField(required=False)
voter_id = forms.CharField(required=False, label="Voter ID")
birth_month = forms.ChoiceField(choices=MONTH_CHOICES, required=False, label="Birth Month")
city = forms.CharField(required=False)
zip_code = forms.CharField(required=False)
neighborhood = forms.CharField(required=False)
district = forms.CharField(required=False)
precinct = forms.CharField(required=False)
phone_type = forms.ChoiceField(
choices=[('', 'Any')] + Voter.PHONE_TYPE_CHOICES,
required=False
)
is_targeted = forms.BooleanField(required=False, label="Targeted Only")
door_visit = forms.BooleanField(required=False, label="Visited Only")
candidate_support = forms.ChoiceField(
choices=[('', 'Any')] + Voter.SUPPORT_CHOICES,
required=False
)
yard_sign = forms.ChoiceField(
choices=[('', 'Any')] + Voter.YARD_SIGN_CHOICES,
required=False
)
window_sticker = forms.ChoiceField(
choices=[('', 'Any')] + Voter.WINDOW_STICKER_CHOICES,
required=False
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields.values():
if isinstance(field.widget, forms.CheckboxInput):
field.widget.attrs.update({'class': 'form-check-input'})
else:
field.widget.attrs.update({'class': 'form-control'})
self.fields['birth_month'].widget.attrs.update({'class': 'form-select'})
self.fields['candidate_support'].widget.attrs.update({'class': 'form-select'})
self.fields['yard_sign'].widget.attrs.update({'class': 'form-select'})
self.fields['window_sticker'].widget.attrs.update({'class': 'form-select'})
self.fields['phone_type'].widget.attrs.update({'class': 'form-select'})
class InteractionForm(forms.ModelForm):
class Meta:
model = Interaction
fields = ['type', 'volunteer', 'date', 'description', 'notes']
widgets = {
'date': forms.DateTimeInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%dT%H:%M'),
'notes': forms.Textarea(attrs={'rows': 2}),
}
def __init__(self, *args, tenant=None, **kwargs):
super().__init__(*args, **kwargs)
if tenant:
self.fields['type'].queryset = InteractionType.objects.filter(tenant=tenant, is_active=True)
self.fields['volunteer'].queryset = Volunteer.objects.filter(tenant=tenant)
for field in self.fields.values():
field.widget.attrs.update({'class': 'form-control'})
self.fields['type'].widget.attrs.update({'class': 'form-select'})
self.fields['volunteer'].widget.attrs.update({'class': 'form-select'})
if self.instance and self.instance.date:
self.initial['date'] = self.instance.date.strftime('%Y-%m-%dT%H:%M')
class DonationForm(forms.ModelForm):
class Meta:
model = Donation
fields = ['date', 'method', 'amount']
widgets = {
'date': forms.DateInput(attrs={'type': 'date'}),
}
def __init__(self, *args, tenant=None, **kwargs):
super().__init__(*args, **kwargs)
if tenant:
self.fields['method'].queryset = DonationMethod.objects.filter(tenant=tenant, is_active=True)
for field in self.fields.values():
field.widget.attrs.update({'class': 'form-control'})
self.fields['method'].widget.attrs.update({'class': 'form-select'})
class VoterLikelihoodForm(forms.ModelForm):
class Meta:
model = VoterLikelihood
fields = ['election_type', 'likelihood']
def __init__(self, *args, tenant=None, **kwargs):
super().__init__(*args, **kwargs)
if tenant:
self.fields['election_type'].queryset = ElectionType.objects.filter(tenant=tenant, is_active=True)
for field in self.fields.values():
field.widget.attrs.update({'class': 'form-control'})
self.fields['election_type'].widget.attrs.update({'class': 'form-select'})
self.fields['likelihood'].widget.attrs.update({'class': 'form-select'})
class EventParticipationForm(forms.ModelForm):
class Meta:
model = EventParticipation
fields = ['event', 'participation_status']
def __init__(self, *args, tenant=None, **kwargs):
super().__init__(*args, **kwargs)
if tenant:
self.fields['event'].queryset = Event.objects.filter(tenant=tenant)
self.fields['participation_status'].queryset = ParticipationStatus.objects.filter(tenant=tenant, is_active=True)
for field in self.fields.values():
field.widget.attrs.update({'class': 'form-control'})
self.fields['event'].widget.attrs.update({'class': 'form-select'})
self.fields['participation_status'].widget.attrs.update({'class': 'form-select'})
class EventParticipantAddForm(forms.ModelForm):
class Meta:
model = EventParticipation
fields = ['voter', 'participation_status']
def __init__(self, *args, tenant=None, **kwargs):
super().__init__(*args, **kwargs)
if tenant:
voter_id = self.data.get('voter') or self.initial.get('voter')
if voter_id:
self.fields['voter'].queryset = Voter.objects.filter(tenant=tenant, id=voter_id)
else:
self.fields['voter'].queryset = Voter.objects.none()
self.fields['participation_status'].queryset = ParticipationStatus.objects.filter(tenant=tenant, is_active=True)
for field in self.fields.values():
field.widget.attrs.update({'class': 'form-control'})
self.fields['voter'].widget.attrs.update({'class': 'form-select'})
self.fields['participation_status'].widget.attrs.update({'class': 'form-select'})
class EventForm(forms.ModelForm):
class Meta:
model = Event
fields = ['name', 'date', 'start_time', 'end_time', 'event_type', 'default_volunteer_role', 'description', 'location_name', 'address', 'city', 'state', 'zip_code', 'latitude', 'longitude']
widgets = {
'date': forms.DateInput(attrs={'type': 'date'}),
'start_time': forms.TimeInput(attrs={'type': 'time'}),
'end_time': forms.TimeInput(attrs={'type': 'time'}),
'description': forms.Textarea(attrs={'rows': 2}),
}
def __init__(self, *args, tenant=None, **kwargs):
super().__init__(*args, **kwargs)
if tenant:
self.fields['event_type'].queryset = EventType.objects.filter(tenant=tenant, is_active=True)
self.fields['default_volunteer_role'].queryset = VolunteerRole.objects.filter(tenant=tenant, is_active=True)
for field in self.fields.values():
field.widget.attrs.update({'class': 'form-control'})
self.fields['event_type'].widget.attrs.update({'class': 'form-select'})
self.fields['default_volunteer_role'].widget.attrs.update({'class': 'form-select'})
class VoterImportForm(forms.Form):
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), label="Campaign")
file = forms.FileField(label="Select CSV file")
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tenant'].widget.attrs.update({'class': 'form-control form-select'})
self.fields['file'].widget.attrs.update({'class': 'form-control'})
class EventImportForm(forms.Form):
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), label="Campaign")
file = forms.FileField(label="Select CSV file")
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tenant'].widget.attrs.update({'class': 'form-control form-select'})
self.fields['file'].widget.attrs.update({'class': 'form-control'})
class EventParticipationImportForm(forms.Form):
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), label="Campaign")
file = forms.FileField(label="Select CSV file")
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tenant'].widget.attrs.update({'class': 'form-control form-select'})
self.fields['file'].widget.attrs.update({'class': 'form-control'})
class DonationImportForm(forms.Form):
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), label="Campaign")
file = forms.FileField(label="Select CSV file")
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tenant'].widget.attrs.update({'class': 'form-control form-select'})
self.fields['file'].widget.attrs.update({'class': 'form-control'})
class InteractionImportForm(forms.Form):
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), label="Campaign")
file = forms.FileField(label="Select CSV file")
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tenant'].widget.attrs.update({'class': 'form-control form-select'})
self.fields['file'].widget.attrs.update({'class': 'form-control'})
class VoterLikelihoodImportForm(forms.Form):
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), label="Campaign")
file = forms.FileField(label="Select CSV file")
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tenant'].widget.attrs.update({'class': 'form-control form-select'})
self.fields['file'].widget.attrs.update({'class': 'form-control'})
class VolunteerImportForm(forms.Form):
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), label="Campaign")
file = forms.FileField(label="Select CSV file")
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tenant'].widget.attrs.update({'class': 'form-control form-select'})
self.fields['file'].widget.attrs.update({'class': 'form-control'})
class VolunteerForm(forms.ModelForm):
class Meta:
model = Volunteer
fields = ['first_name', 'last_name', 'email', 'phone', 'is_default_caller', 'notes', 'interests']
widgets = {'notes': forms.Textarea(attrs={'rows': 3})}
def __init__(self, *args, tenant=None, **kwargs):
super().__init__(*args, **kwargs)
if tenant:
from .models import Interest
self.fields['interests'].queryset = Interest.objects.filter(tenant=tenant)
for field in self.fields.values():
if not isinstance(field.widget, forms.CheckboxInput):
field.widget.attrs.update({'class': 'form-control'})
else:
field.widget.attrs.update({'class': 'form-check-input'})
self.fields['interests'].widget.attrs.update({'class': 'form-select tom-select'})
class VolunteerEventForm(forms.ModelForm):
class Meta:
model = VolunteerEvent
fields = ['event', 'role_type']
def __init__(self, *args, tenant=None, **kwargs):
super().__init__(*args, **kwargs)
if tenant:
self.fields['event'].queryset = Event.objects.filter(tenant=tenant)
for field in self.fields.values():
field.widget.attrs.update({'class': 'form-control'})
self.fields['event'].widget.attrs.update({'class': 'form-select'})
class VolunteerEventAddForm(forms.ModelForm):
class Meta:
model = VolunteerEvent
fields = ['volunteer', 'role_type']
def __init__(self, *args, tenant=None, **kwargs):
super().__init__(*args, **kwargs)
if tenant:
volunteer_id = self.data.get('volunteer') or self.initial.get('volunteer')
if volunteer_id:
self.fields['volunteer'].queryset = Volunteer.objects.filter(tenant=tenant, id=volunteer_id)
else:
self.fields['volunteer'].queryset = Volunteer.objects.none()
for field in self.fields.values():
field.widget.attrs.update({'class': 'form-control'})
self.fields['volunteer'].widget.attrs.update({'class': 'form-select'})
class VotingRecordImportForm(forms.Form):
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), label="Campaign")
file = forms.FileField(label="Select CSV file")
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tenant'].widget.attrs.update({'class': 'form-control form-select'})
self.fields['file'].widget.attrs.update({'class': 'form-control'})
class DoorVisitLogForm(forms.Form):
OUTCOME_CHOICES = [
("No Answer Left Literature", "No Answer Left Literature"),
("Spoke to voter", "Spoke to voter"),
("No Access to House", "No Access to House"),
]
outcome = forms.ChoiceField(
choices=OUTCOME_CHOICES,
widget=forms.RadioSelect(attrs={"class": "btn-check"}),
label="Outcome"
)
notes = forms.CharField(
widget=forms.Textarea(attrs={"class": "form-control", "rows": 3}),
required=False,
label="Notes"
)
wants_yard_sign = forms.BooleanField(
required=False,
widget=forms.CheckboxInput(attrs={"class": "form-check-input"}),
label="Wants a Yard Sign"
)
candidate_support = forms.ChoiceField(
choices=Voter.SUPPORT_CHOICES,
initial="unknown",
widget=forms.Select(attrs={"class": "form-select"}),
label="Candidate Support"
)
follow_up = forms.BooleanField(
required=False,
widget=forms.CheckboxInput(attrs={"class": "form-check-input"}),
label="Follow Up"
)
follow_up_voter = forms.CharField( required=False, widget=forms.Select(attrs={"class": "form-select"}), label="Voter to Follow Up")
call_notes = forms.CharField(
widget=forms.Textarea(attrs={"class": "form-control", "rows": 2}),
required=False,
label="Call Notes"
)
class ScheduledCallForm(forms.ModelForm):
class Meta:
model = ScheduledCall
fields = ['volunteer', 'comments']
widgets = {
'comments': forms.Textarea(attrs={'rows': 3}),
}
def __init__(self, *args, tenant=None, **kwargs):
super().__init__(*args, **kwargs)
if tenant:
self.fields['volunteer'].queryset = Volunteer.objects.filter(tenant=tenant)
default_caller = Volunteer.objects.filter(tenant=tenant, is_default_caller=True).first()
if default_caller:
self.initial['volunteer'] = default_caller
for field in self.fields.values():
field.widget.attrs.update({'class': 'form-control'})
self.fields['volunteer'].widget.attrs.update({'class': 'form-select'})
class UserUpdateForm(forms.ModelForm):
class Meta:
model = User
fields = ['first_name', 'last_name', 'email']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs.update({'class': 'form-control'})
class VolunteerProfileForm(forms.ModelForm):
class Meta:
model = Volunteer
fields = ['phone']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs.update({'class': 'form-control'})