128 lines
5.8 KiB
Python
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")
|