270 lines
12 KiB
Python
270 lines
12 KiB
Python
from django.shortcuts import render, redirect, get_object_or_404
|
|
from django.db.models import Q
|
|
from django.contrib import messages
|
|
from .models import Voter, Tenant, Interaction, Donation, VoterLikelihood, EventParticipation, Event
|
|
from .forms import VoterForm, InteractionForm, DonationForm, VoterLikelihoodForm, EventParticipationForm
|
|
|
|
def index(request):
|
|
"""
|
|
Main landing page for Grassroots Campaign Manager.
|
|
Displays a list of campaigns if the user is logged in but hasn't selected one.
|
|
"""
|
|
tenants = Tenant.objects.all()
|
|
selected_tenant_id = request.session.get('tenant_id')
|
|
selected_tenant = None
|
|
if selected_tenant_id:
|
|
selected_tenant = Tenant.objects.filter(id=selected_tenant_id).first()
|
|
|
|
context = {
|
|
'tenants': tenants,
|
|
'selected_tenant': selected_tenant,
|
|
}
|
|
return render(request, 'core/index.html', context)
|
|
|
|
def select_campaign(request, tenant_id):
|
|
"""
|
|
Sets the selected campaign in the session.
|
|
"""
|
|
tenant = get_object_or_404(Tenant, id=tenant_id)
|
|
request.session['tenant_id'] = tenant.id
|
|
messages.success(request, f"You are now managing: {tenant.name}")
|
|
return redirect('index')
|
|
|
|
def voter_list(request):
|
|
"""
|
|
List and search voters. Restricted to selected tenant.
|
|
"""
|
|
selected_tenant_id = request.session.get('tenant_id')
|
|
if not selected_tenant_id:
|
|
messages.warning(request, "Please select a campaign first.")
|
|
return redirect('index')
|
|
|
|
tenant = get_object_or_404(Tenant, id=selected_tenant_id)
|
|
query = request.GET.get('q')
|
|
voters = Voter.objects.filter(tenant=tenant)
|
|
|
|
if query:
|
|
query = query.strip()
|
|
search_filter = Q(first_name__icontains=query) | Q(last_name__icontains=query) | Q(voter_id__icontains=query)
|
|
|
|
if " " in query:
|
|
parts = query.split()
|
|
if len(parts) >= 2:
|
|
first_part = parts[0]
|
|
last_part = " ".join(parts[1:])
|
|
search_filter |= Q(first_name__icontains=first_part, last_name__icontains=last_part)
|
|
|
|
voters = voters.filter(search_filter)
|
|
|
|
context = {
|
|
'voters': voters,
|
|
'query': query,
|
|
'selected_tenant': tenant
|
|
}
|
|
return render(request, 'core/voter_list.html', context)
|
|
|
|
def voter_detail(request, voter_id):
|
|
"""
|
|
360-degree view of a voter.
|
|
"""
|
|
selected_tenant_id = request.session.get('tenant_id')
|
|
if not selected_tenant_id:
|
|
messages.warning(request, "Please select a campaign first.")
|
|
return redirect('index')
|
|
|
|
tenant = get_object_or_404(Tenant, id=selected_tenant_id)
|
|
voter = get_object_or_404(Voter, id=voter_id, tenant=tenant)
|
|
|
|
context = {
|
|
'voter': voter,
|
|
'selected_tenant': tenant,
|
|
'voting_records': voter.voting_records.all().order_by('-election_date'),
|
|
'donations': voter.donations.all().order_by('-date'),
|
|
'interactions': voter.interactions.all().order_by('-date'),
|
|
'event_participations': voter.event_participations.all().order_by('-event__date'),
|
|
'likelihoods': voter.likelihoods.all(),
|
|
'voter_form': VoterForm(instance=voter),
|
|
'interaction_form': InteractionForm(tenant=tenant),
|
|
'donation_form': DonationForm(tenant=tenant),
|
|
'likelihood_form': VoterLikelihoodForm(tenant=tenant),
|
|
'event_participation_form': EventParticipationForm(tenant=tenant),
|
|
}
|
|
return render(request, 'core/voter_detail.html', context)
|
|
|
|
def voter_edit(request, voter_id):
|
|
"""
|
|
Update voter core demographics.
|
|
"""
|
|
selected_tenant_id = request.session.get('tenant_id')
|
|
tenant = get_object_or_404(Tenant, id=selected_tenant_id)
|
|
voter = get_object_or_404(Voter, id=voter_id, tenant=tenant)
|
|
|
|
if request.method == 'POST':
|
|
form = VoterForm(request.POST, instance=voter)
|
|
if form.is_valid():
|
|
form.save()
|
|
messages.success(request, "Voter profile updated successfully.")
|
|
return redirect('voter_detail', voter_id=voter.id)
|
|
return redirect('voter_detail', voter_id=voter.id)
|
|
|
|
def add_interaction(request, voter_id):
|
|
selected_tenant_id = request.session.get('tenant_id')
|
|
tenant = get_object_or_404(Tenant, id=selected_tenant_id)
|
|
voter = get_object_or_404(Voter, id=voter_id, tenant=tenant)
|
|
|
|
if request.method == 'POST':
|
|
form = InteractionForm(request.POST, tenant=tenant)
|
|
if form.is_valid():
|
|
interaction = form.save(commit=False)
|
|
interaction.voter = voter
|
|
interaction.save()
|
|
messages.success(request, "Interaction added.")
|
|
return redirect('voter_detail', voter_id=voter.id)
|
|
|
|
def edit_interaction(request, interaction_id):
|
|
selected_tenant_id = request.session.get('tenant_id')
|
|
tenant = get_object_or_404(Tenant, id=selected_tenant_id)
|
|
interaction = get_object_or_404(Interaction, id=interaction_id, voter__tenant=tenant)
|
|
|
|
if request.method == 'POST':
|
|
form = InteractionForm(request.POST, instance=interaction, tenant=tenant)
|
|
if form.is_valid():
|
|
form.save()
|
|
messages.success(request, "Interaction updated.")
|
|
return redirect('voter_detail', voter_id=interaction.voter.id)
|
|
|
|
def delete_interaction(request, interaction_id):
|
|
selected_tenant_id = request.session.get('tenant_id')
|
|
tenant = get_object_or_404(Tenant, id=selected_tenant_id)
|
|
interaction = get_object_or_404(Interaction, id=interaction_id, voter__tenant=tenant)
|
|
voter_id = interaction.voter.id
|
|
|
|
if request.method == 'POST':
|
|
interaction.delete()
|
|
messages.success(request, "Interaction deleted.")
|
|
return redirect('voter_detail', voter_id=voter_id)
|
|
|
|
def add_donation(request, voter_id):
|
|
selected_tenant_id = request.session.get('tenant_id')
|
|
tenant = get_object_or_404(Tenant, id=selected_tenant_id)
|
|
voter = get_object_or_404(Voter, id=voter_id, tenant=tenant)
|
|
|
|
if request.method == 'POST':
|
|
form = DonationForm(request.POST, tenant=tenant)
|
|
if form.is_valid():
|
|
donation = form.save(commit=False)
|
|
donation.voter = voter
|
|
donation.save()
|
|
messages.success(request, "Donation recorded.")
|
|
return redirect('voter_detail', voter_id=voter.id)
|
|
|
|
def edit_donation(request, donation_id):
|
|
selected_tenant_id = request.session.get('tenant_id')
|
|
tenant = get_object_or_404(Tenant, id=selected_tenant_id)
|
|
donation = get_object_or_404(Donation, id=donation_id, voter__tenant=tenant)
|
|
|
|
if request.method == 'POST':
|
|
form = DonationForm(request.POST, instance=donation, tenant=tenant)
|
|
if form.is_valid():
|
|
form.save()
|
|
messages.success(request, "Donation updated.")
|
|
return redirect('voter_detail', voter_id=donation.voter.id)
|
|
|
|
def delete_donation(request, donation_id):
|
|
selected_tenant_id = request.session.get('tenant_id')
|
|
tenant = get_object_or_404(Tenant, id=selected_tenant_id)
|
|
donation = get_object_or_404(Donation, id=donation_id, voter__tenant=tenant)
|
|
voter_id = donation.voter.id
|
|
|
|
if request.method == 'POST':
|
|
donation.delete()
|
|
messages.success(request, "Donation deleted.")
|
|
return redirect('voter_detail', voter_id=voter_id)
|
|
|
|
def add_likelihood(request, voter_id):
|
|
selected_tenant_id = request.session.get('tenant_id')
|
|
tenant = get_object_or_404(Tenant, id=selected_tenant_id)
|
|
voter = get_object_or_404(Voter, id=voter_id, tenant=tenant)
|
|
|
|
if request.method == 'POST':
|
|
form = VoterLikelihoodForm(request.POST, tenant=tenant)
|
|
if form.is_valid():
|
|
likelihood = form.save(commit=False)
|
|
likelihood.voter = voter
|
|
# Handle potential duplicate election_type
|
|
VoterLikelihood.objects.filter(voter=voter, election_type=likelihood.election_type).delete()
|
|
likelihood.save()
|
|
messages.success(request, "Likelihood updated.")
|
|
return redirect('voter_detail', voter_id=voter.id)
|
|
|
|
def edit_likelihood(request, likelihood_id):
|
|
selected_tenant_id = request.session.get('tenant_id')
|
|
tenant = get_object_or_404(Tenant, id=selected_tenant_id)
|
|
likelihood = get_object_or_404(VoterLikelihood, id=likelihood_id, voter__tenant=tenant)
|
|
|
|
if request.method == 'POST':
|
|
form = VoterLikelihoodForm(request.POST, instance=likelihood, tenant=tenant)
|
|
if form.is_valid():
|
|
# Check for conflict with another record of same election_type
|
|
election_type = form.cleaned_data['election_type']
|
|
if VoterLikelihood.objects.filter(voter=likelihood.voter, election_type=election_type).exclude(id=likelihood.id).exists():
|
|
VoterLikelihood.objects.filter(voter=likelihood.voter, election_type=election_type).exclude(id=likelihood.id).delete()
|
|
form.save()
|
|
messages.success(request, "Likelihood updated.")
|
|
return redirect('voter_detail', voter_id=likelihood.voter.id)
|
|
|
|
def delete_likelihood(request, likelihood_id):
|
|
selected_tenant_id = request.session.get('tenant_id')
|
|
tenant = get_object_or_404(Tenant, id=selected_tenant_id)
|
|
likelihood = get_object_or_404(VoterLikelihood, id=likelihood_id, voter__tenant=tenant)
|
|
voter_id = likelihood.voter.id
|
|
|
|
if request.method == 'POST':
|
|
likelihood.delete()
|
|
messages.success(request, "Likelihood record deleted.")
|
|
return redirect('voter_detail', voter_id=voter_id)
|
|
|
|
def add_event_participation(request, voter_id):
|
|
selected_tenant_id = request.session.get('tenant_id')
|
|
tenant = get_object_or_404(Tenant, id=selected_tenant_id)
|
|
voter = get_object_or_404(Voter, id=voter_id, tenant=tenant)
|
|
|
|
if request.method == 'POST':
|
|
form = EventParticipationForm(request.POST, tenant=tenant)
|
|
if form.is_valid():
|
|
participation = form.save(commit=False)
|
|
participation.voter = voter
|
|
# Avoid duplicate participation
|
|
if not EventParticipation.objects.filter(voter=voter, event=participation.event).exists():
|
|
participation.save()
|
|
messages.success(request, "Event participation added.")
|
|
else:
|
|
messages.warning(request, "Voter is already participating in this event.")
|
|
return redirect('voter_detail', voter_id=voter.id)
|
|
|
|
def edit_event_participation(request, participation_id):
|
|
selected_tenant_id = request.session.get('tenant_id')
|
|
tenant = get_object_or_404(Tenant, id=selected_tenant_id)
|
|
participation = get_object_or_404(EventParticipation, id=participation_id, voter__tenant=tenant)
|
|
|
|
if request.method == 'POST':
|
|
form = EventParticipationForm(request.POST, instance=participation, tenant=tenant)
|
|
if form.is_valid():
|
|
event = form.cleaned_data['event']
|
|
if EventParticipation.objects.filter(voter=participation.voter, event=event).exclude(id=participation.id).exists():
|
|
messages.warning(request, "Voter is already participating in that event.")
|
|
else:
|
|
form.save()
|
|
messages.success(request, "Event participation updated.")
|
|
return redirect('voter_detail', voter_id=participation.voter.id)
|
|
|
|
def delete_event_participation(request, participation_id):
|
|
selected_tenant_id = request.session.get('tenant_id')
|
|
tenant = get_object_or_404(Tenant, id=selected_tenant_id)
|
|
participation = get_object_or_404(EventParticipation, id=participation_id, voter__tenant=tenant)
|
|
voter_id = participation.voter.id
|
|
|
|
if request.method == 'POST':
|
|
participation.delete()
|
|
messages.success(request, "Event participation removed.")
|
|
return redirect('voter_detail', voter_id=voter_id) |