112 lines
4.6 KiB
Python
112 lines
4.6 KiB
Python
@role_required(['admin', 'campaign_manager', 'campaign_staff', 'system_admin', 'campaign_admin'], permission='core.view_voter')
|
|
def log_door_visit(request):
|
|
"""
|
|
Mark all targeted voters at a specific address as visited, update their flags,
|
|
and create interaction records.
|
|
"""
|
|
selected_tenant_id = request.session.get("tenant_id")
|
|
if not selected_tenant_id:
|
|
return redirect("index")
|
|
|
|
tenant = get_object_or_404(Tenant, id=selected_tenant_id)
|
|
campaign_settings, _ = CampaignSettings.objects.get_or_create(tenant=tenant)
|
|
|
|
# Capture query string for redirecting back with filters
|
|
next_qs = request.POST.get("next_query_string", "")
|
|
redirect_url = reverse("door_visits")
|
|
if next_qs:
|
|
redirect_url += f"?{next_qs}"
|
|
|
|
# Get the volunteer linked to the current user
|
|
volunteer = Volunteer.objects.filter(user=request.user, tenant=tenant).first()
|
|
|
|
if request.method == "POST":
|
|
form = DoorVisitLogForm(request.POST)
|
|
if form.is_valid():
|
|
address_street = request.POST.get("address_street")
|
|
city = request.POST.get("city")
|
|
state = request.POST.get("state")
|
|
zip_code = request.POST.get("zip_code")
|
|
|
|
outcome = form.cleaned_data["outcome"]
|
|
notes = form.cleaned_data["notes"]
|
|
wants_yard_sign = form.cleaned_data["wants_yard_sign"]
|
|
candidate_support = form.cleaned_data["candidate_support"]
|
|
follow_up = form.cleaned_data["follow_up"]
|
|
follow_up_voter_id = form.cleaned_data.get("follow_up_voter")
|
|
call_notes = form.cleaned_data["call_notes"]
|
|
|
|
# Determine date/time in campaign timezone
|
|
campaign_tz_name = campaign_settings.timezone or "America/Chicago"
|
|
try:
|
|
tz = zoneinfo.ZoneInfo(campaign_tz_name)
|
|
except:
|
|
tz = zoneinfo.ZoneInfo("America/Chicago")
|
|
|
|
interaction_date = timezone.now().astimezone(tz)
|
|
|
|
# Get or create InteractionType
|
|
interaction_type, _ = InteractionType.objects.get_or_create(tenant=tenant, name="Door Visit")
|
|
|
|
# Find targeted voters at this exact address
|
|
voters = Voter.objects.filter(
|
|
tenant=tenant,
|
|
address_street=address_street,
|
|
city=city,
|
|
state=state,
|
|
zip_code=zip_code,
|
|
is_targeted=True
|
|
)
|
|
|
|
if not voters.exists():
|
|
messages.warning(request, f"No targeted voters found at {address_street}.")
|
|
return redirect(redirect_url)
|
|
|
|
# Get default caller for follow-ups
|
|
default_caller = None
|
|
if follow_up:
|
|
default_caller = Volunteer.objects.filter(tenant=tenant, is_default_caller=True).first()
|
|
|
|
for voter in voters:
|
|
# 1) Update voter flags
|
|
voter.door_visit = True
|
|
|
|
# 2) If "Wants a Yard Sign" checkbox is selected
|
|
if wants_yard_sign:
|
|
voter.yard_sign = "wants"
|
|
|
|
# 3) Update support status if Supporting or Not Supporting
|
|
if candidate_support in ["supporting", "not_supporting"]:
|
|
voter.candidate_support = candidate_support
|
|
|
|
voter.save()
|
|
|
|
# 4) Create interaction
|
|
Interaction.objects.create(
|
|
voter=voter,
|
|
volunteer=volunteer,
|
|
type=interaction_type,
|
|
date=interaction_date,
|
|
description=outcome,
|
|
notes=notes
|
|
)
|
|
|
|
# 5) Create ScheduledCall if follow_up is checked and this is the selected voter
|
|
if follow_up and follow_up_voter_id and str(voter.id) == follow_up_voter_id:
|
|
ScheduledCall.objects.create(
|
|
tenant=tenant,
|
|
voter=voter,
|
|
volunteer=default_caller,
|
|
comments=call_notes,
|
|
status="pending"
|
|
)
|
|
|
|
if follow_up:
|
|
messages.success(request, f"Door visit logged and follow-up call scheduled for {address_street}.")
|
|
else:
|
|
messages.success(request, f"Door visit logged for {address_street}.")
|
|
else:
|
|
messages.error(request, "There was an error in the visit log form.")
|
|
|
|
return redirect(redirect_url)
|