"""Reuse the contact directory's scoped history; never render all customer choices.""" from uuid import UUID from django.db.models import Prefetch, Q from django.http import Http404 from django.urls import reverse from apps.accounts.models import normalize_mobile from apps.core.persian_text import normalize_persian_text from apps.tickets.selectors import staff_ticket_rows from .validators import digits def customer_rows(user, search=''): # The existing directory projection counts only tickets visible to this staff user. from apps.tickets.views import _customer_rows rows = _customer_rows(user=user).filter(is_active=True) if search: terms_query = Q() for term in search.split(): mobile = term try: mobile = normalize_mobile(term) except ValueError: if term.isascii() and term.isdecimal() and term.startswith('0'): mobile = term[1:] terms_query &= (Q(mobile__icontains=mobile) | Q(username__icontains=term) | Q(first_name__icontains=term) | Q(last_name__icontains=term) | Q(customer_profile__first_name__icontains=term) | Q(customer_profile__last_name__icontains=term) | Q(customer_profile__organization_name__icontains=term)) history = staff_ticket_rows(user).filter( Q(ticket_number__icontains=search) | Q(subject__icontains=search) | Q(subject__icontains=normalize_persian_text(search))) rows = rows.filter(terms_query | Q(customer_tickets__pk__in=history.values('pk'))).distinct() return rows.prefetch_related(Prefetch('customer_tickets', queryset=staff_ticket_rows(user).order_by('-created_at', '-pk')[:3], to_attr='payment_recent_tickets')) def customer_data(customer): profile = getattr(customer, 'customer_profile', None) name = ' '.join(filter(None, [getattr(profile, 'first_name', ''), getattr(profile, 'last_name', '')])) return {'value': str(customer.pk), 'id': str(customer.public_id), 'name': name or customer.get_full_name() or 'نام ثبت نشده', 'mobile': customer.local_mobile, 'organization': getattr(profile, 'organization_name', ''), 'location': '، '.join(filter(None, [getattr(profile, 'city', ''), getattr(profile, 'province', '')])), 'ticket_count': customer.ticket_count, 'active_count': customer.active_count, 'history': [{'number': ticket.ticket_number, 'subject': ticket.subject, 'status': ticket.get_status_display(), 'url': reverse('staff_tickets:detail', args=[ticket.public_id])} for ticket in customer.payment_recent_tickets]} def initial_customer(request): public_id = request.GET.get('customer', '') if not public_id or request.method != 'GET': return {} try: public_id = UUID(public_id) except (ValueError, TypeError, AttributeError): raise Http404('مشتری معتبر نیست.') customer = customer_rows(request.user).filter(public_id=public_id).first() if customer is None: raise Http404('مشتری فعال پیدا نشد.') return {'customer': customer.pk} def picker_context(request, form): value = str(form['customer'].value() or '') selected = customer_rows(request.user).filter(pk=value).first() if value.isascii() and value.isdecimal() else None return {'customer_selection': customer_data(selected) if selected else None} def search_results(user, query): query = digits(query).translate(str.maketrans('يك', 'یک'))[:100] if len(query) < 2: return {'results': [], 'has_more': False} rows = list(customer_rows(user, query)[:21]) return {'results': [customer_data(customer) for customer in rows[:20]], 'has_more': len(rows) > 20}