1 # This file is part of Wolne Lektury, licensed under GNU Affero GPLv3 or later.
2 # Copyright © Fundacja Wolne Lektury. See NOTICE for more information.
5 from django.contrib import admin
6 from django.db.models.functions import Now
7 from django.db.models import Q
8 from django import forms
9 from django.utils.html import conditional_escape
10 from django.utils.safestring import mark_safe
11 from fnpdjango.actions import export_as_csv_action
12 from modeltranslation.admin import TranslationAdmin
14 from messaging.models import Contact, Level
15 from wolnelektury.utils import YesNoFilter
19 class SingleAmountInline(admin.TabularInline):
20 model = models.SingleAmount
23 class MonthlyAmountInline(admin.TabularInline):
24 model = models.MonthlyAmount
27 @admin.register(models.Club)
28 class ClubAdmin(admin.ModelAdmin):
35 class PayUOrderInline(admin.TabularInline):
36 model = models.PayUOrder
37 fields = ['order_id', 'status', 'customer_ip']
38 readonly_fields = fields
40 show_change_link = True
43 def has_add_permission(self, request, obj):
47 class PayUCardTokenInline(admin.TabularInline):
48 model = models.PayUCardToken
49 fields = ['created_at', 'disposable_token', 'reusable_token']
50 readonly_fields = fields
52 show_change_link = True
54 show_change_link = True
56 def has_add_permission(self, request, obj):
60 class PayedFilter(YesNoFilter):
61 title = 'płatność zakończona'
62 parameter_name = 'payed'
66 class ExpiredFilter(YesNoFilter):
67 title = 'harmonogram przedawniony'
68 parameter_name = 'expired'
69 q = Q(expires_at__isnull=False, expires_at__lt=Now())
72 class ActiveFilter(YesNoFilter):
73 title = 'płatność aktualna'
74 parameter_name = 'active'
75 q = Q(expires_at__gt=Now())
78 class ScheduleForm(forms.ModelForm):
79 def __init__(self, *args, **kwargs):
80 super().__init__(*args, **kwargs)
81 self.fields['email'].required = False
82 self.fields['method'].required = False
83 self.fields['consent'].required = False
86 model = models.Schedule
90 class SourceFilter(admin.SimpleListFilter):
91 title = 'Źródło' # display title
92 parameter_name = 'source'
93 template = "admin/long_filter.html"
95 def lookups(self, request, model_admin):
98 model_admin.model.objects.exclude(source='').values_list('source', flat=True).distinct()[:10]
102 def queryset(self, request, queryset):
106 class CrisisFilter(admin.SimpleListFilter):
107 title = 'czas zbiórki kryzysowej'
108 parameter_name = 'crisis'
110 def lookups(self, request, model_admin):
112 (b.id, '%s — %s' % (b.since, b.until)) for b in
113 annoy.models.Banner.objects.filter(place='crisis')
117 def queryset(self, request, queryset):
122 b = annoy.models.Banner.objects.get(id=self.value())
123 except annoy.models.Banner.DoesNotExist:
125 return queryset.filter(
126 started_at__gte=b.since,
127 started_at__lte=b.until
131 class OptOutFilter(YesNoFilter):
133 parameter_name = 'optout'
134 q = Q(email__in=Contact.objects.filter(level=Level.OPT_OUT).values_list('email', flat=True))
137 class ScheduleAdmin(admin.ModelAdmin):
141 'email', 'started_at', 'payed_at', 'expires_at', 'amount', 'monthly', 'yearly', 'is_cancelled',
144 list_display_links = ['email', 'started_at']
145 search_fields = ['email', 'source']
147 'is_cancelled', 'monthly', 'yearly', 'method',
148 'consent', OptOutFilter,
149 PayedFilter, ActiveFilter, ExpiredFilter,
150 SourceFilter, CrisisFilter
152 filter_horizontal = ['consent']
153 date_hierarchy = 'started_at'
154 raw_id_fields = ['membership']
155 inlines = [PayUOrderInline, PayUCardTokenInline]
156 actions = [export_as_csv_action()]
158 admin.site.register(models.Schedule, ScheduleAdmin)
161 class ScheduleInline(admin.TabularInline):
162 model = models.Schedule
163 fields = ['email', 'amount', 'is_cancelled', 'started_at', 'payed_at', 'expires_at', 'email_sent']
164 readonly_fields = fields
166 show_change_link = True
169 def has_add_permission(self, request, obj):
173 class MembershipAdmin(admin.ModelAdmin):
174 list_display = ['user', 'manual', 'updated_at', 'notes']
175 list_filter = ['manual']
176 date_hierarchy = 'updated_at'
177 raw_id_fields = ['user']
178 search_fields = ['user__username', 'user__email', 'schedule__email', 'notes']
179 inlines = [ScheduleInline]
181 admin.site.register(models.Membership, MembershipAdmin)
184 admin.site.register(models.ReminderEmail, TranslationAdmin)
187 class PayUNotificationAdmin(admin.ModelAdmin):
188 list_display = ['received_at', 'order']
189 fields = ['received_at', 'order', 'body_']
190 readonly_fields = ['received_at', 'body_']
191 raw_id_fields = ['order']
193 def body_(self, obj):
196 conditional_escape(json.dumps(json.loads(obj.body), indent=4))
200 admin.site.register(models.PayUNotification, PayUNotificationAdmin)
203 class PayUNotificationInline(admin.TabularInline):
204 model = models.PayUNotification
205 fields = ['received_at', 'body_']
206 readonly_fields = fields
208 show_change_link = True
211 def body_(self, obj):
214 conditional_escape(json.dumps(json.loads(obj.body), indent=4))
217 def has_add_permission(self, request, obj):
221 class PayUOrderAdmin(admin.ModelAdmin):
222 list_display = ['schedule']
223 raw_id_fields = ['schedule']
224 inlines = [PayUNotificationInline]
227 admin.site.register(models.PayUOrder, PayUOrderAdmin)
230 admin.site.register(models.Ambassador)
235 @admin.register(models.Consent)
236 class ConsentAdmin(admin.ModelAdmin):
237 list_display = ['text', 'order', 'active', 'required']
239 def get_readonly_fields(self, request, obj=None):