From d04891c0649eb3d2adbd697947c18f4a892aa611 Mon Sep 17 00:00:00 2001 From: Sicherhaven Date: Tue, 7 Apr 2026 11:52:41 +0530 Subject: [PATCH] feat(leads): link consumer account to lead on submission - user_account FK on Lead model (SET_NULL, related_name='submitted_leads') - Migration 0004_lead_user_account - ScheduleCallView auto-matches consumer account by email on create - _serialize_lead now returns userAccount: {id, name, email, phone, eventifyId, profilePicture} --- .../migrations/0004_lead_user_account.py | 28 +++++++++++++++++++ admin_api/models.py | 6 +++- admin_api/views.py | 24 ++++++++++++++-- mobile_api/views/user.py | 9 ++++++ 4 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 admin_api/migrations/0004_lead_user_account.py diff --git a/admin_api/migrations/0004_lead_user_account.py b/admin_api/migrations/0004_lead_user_account.py new file mode 100644 index 0000000..8976fc4 --- /dev/null +++ b/admin_api/migrations/0004_lead_user_account.py @@ -0,0 +1,28 @@ +# Generated by Django 4.2.21 on 2026-04-07 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('admin_api', '0003_lead'), + ] + + operations = [ + migrations.AddField( + model_name='lead', + name='user_account', + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='submitted_leads', + to=settings.AUTH_USER_MODEL, + help_text='Consumer platform account that submitted this lead (auto-matched by email)', + ), + ), + ] diff --git a/admin_api/models.py b/admin_api/models.py index b4e3ff2..ae0734f 100644 --- a/admin_api/models.py +++ b/admin_api/models.py @@ -222,9 +222,13 @@ class Lead(models.Model): status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='new') source = models.CharField(max_length=20, choices=SOURCE_CHOICES, default='schedule_call') priority = models.CharField(max_length=10, choices=PRIORITY_CHOICES, default='medium') - assigned_to = models.ForeignKey( + assigned_to = models.ForeignKey( User, on_delete=models.SET_NULL, null=True, blank=True, related_name='assigned_leads' ) + user_account = models.ForeignKey( + User, on_delete=models.SET_NULL, null=True, blank=True, related_name='submitted_leads', + help_text='Consumer platform account that submitted this lead (auto-matched by email)' + ) notes = models.TextField(blank=True, default='') created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) diff --git a/admin_api/views.py b/admin_api/views.py index b8c1393..6d3b8ef 100644 --- a/admin_api/views.py +++ b/admin_api/views.py @@ -2357,6 +2357,25 @@ def _serialize_lead(lead): if lead.assigned_to: assigned_name = lead.assigned_to.get_full_name() or lead.assigned_to.username assigned_id = lead.assigned_to.pk + + user_account = None + if lead.user_account: + u = lead.user_account + profile_pic = None + try: + if u.profile_picture: + profile_pic = u.profile_picture.url + except Exception: + pass + user_account = { + 'id': u.pk, + 'name': u.get_full_name() or u.username, + 'email': u.email, + 'phone': getattr(u, 'phone_number', None) or '', + 'eventifyId': getattr(u, 'eventify_id', None), + 'profilePicture': profile_pic, + } + return { 'id': lead.pk, 'name': lead.name, @@ -2372,6 +2391,7 @@ def _serialize_lead(lead): 'notes': lead.notes, 'createdAt': lead.created_at.isoformat(), 'updatedAt': lead.updated_at.isoformat(), + 'userAccount': user_account, } @@ -2399,7 +2419,7 @@ class LeadListView(APIView): def get(self, request): from admin_api.models import Lead from django.db.models import Q - qs = Lead.objects.select_related('assigned_to').order_by('-created_at') + qs = Lead.objects.select_related('assigned_to', 'user_account').order_by('-created_at') # Filters status_f = request.query_params.get('status', '').strip() @@ -2448,7 +2468,7 @@ class LeadDetailView(APIView): def get(self, request, pk): from admin_api.models import Lead from django.shortcuts import get_object_or_404 - lead = get_object_or_404(Lead.objects.select_related('assigned_to'), pk=pk) + lead = get_object_or_404(Lead.objects.select_related('assigned_to', 'user_account'), pk=pk) return Response(_serialize_lead(lead)) diff --git a/mobile_api/views/user.py b/mobile_api/views/user.py index 79856ac..7f273ab 100644 --- a/mobile_api/views/user.py +++ b/mobile_api/views/user.py @@ -491,6 +491,14 @@ class ScheduleCallView(View): if errors: return JsonResponse({'errors': errors}, status=400) + # Auto-link to a consumer account if one exists with this email + from django.contrib.auth import get_user_model + _User = get_user_model() + try: + consumer_account = _User.objects.get(email=email) + except _User.DoesNotExist: + consumer_account = None + lead = Lead.objects.create( name=name, email=email, @@ -500,6 +508,7 @@ class ScheduleCallView(View): status='new', source='schedule_call', priority='medium', + user_account=consumer_account, ) log("info", f"New schedule-call lead #{lead.pk} from {email}", request=request) return JsonResponse({