|
6 | 6 | class UserReportsFilter(filters.FilterSet): |
7 | 7 | email = filters.CharFilter(lookup_expr='icontains') |
8 | 8 | username = filters.CharFilter(lookup_expr='icontains') |
9 | | - date_joined = filters.DateTimeFromToRangeFilter( |
10 | | - field_name='date_joined', |
11 | | - help_text="Filter by date joined range. Format: YYYY-MM-DDTHH:MM:SSZ" |
12 | | - ) |
13 | | - last_login = filters.DateTimeFromToRangeFilter( |
14 | | - field_name='last_login', |
15 | | - help_text="Filter by last login range. Format: YYYY-MM-DDTHH:MM:SSZ" |
16 | | - ) |
17 | | - |
18 | | - storage_bytes_total = filters.RangeFilter( |
19 | | - field_name='storage_bytes_total', |
20 | | - help_text="Filter by storage bytes range. Format: min,max" |
21 | | - ) |
| 9 | + date_joined = filters.DateTimeFromToRangeFilter(field_name='date_joined') |
| 10 | + last_login = filters.DateTimeFromToRangeFilter(field_name='last_login') |
| 11 | + storage_bytes_total = filters.RangeFilter(field_name='storage_bytes_total') |
22 | 12 | current_period_submissions = filters.RangeFilter( |
23 | | - field_name='current_period_submissions', |
24 | | - help_text="Filter by current month submissions range. Format: min,max" |
| 13 | + field_name='current_period_submissions' |
25 | 14 | ) |
26 | 15 | submission_counts_all_time = filters.RangeFilter( |
27 | 16 | field_name='submission_counts_all_time', |
28 | | - help_text="Filter by all-time submissions range. Format: min,max" |
29 | 17 | ) |
30 | 18 | nlp_usage_asr_seconds_total = filters.RangeFilter( |
31 | 19 | field_name='nlp_usage_asr_seconds_total', |
32 | | - help_text="Filter by total ASR seconds range. Format: min,max" |
33 | 20 | ) |
34 | 21 | nlp_usage_mt_characters_total = filters.RangeFilter( |
35 | 22 | field_name='nlp_usage_mt_characters_total', |
36 | | - help_text="Filter by total MT characters range. Format: min,max" |
37 | | - ) |
38 | | - |
39 | | - # Asset filters |
40 | | - asset_count = filters.RangeFilter( |
41 | | - field_name='asset_count', |
42 | | - help_text="Filter by asset count range. Format: min,max" |
43 | | - ) |
44 | | - deployed_asset_count = filters.RangeFilter( |
45 | | - field_name='deployed_asset_count', |
46 | | - help_text="Filter by deployed asset count range. Format: min,max" |
47 | | - ) |
48 | | - |
49 | | - is_active = filters.BooleanFilter() |
50 | | - is_staff = filters.BooleanFilter() |
51 | | - is_superuser = filters.BooleanFilter() |
52 | | - validated_email = filters.BooleanFilter() |
53 | | - validated_password = filters.BooleanFilter() |
54 | | - mfa_is_active = filters.BooleanFilter() |
55 | | - sso_is_active = filters.BooleanFilter() |
56 | | - accepted_tos = filters.BooleanFilter() |
57 | | - |
58 | | - metadata__organization_type = filters.CharFilter( |
59 | | - method='filter_metadata_organization_type', |
60 | | - help_text="Filter by organization type in metadata" |
61 | | - ) |
62 | | - |
63 | | - # Subscription filters |
64 | | - has_subscriptions = filters.BooleanFilter( |
65 | | - method='filter_has_subscriptions', |
66 | | - help_text="Filter users with/without subscriptions" |
67 | | - ) |
68 | | - subscription_status = filters.CharFilter( |
69 | | - method='filter_subscription_status', |
70 | | - help_text="Filter by subscription status (active, canceled, etc.)" |
71 | | - ) |
72 | | - subscription_id = filters.CharFilter( |
73 | | - method='filter_subscription_id', |
74 | | - help_text="Filter by exact subscription id" |
75 | 23 | ) |
| 24 | + has_subscriptions = filters.BooleanFilter(method='filter_has_subscriptions') |
| 25 | + subscription_status = filters.CharFilter(method='filter_subscription_status') |
| 26 | + subscription_id = filters.CharFilter(method='filter_subscription_id') |
76 | 27 |
|
77 | 28 | class Meta: |
78 | 29 | model = UserReports |
79 | 30 | fields = [ |
80 | 31 | 'email', 'username', 'date_joined', 'last_login', |
81 | 32 | 'storage_bytes_total', 'current_period_submissions', |
82 | 33 | 'submission_counts_all_time', 'nlp_usage_asr_seconds_total', |
83 | | - 'nlp_usage_mt_characters_total', 'asset_count', 'deployed_asset_count', |
84 | | - 'is_active', 'is_staff', 'is_superuser', 'validated_email', |
85 | | - 'validated_password', 'mfa_is_active', 'sso_is_active', 'accepted_tos', |
86 | | - 'subscription_id' |
| 34 | + 'nlp_usage_mt_characters_total', 'subscription_id' |
87 | 35 | ] |
88 | 36 |
|
89 | | - def filter_metadata_organization_type(self, queryset, name, value): |
90 | | - if not value: |
91 | | - return queryset |
92 | | - |
93 | | - # Use raw SQL for JSON filtering with proper indexing |
94 | | - return queryset.extra( |
95 | | - where=["metadata::jsonb ->> 'organization_type' ILIKE %s"], |
96 | | - params=[f'%{value}%'] |
97 | | - ) |
98 | | - |
99 | 37 | def filter_has_subscriptions(self, queryset, name, value): |
100 | | - """ |
101 | | - Filter users based on whether they have subscriptions |
102 | | - """ |
103 | 38 | if value is None: |
104 | 39 | return queryset |
105 | 40 |
|
106 | 41 | if value: |
107 | | - # Users with subscriptions (non-empty array) |
108 | | - return queryset.extra( |
109 | | - where=["jsonb_array_length(subscriptions::jsonb) > 0"] |
110 | | - ) |
| 42 | + return queryset.exclude(subscriptions=[]) |
111 | 43 | else: |
112 | | - # Users without subscriptions (empty array) |
113 | | - return queryset.extra( |
114 | | - where=["jsonb_array_length(subscriptions::jsonb) = 0"] |
115 | | - ) |
| 44 | + return queryset.filter(subscriptions=[]) |
116 | 45 |
|
117 | 46 | def filter_subscription_status(self, queryset, name, value): |
118 | | - """ |
119 | | - Filter by subscription status within the JSON field |
120 | | - """ |
121 | 47 | if not value: |
122 | 48 | return queryset |
123 | | - |
124 | | - # Use JSON path query for subscription status |
125 | | - return queryset.extra( |
126 | | - where=[ |
127 | | - "EXISTS (SELECT 1 FROM jsonb_array_elements(subscriptions::jsonb) AS sub WHERE sub ->> 'status' = %s)" # noqa |
128 | | - ], |
129 | | - params=[value] |
130 | | - ) |
| 49 | + return queryset.filter(subscriptions__contains=[{'status': value}]) |
131 | 50 |
|
132 | 51 | def filter_subscription_id(self, queryset, name, value): |
133 | 52 | if not value: |
134 | 53 | return queryset |
135 | | - return queryset.extra( |
136 | | - where=[ |
137 | | - "EXISTS (SELECT 1 FROM jsonb_array_elements(subscriptions::jsonb) AS sub WHERE sub ->> 'id' = %s)" |
138 | | - ], |
139 | | - params=[value] |
140 | | - ) |
| 54 | + return queryset.filter(subscriptions__contains=[{'id': value}]) |
0 commit comments