add contacts export
[wolnelektury.git] / src / club / admin.py
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.
3 #
4 import json
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
13 import annoy.models
14 from messaging.models import Contact, Level
15 from wolnelektury.utils import YesNoFilter
16 from . import models
17
18
19 class SingleAmountInline(admin.TabularInline):
20     model = models.SingleAmount
21
22
23 class MonthlyAmountInline(admin.TabularInline):
24     model = models.MonthlyAmount
25
26
27 @admin.register(models.Club)
28 class ClubAdmin(admin.ModelAdmin):
29     inlines = [
30         SingleAmountInline,
31         MonthlyAmountInline
32     ]
33
34
35 class PayUOrderInline(admin.TabularInline):
36     model = models.PayUOrder
37     fields = ['order_id', 'status', 'customer_ip']
38     readonly_fields = fields
39     extra = 0
40     show_change_link = True
41     can_delete = False
42
43     def has_add_permission(self, request, obj):
44         return False
45
46
47 class PayUCardTokenInline(admin.TabularInline):
48     model = models.PayUCardToken
49     fields = ['created_at', 'disposable_token', 'reusable_token']
50     readonly_fields = fields
51     extra = 0
52     show_change_link = True
53     can_delete = False
54     show_change_link = True
55
56     def has_add_permission(self, request, obj):
57         return False
58
59
60 class PayedFilter(YesNoFilter):
61     title = 'płatność zakończona'
62     parameter_name = 'payed'
63     q = ~Q(payed_at=None)
64
65
66 class ExpiredFilter(YesNoFilter):
67     title = 'harmonogram przedawniony'
68     parameter_name = 'expired'
69     q = Q(expires_at__isnull=False, expires_at__lt=Now())
70
71
72 class ActiveFilter(YesNoFilter):
73     title = 'płatność aktualna'
74     parameter_name = 'active'
75     q = Q(expires_at__gt=Now())
76
77
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
84
85     class Meta:
86         model = models.Schedule
87         fields = '__all__'
88
89
90 class SourceFilter(admin.SimpleListFilter):
91     title = 'Źródło' # display title
92     parameter_name = 'source'
93     template = "admin/long_filter.html"
94
95     def lookups(self, request, model_admin):
96         lookups = [
97             (m, m) for m in
98             model_admin.model.objects.exclude(source='').values_list('source', flat=True).distinct()[:10]
99         ]
100         return lookups
101
102     def queryset(self, request, queryset):
103         return queryset
104     
105
106 class CrisisFilter(admin.SimpleListFilter):
107     title = 'czas zbiórki kryzysowej'
108     parameter_name = 'crisis'
109
110     def lookups(self, request, model_admin):
111         lookups = [
112             (b.id, '%s — %s' % (b.since, b.until)) for b in
113             annoy.models.Banner.objects.filter(place='crisis')
114         ]
115         return lookups
116
117     def queryset(self, request, queryset):
118         bid = self.value()
119         if not bid:
120             return
121         try:
122             b = annoy.models.Banner.objects.get(id=self.value())
123         except annoy.models.Banner.DoesNotExist:
124             return
125         return queryset.filter(
126             started_at__gte=b.since,
127             started_at__lte=b.until
128         )
129
130
131 class OptOutFilter(YesNoFilter):
132     title = 'opt out'
133     parameter_name = 'optout'
134     q = Q(email__in=Contact.objects.filter(level=Level.OPT_OUT).values_list('email', flat=True))
135
136
137 class ScheduleAdmin(admin.ModelAdmin):
138     form = ScheduleForm
139
140     list_display = [
141         'email', 'started_at', 'payed_at', 'expires_at', 'amount', 'monthly', 'yearly', 'is_cancelled',
142         'method'
143     ]
144     list_display_links = ['email', 'started_at']
145     search_fields = ['email', 'source']
146     list_filter = [
147         'is_cancelled', 'monthly', 'yearly', 'method',
148         'consent', OptOutFilter,
149         PayedFilter, ActiveFilter, ExpiredFilter,
150         SourceFilter, CrisisFilter
151     ]
152     filter_horizontal = ['consent']
153     date_hierarchy = 'started_at'
154     raw_id_fields = ['membership']
155     inlines = [PayUOrderInline, PayUCardTokenInline]
156     actions = [export_as_csv_action()]
157
158 admin.site.register(models.Schedule, ScheduleAdmin)
159
160
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
165     extra = 0
166     show_change_link = True
167     can_delete = False
168
169     def has_add_permission(self, request, obj):
170         return False
171
172
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]
180
181 admin.site.register(models.Membership, MembershipAdmin)
182
183
184 admin.site.register(models.ReminderEmail, TranslationAdmin)
185
186
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']
192
193     def body_(self, obj):
194         return mark_safe(
195                 "<pre>" +
196                 conditional_escape(json.dumps(json.loads(obj.body), indent=4))
197                 + "</pre>")
198
199
200 admin.site.register(models.PayUNotification, PayUNotificationAdmin)
201
202
203 class PayUNotificationInline(admin.TabularInline):
204     model = models.PayUNotification
205     fields = ['received_at', 'body_']
206     readonly_fields = fields
207     extra = 0
208     show_change_link = True
209     can_delete = False
210
211     def body_(self, obj):
212         return mark_safe(
213                 "<pre>" +
214                 conditional_escape(json.dumps(json.loads(obj.body), indent=4))
215                 + "</pre>")
216
217     def has_add_permission(self, request, obj):
218         return False
219
220
221 class PayUOrderAdmin(admin.ModelAdmin):
222     list_display = ['schedule']
223     raw_id_fields = ['schedule']
224     inlines = [PayUNotificationInline]
225
226
227 admin.site.register(models.PayUOrder, PayUOrderAdmin)
228
229
230 admin.site.register(models.Ambassador)
231
232
233     
234
235 @admin.register(models.Consent)
236 class ConsentAdmin(admin.ModelAdmin):
237     list_display = ['text', 'order', 'active', 'required']
238
239     def get_readonly_fields(self, request, obj=None):
240         if obj:
241             return ['text']
242         else:
243             return []