1
|
|
|
""" |
2
|
|
|
byceps.blueprints.admin.orga.views |
3
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
4
|
|
|
|
5
|
|
|
:Copyright: 2006-2020 Jochen Kupperschmidt |
6
|
|
|
:License: Modified BSD, see LICENSE for details. |
7
|
|
|
""" |
8
|
|
|
|
9
|
1 |
|
from operator import attrgetter |
10
|
|
|
|
11
|
1 |
|
from flask import abort, g, request |
12
|
|
|
|
13
|
1 |
|
from ....services.brand import service as brand_service |
14
|
1 |
|
from ....services.orga import service as orga_service |
15
|
1 |
|
from ....services.orga import birthday_service as orga_birthday_service |
16
|
1 |
|
from ....services.user import service as user_service |
17
|
1 |
|
from ....util.export import serialize_to_csv |
18
|
1 |
|
from ....util.framework.blueprint import create_blueprint |
19
|
1 |
|
from ....util.framework.flash import flash_success |
20
|
1 |
|
from ....util.framework.templating import templated |
21
|
1 |
|
from ....util.views import redirect_to, respond_no_content, textified |
22
|
|
|
|
23
|
1 |
|
from ...authorization.decorators import permission_required |
24
|
1 |
|
from ...authorization.registry import permission_registry |
25
|
|
|
|
26
|
1 |
|
from ..orga_team.authorization import OrgaTeamPermission |
27
|
|
|
|
28
|
1 |
|
from .authorization import OrgaBirthdayPermission, OrgaDetailPermission |
29
|
1 |
|
from .forms import OrgaFlagCreateForm |
30
|
|
|
|
31
|
|
|
|
32
|
1 |
|
blueprint = create_blueprint('orga_admin', __name__) |
33
|
|
|
|
34
|
|
|
|
35
|
1 |
|
permission_registry.register_enum(OrgaBirthdayPermission) |
36
|
1 |
|
permission_registry.register_enum(OrgaDetailPermission) |
37
|
1 |
|
permission_registry.register_enum(OrgaTeamPermission) |
38
|
|
|
|
39
|
|
|
|
40
|
1 |
|
@blueprint.route('/persons') |
41
|
1 |
|
@permission_required(OrgaDetailPermission.view) |
42
|
1 |
|
@templated |
43
|
|
|
def persons(): |
44
|
|
|
"""List brands to choose from.""" |
45
|
|
|
brands_with_person_counts = orga_service.get_brands_with_person_counts() |
46
|
|
|
|
47
|
|
|
return { |
48
|
|
|
'brands_with_person_counts': brands_with_person_counts, |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
|
52
|
1 |
|
@blueprint.route('/persons/<brand_id>') |
53
|
1 |
|
@permission_required(OrgaDetailPermission.view) |
54
|
1 |
|
@templated |
55
|
|
|
def persons_for_brand(brand_id): |
56
|
|
|
"""List organizers for the brand with details.""" |
57
|
|
|
brand = _get_brand_or_404(brand_id) |
58
|
|
|
|
59
|
|
|
orgas = orga_service.get_orgas_for_brand(brand.id) |
60
|
|
|
orgas.sort(key=user_service.get_sort_key_for_screen_name) |
61
|
|
|
|
62
|
|
|
return { |
63
|
|
|
'brand': brand, |
64
|
|
|
'orgas': orgas, |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
|
68
|
1 |
|
@blueprint.route('/persons/<brand_id>/create') |
69
|
1 |
|
@permission_required(OrgaTeamPermission.administrate_memberships) |
70
|
1 |
|
@templated |
71
|
1 |
|
def create_orgaflag_form(brand_id, erroneous_form=None): |
72
|
|
|
"""Show form to give the organizer flag to a user.""" |
73
|
|
|
brand = _get_brand_or_404(brand_id) |
74
|
|
|
|
75
|
|
|
form = erroneous_form if erroneous_form else OrgaFlagCreateForm() |
76
|
|
|
|
77
|
|
|
return { |
78
|
|
|
'brand': brand, |
79
|
|
|
'form': form, |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
|
83
|
1 |
|
@blueprint.route('/persons/<brand_id>', methods=['POST']) |
84
|
1 |
|
@permission_required(OrgaTeamPermission.administrate_memberships) |
85
|
|
|
def create_orgaflag(brand_id): |
86
|
|
|
"""Give the organizer flag to a user.""" |
87
|
|
|
brand = _get_brand_or_404(brand_id) |
88
|
|
|
|
89
|
|
|
form = OrgaFlagCreateForm(request.form, brand_id=brand.id) |
90
|
|
|
if not form.validate(): |
91
|
|
|
return create_orgaflag_form(brand.id, form) |
92
|
|
|
|
93
|
|
|
user = form.user.data |
94
|
|
|
initiator = g.current_user |
95
|
|
|
|
96
|
|
|
orga_flag = orga_service.add_orga_flag(brand.id, user.id, initiator.id) |
97
|
|
|
|
98
|
|
|
flash_success( |
99
|
|
|
f'{orga_flag.user.screen_name} wurde das Orga-Flag ' |
100
|
|
|
f'für die Marke {orga_flag.brand.title} gegeben.' |
101
|
|
|
) |
102
|
|
|
return redirect_to('.persons_for_brand', brand_id=orga_flag.brand.id) |
103
|
|
|
|
104
|
|
|
|
105
|
1 |
|
@blueprint.route('/persons/<brand_id>/<uuid:user_id>', methods=['DELETE']) |
106
|
1 |
|
@permission_required(OrgaTeamPermission.administrate_memberships) |
107
|
1 |
|
@respond_no_content |
108
|
|
|
def remove_orgaflag(brand_id, user_id): |
109
|
|
|
"""Remove the organizer flag for a brand from a person.""" |
110
|
|
|
orga_flag = orga_service.find_orga_flag(brand_id, user_id) |
111
|
|
|
|
112
|
|
|
if orga_flag is None: |
113
|
|
|
abort(404) |
114
|
|
|
|
115
|
|
|
brand = orga_flag.brand |
116
|
|
|
user = orga_flag.user |
117
|
|
|
initiator = g.current_user |
118
|
|
|
|
119
|
|
|
orga_service.remove_orga_flag(orga_flag, initiator.id) |
120
|
|
|
|
121
|
|
|
flash_success( |
122
|
|
|
f'{user.screen_name} wurde das Orga-Flag ' |
123
|
|
|
f'für die Marke {brand.title} entzogen.' |
124
|
|
|
) |
125
|
|
|
|
126
|
|
|
|
127
|
1 |
|
@blueprint.route('/persons/<brand_id>/export') |
128
|
1 |
|
@permission_required(OrgaDetailPermission.view) |
129
|
1 |
|
@textified |
130
|
|
|
def export_persons(brand_id): |
131
|
|
|
"""Export the list of organizers for the brand as a CSV document in |
132
|
|
|
Microsoft Excel dialect. |
133
|
|
|
""" |
134
|
|
|
brand = _get_brand_or_404(brand_id) |
135
|
|
|
|
136
|
|
|
field_names = [ |
137
|
|
|
'Benutzername', |
138
|
|
|
'Vorname', |
139
|
|
|
'Nachname', |
140
|
|
|
'Geburtstag', |
141
|
|
|
'Straße', |
142
|
|
|
'PLZ', |
143
|
|
|
'Ort', |
144
|
|
|
'Land', |
145
|
|
|
'E-Mail-Adresse', |
146
|
|
|
'Telefonnummer', |
147
|
|
|
] |
148
|
|
|
|
149
|
|
|
def to_dict(user): |
150
|
|
|
date_of_birth = ( |
151
|
|
|
user.detail.date_of_birth.strftime('%d.%m.%Y') |
152
|
|
|
if user.detail.date_of_birth |
153
|
|
|
else None |
154
|
|
|
) |
155
|
|
|
|
156
|
|
|
return { |
157
|
|
|
'Benutzername': user.screen_name, |
158
|
|
|
'Vorname': user.detail.first_names, |
159
|
|
|
'Nachname': user.detail.last_name, |
160
|
|
|
'Geburtstag': date_of_birth, |
161
|
|
|
'Straße': user.detail.street, |
162
|
|
|
'PLZ': user.detail.zip_code, |
163
|
|
|
'Ort': user.detail.city, |
164
|
|
|
'Land': user.detail.country, |
165
|
|
|
'E-Mail-Adresse': user.email_address, |
166
|
|
|
'Telefonnummer': user.detail.phone_number, |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
orgas = orga_service.get_orgas_for_brand(brand.id) |
170
|
|
|
orgas = [orga for orga in orgas if not orga.deleted] |
171
|
|
|
orgas.sort(key=user_service.get_sort_key_for_screen_name) |
172
|
|
|
rows = map(to_dict, orgas) |
173
|
|
|
return serialize_to_csv(field_names, rows) |
174
|
|
|
|
175
|
|
|
|
176
|
1 |
|
@blueprint.route('/birthdays') |
177
|
1 |
|
@permission_required(OrgaBirthdayPermission.view) |
178
|
1 |
|
@templated |
179
|
|
|
def birthdays(): |
180
|
|
|
orgas = list( |
181
|
|
|
orga_birthday_service.collect_orgas_with_next_birthdays(limit=5) |
182
|
|
|
) |
183
|
|
|
|
184
|
|
|
return { |
185
|
|
|
'orgas': orgas, |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
|
189
|
1 |
|
def _get_brand_or_404(brand_id): |
190
|
|
|
brand = brand_service.find_brand(brand_id) |
191
|
|
|
|
192
|
|
|
if brand is None: |
193
|
|
|
abort(404) |
194
|
|
|
|
195
|
|
|
return brand |
196
|
|
|
|