PERF(promotions): collapse allowed-user check into a single query

Fold the restricted-recipient access check into the recipients
queryset itself via Q(public OR restricted-and-allowed), joining
against AllowedUser instead of running a separate lookup query.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Ali Asadi 2026-08-03 18:21:23 +03:30
parent 33aa0ed1b4
commit 54de7fdb48

View file

@ -3,7 +3,7 @@ import uuid
from django.conf import settings from django.conf import settings
from django.contrib.postgres.indexes import GinIndex from django.contrib.postgres.indexes import GinIndex
from django.db import models, transaction from django.db import models, transaction
from django.db.models import F from django.db.models import F, Q
from django.utils import timezone from django.utils import timezone
from django_minio_backend import MinioBackend, iso_date_prefix from django_minio_backend import MinioBackend, iso_date_prefix
@ -136,17 +136,16 @@ class Plan(BaseModel):
return self.title return self.title
def get_configured_promotion_amount(self, user_uuid=None): def get_configured_promotion_amount(self, user_uuid=None):
recipients = list(self.recipients.filter(recipient_uuid_field='->event:user')) #TODO: instead of hard code use better soloution access_filter = Q(access_type=RecipientTypeChoices.PUBLIC)
restricted_ids = [r.pk for r in recipients if r.access_type == RecipientTypeChoices.RESTRICTED] if user_uuid:
allowed_ids = set( access_filter |= Q(access_type=RecipientTypeChoices.RESTRICTED, allowed_users__user__uuid=user_uuid)
AllowedUser.objects.filter(recipient_id__in=restricted_ids, user__uuid=user_uuid)
.values_list('recipient_id', flat=True) recipients = self.recipients.filter(
) if restricted_ids and user_uuid else set() recipient_uuid_field='->event:user' #TODO: instead of hard code use better soloution
).filter(access_filter).distinct()
amount = 0 amount = 0
for recipient in recipients: for recipient in recipients:
if recipient.access_type == RecipientTypeChoices.RESTRICTED and recipient.pk not in allowed_ids:
continue
base_amount, promotion_amount = recipient.get_promotion_amount() base_amount, promotion_amount = recipient.get_promotion_amount()
amount += promotion_amount amount += promotion_amount
return amount return amount