from django.conf import settings from django.contrib import admin from django.db.models import F, PositiveIntegerField from django.db.models.fields.json import KeyTextTransform from django.db.models.functions import Cast from django.utils.html import format_html from import_export.admin import ImportExportModelAdmin from organizations.base_admin import ( BaseOrganizationAdmin, BaseOrganizationUserAdmin, BaseOwnerInline, ) from apps.stripe.models import StripeSubscription from apps.stripe.utils import get_stripe_link from .models import ( Organization, OrganizationOwner, OrganizationSocialApp, OrganizationUser, ) from .resources import OrganizationResource, OrganizationUserResource ORGANIZATION_LIST_FILTER = ( "is_active", "is_accepting_events", "stripesubscription__product", ) class OwnerInline(BaseOwnerInline): model = OrganizationOwner class OrganizationUserInline(admin.StackedInline): raw_id_fields = ("user",) model = OrganizationUser extra = 0 class OrganizationSubscriptionInline(admin.StackedInline): model = StripeSubscription extra = 0 readonly_fields = [field.name for field in StripeSubscription._meta.fields] class GlitchTipBaseOrganizationAdmin(BaseOrganizationAdmin): readonly_fields = ("customer_link", "subscription_link", "created") list_filter = ORGANIZATION_LIST_FILTER inlines = [OrganizationUserInline, OwnerInline, OrganizationSubscriptionInline] show_full_result_count = False def issue_events(self, obj): return obj.issue_event_count def customer_link(self, obj): if customer_id := obj.stripe_customer_id: return format_html( '{}', get_stripe_link(customer_id), customer_id, ) def subscription_link(self, obj): if subscription_id := obj.stripe_primary_subscription_id: return format_html( '{}', get_stripe_link(subscription_id), subscription_id, ) def transaction_events(self, obj): return obj.transaction_count def uptime_check_events(self, obj): return obj.uptime_check_event_count def file_size(self, obj): return obj.file_size def total_events(self, obj): return obj.total_event_count class OrganizationAdmin(GlitchTipBaseOrganizationAdmin, ImportExportModelAdmin): list_display = [ "name", "is_active", "is_accepting_events", "issue_events", "transaction_events", "uptime_check_events", "file_size", "total_events", "stripe_primary_subscription", ] resource_class = OrganizationResource def get_queryset(self, request): qs = self.model.objects.with_event_counts() # From super ordering = self.ordering or () if ordering: qs = qs.order_by(*ordering) return qs class OrganizationSubscription(Organization): class Meta: proxy = True class IsOverListFilter(admin.SimpleListFilter): title = "Is over plan limit" parameter_name = "is_over" def lookups(self, request, model_admin): return ( (True, "Yes"), (False, "No"), ) def queryset(self, request, queryset): if self.value() is not None: queryset = queryset.filter(max_events__isnull=False) if self.value() is False: return queryset.filter(total_event_count__lte=F("max_events")) if self.value() is True: return queryset.filter(total_event_count__gt=F("max_events")) return queryset class OrganizationSubscriptionAdmin(GlitchTipBaseOrganizationAdmin): list_display = [ "name", "is_active", "is_accepting_events", "issue_events", "transaction_events", "uptime_check_events", "file_size", "total_events", "max_events", "current_period_end", ] def max_events(self, obj): return obj.max_events def current_period_end(self, obj): return obj.current_period_end def get_queryset(self, request): qs = Organization.objects.with_event_counts().annotate( max_events=Cast( KeyTextTransform( "events", "djstripe_customers__subscriptions__plan__product__metadata", ), output_field=PositiveIntegerField(), ), current_period_end=F( "djstripe_customers__subscriptions__current_period_end" ), ) # From super ordering = self.ordering or () if ordering: qs = qs.order_by(*ordering) return qs list_filter = GlitchTipBaseOrganizationAdmin.list_filter + (IsOverListFilter,) class OrganizationUserAdmin(BaseOrganizationUserAdmin, ImportExportModelAdmin): list_display = ["user", "organization", "role", "email"] search_fields = ("email", "user__email", "organization__name") list_filter = ("role",) resource_class = OrganizationUserResource class OrganizationSocialAppAdmin(admin.ModelAdmin): list_display = ["organization", "social_app"] search_fields = ("organization__name", "social_app__name") admin.site.register(Organization, OrganizationAdmin) if settings.BILLING_ENABLED: admin.site.register(OrganizationSubscription, OrganizationSubscriptionAdmin) admin.site.register(OrganizationUser, OrganizationUserAdmin) admin.site.register(OrganizationSocialApp, OrganizationSocialAppAdmin)