tasks.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. from django.conf import settings
  2. from django.db.models import Count, Q, F, Subquery, OuterRef, IntegerField
  3. from django.db.models.functions import Cast
  4. from django.db.models.fields.json import KeyTextTransform
  5. from celery import shared_task
  6. from organizations_ext.models import Organization
  7. from projects.models import Project
  8. from .models import SubscriptionQuotaWarning
  9. from .email import WarnQuotaEmail
  10. @shared_task
  11. def warn_organization_throttle():
  12. """ Warn user about approaching 80% of allotted events """
  13. if not settings.BILLING_ENABLED:
  14. return
  15. queryset = Organization.objects.filter(
  16. djstripe_customers__subscriptions__status="active",
  17. ).filter(
  18. Q(djstripe_customers__subscriptions__subscriptionquotawarning=None)
  19. | Q(
  20. djstripe_customers__subscriptions__subscriptionquotawarning__notice_last_sent__lt=F(
  21. "djstripe_customers__subscriptions__current_period_start"
  22. ),
  23. )
  24. )
  25. projects = Project.objects.filter(organization=OuterRef("pk")).values(
  26. "organization"
  27. )
  28. total_issue_events = projects.annotate(
  29. total=Count(
  30. "issue__event",
  31. filter=Q(
  32. issue__event__created__gte=OuterRef(
  33. "djstripe_customers__subscriptions__current_period_start"
  34. )
  35. ),
  36. )
  37. ).values("total")
  38. total_transaction_events = projects.annotate(
  39. total=Count(
  40. "transactionevent",
  41. filter=Q(
  42. transactionevent__created__gte=OuterRef(
  43. "djstripe_customers__subscriptions__current_period_start"
  44. )
  45. ),
  46. )
  47. ).values("total")
  48. queryset = queryset.annotate(
  49. event_count=Subquery(total_issue_events) + Subquery(total_transaction_events),
  50. plan_event_count=Cast(
  51. KeyTextTransform(
  52. "events", "djstripe_customers__subscriptions__plan__product__metadata"
  53. ),
  54. output_field=IntegerField(),
  55. ),
  56. )
  57. # 80% to 100% of event quota
  58. queryset = queryset.filter(
  59. event_count__gte=F("plan_event_count") * 0.80,
  60. event_count__lte=F("plan_event_count"),
  61. )
  62. for org in queryset:
  63. subscription = org.djstripe_customers.first().subscription
  64. send_email_warn_quota.delay(subscription.pk, org.event_count)
  65. warning, created = SubscriptionQuotaWarning.objects.get_or_create(
  66. subscription=subscription
  67. )
  68. if not created:
  69. warning.save()
  70. @shared_task
  71. def send_email_warn_quota(subscription_id: int, event_count: int):
  72. WarnQuotaEmail(pk=subscription_id, event_count=event_count).send_email()