import sys import re file_path = 'core/views.py' with open(file_path, 'r') as f: content = f.read() # Define the new function as a single string new_func = """def door_visit_history(request): """ Shows a distinct list of Door visit interactions for addresses. """ 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) # Date filter start_date = request.GET.get("start_date") end_date = request.GET.get("end_date") # Get all "Door Visit" interactions for this tenant interactions = Interaction.objects.filter( voter__tenant=tenant, type__name="Door Visit" ).select_related("voter", "volunteer") if start_date or end_date: try: if start_date: d = parse_date(start_date) if d: start_dt = timezone.make_aware(datetime.combine(d, time.min)) interactions = interactions.filter(date__gte=start_dt) if end_date: d = parse_date(end_date) if d: # Use lt with next day to capture everything on the end_date end_dt = timezone.make_aware(datetime.combine(d + timedelta(days=1), time.min)) interactions = interactions.filter(date__lt=end_dt) except Exception as e: logger.error(f"Error filtering door visit history by date: {e}") # Summary of counts per volunteer # Grouping by household (unique address) visited_households = {} volunteer_counts = {} for interaction in interactions.order_by("-date"): v = interaction.voter addr = v.address.strip() if v.address else f"{v.address_street}, {v.city}, {v.state} {v.zip_code}".strip(", ") if not addr: continue key = addr.lower() if key not in visited_households: # Calculate volunteer summary - only once per household v_obj = interaction.volunteer v_name = f"{v_obj.first_name} {v_obj.last_name}".strip() or v_obj.email if v_obj else "N/A" volunteer_counts[v_name] = volunteer_counts.get(v_name, 0) + 1 # Parse street name and number for sorting street_number = "" street_name = v.address_street or "" match = re.match(r'^(\d+)\s+(.*)$', street_name) if match: street_number = match.group(1) street_name = match.group(2) try: street_number_sort = int(street_number) except ValueError: street_number_sort = 0 visited_households[key] = { 'address_display': addr, 'address_street': v.address_street, 'city': v.city, 'state': v.state, 'zip_code': v.zip_code, 'neighborhood': v.neighborhood, 'district': v.district, 'latitude': float(v.latitude) if v.latitude else None, 'longitude': float(v.longitude) if v.longitude else None, 'street_name_sort': street_name.lower(), 'street_number_sort': street_number_sort, 'last_visit_date': interaction.date, 'target_voters': [], 'voters_json': [] } visited_households[key]["voters_json"].append({'id': v.id, 'name': f"{v.first_name} {v.last_name}"}) visited_households[key]['target_voters'].append(v) # Sort volunteer counts by total (descending) sorted_volunteer_counts = sorted(volunteer_counts.items(), key=lambda x: x[1], reverse=True) history_list = list(visited_households.values()) history_list.sort(key=lambda x: x["last_visit_date"], reverse=True) paginator = Paginator(history_list, 50) page_number = request.GET.get("page") history_page = paginator.get_page(page_number) context = { "selected_tenant": tenant, "history": history_page, "start_date": start_date, "end_date": end_date, "volunteer_counts": sorted_volunteer_counts, } return render(request, "core/door_visit_history.html", context) """ # Use regex to find and replace the function pattern = r'def door_visit_history\(request\):.*?return render\(request, "core/door_visit_history\.html", context\)' new_content = re.sub(pattern, new_func, content, flags=re.DOTALL) if new_content != content: with open(file_path, 'w') as f: f.write(new_content) print("Successfully updated door_visit_history") else: print("Could not find function to replace")