37769-vm/fix_voter_search_v2.py
2026-05-30 08:01:02 +00:00

128 lines
5.8 KiB
Python

import os
with open('core/views.py', 'r') as f:
content = f.read()
import_snippet = """from django.db.models import Q, Sum, Value, DecimalField
from django.db.models.functions import Coalesce"""
# Make sure imports are there if they aren't
if "from django.db.models import Q, Sum, Value, DecimalField" not in content:
content = content.replace("from django.db.models import Q", "from django.db.models import Q, Sum, Value, DecimalField")
if "from django.db.models.functions import Coalesce" not in content:
content = "from django.db.models.functions import Coalesce\n" + content
# Define the new voter_advanced_search function
new_voter_advanced_search = """@role_required(["admin", "campaign_manager", "campaign_staff", "system_admin", "campaign_admin"], permission="core.view_voter")
def voter_advanced_search(request):
"""
Advanced search for voters with multiple filters.
"""
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)
voters = Voter.objects.filter(tenant=tenant, is_inactive=False).order_by("last_name", "first_name")
form = AdvancedVoterSearchForm(request.GET)
if form.is_valid():
data = form.cleaned_data
if data.get('first_name'):
voters = voters.filter(first_name__icontains=data['first_name'])
if data.get('last_name'):
voters = voters.filter(last_name__icontains=data['last_name'])
if data.get('address'):
voters = voters.filter(Q(address__icontains=data['address']) | Q(address_street__icontains=data['address']))
if data.get('voter_id'):
voters = voters.filter(voter_id__iexact=data['voter_id'])
if data.get('birth_month'):
voters = voters.filter(birthdate__month=data['birth_month'])
if data.get('city'):
voters = voters.filter(city__icontains=data['city'])
if data.get('zip_code'):
voters = voters.filter(zip_code__icontains=data['zip_code'])
if data.get('neighborhood'):
voters = voters.filter(neighborhood__icontains=data['neighborhood'])
if data.get('district'):
voters = voters.filter(district=data['district'])
if data.get('precinct'):
voters = voters.filter(precinct=data['precinct'])
if data.get('email'):
voters = voters.filter(email__icontains=data['email'])
if data.get('phone'):
voters = voters.filter(get_phone_search_filters(data['phone']))
if data.get('phone_type'):
voters = voters.filter(phone_type=data['phone_type'])
if data.get('is_targeted'):
voters = voters.filter(is_targeted=(data['is_targeted'] == 'True'))
if data.get('target_door_visit'):
voters = voters.filter(target_door_visit=(data['target_door_visit'] == 'True'))
if data.get('door_visit'):
voters = voters.filter(door_visit=(data['door_visit'] == 'True'))
if data.get('voted'):
voters = voters.filter(voted=(data['voted'] == 'True'))
if data.get('candidate_support'):
voters = voters.filter(candidate_support=data['candidate_support'])
if data.get('yard_sign'):
voters = voters.filter(yard_sign=data['yard_sign'])
if data.get('window_sticker'):
voters = voters.filter(window_sticker=data['window_sticker'])
if data.get('call_queue_status'):
voters = voters.filter(call_queue_status=data['call_queue_status'])
# Add donation amount filters
min_total_donation = data.get('min_total_donation')
max_total_donation = data.get('max_total_donation')
if min_total_donation is not None or max_total_donation is not None:
# Annotate each voter with their total donation amount, treating no donations as 0
voters = voters.annotate(total_donation_amount=Coalesce(Sum('donations__amount'), Value(0), output_field=DecimalField()))
if min_total_donation is not None:
voters = voters.filter(total_donation_amount__gte=min_total_donation)
if max_total_donation is not None:
voters = voters.filter(total_donation_amount__lte=max_total_donation)
paginator = Paginator(voters, 50)
page_number = request.GET.get('page')
voters_page = paginator.get_page(page_number)
context = {
'form': form,
'voters': voters_page,
'selected_tenant': tenant,
'call_form': ScheduledCallForm(tenant=tenant),
}
return render(request, "core/voter_advanced_search.html", context)"""
# Identify the range to replace
start_marker = "@role_required(["
# Use a more specific marker to find the voter_advanced_search function
search_marker = "def voter_advanced_search(request):"
export_marker = "def export_voters_csv(request):"
start_idx = content.find(search_marker)
if start_idx != -1:
# Go back to the decorator
decorator_idx = content.rfind("@role_required", 0, start_idx)
if decorator_idx != -1:
start_idx = decorator_idx
end_idx = content.find(export_marker, start_idx)
if end_idx != -1:
# Go back to its decorator
export_decorator_idx = content.rfind("@role_required", start_idx, end_idx)
if export_decorator_idx != -1:
end_idx = export_decorator_idx
new_content = content[:start_idx] + new_voter_advanced_search + "\n\n" + content[end_idx:]
with open('core/views.py', 'w') as f:
f.write(new_content)
print("Successfully updated voter_advanced_search in core/views.py")
else:
print("Could not find export_voters_csv marker")
else:
print("Could not find voter_advanced_search marker")