From 76bdc68cb90ef472c51f6d3c08015b36855bb415 Mon Sep 17 00:00:00 2001 From: Tom Teichler <tom.teichler@teckids.org> Date: Wed, 19 Aug 2020 21:28:06 +0200 Subject: [PATCH] [Reformat] Make lint clean --- .gitlab-ci.yml | 7 + aleksis/apps/ticdesk/__init__.py | 2 - aleksis/apps/ticdesk/filters.py | 33 +- aleksis/apps/ticdesk/forms.py | 308 +++++++++++------- aleksis/apps/ticdesk/menus.py | 24 +- .../migrations/0007_auto_20200728_1145.py | 129 ++++++-- .../migrations/0008_auto_20200728_1352.py | 10 +- .../migrations/0009_auto_20200728_1504.py | 19 +- .../migrations/0010_auto_20200728_2017.py | 48 ++- .../migrations/0011_auto_20200728_2119.py | 20 +- .../migrations/0012_auto_20200729_1640.py | 20 +- .../migrations/0013_auto_20200729_1738.py | 8 +- .../migrations/0014_auto_20200731_1511.py | 14 +- .../migrations/0015_auto_20200802_1340.py | 19 +- ...16_eventfeedback_feedbackfeedbackaspect.py | 167 ++++++++-- .../migrations/0017_auto_20200802_1507.py | 29 +- .../migrations/0018_auto_20200802_1646.py | 25 +- aleksis/apps/ticdesk/model_extensions.py | 10 +- aleksis/apps/ticdesk/models.py | 77 ++++- aleksis/apps/ticdesk/predicates.py | 4 +- aleksis/apps/ticdesk/preferences.py | 1 - aleksis/apps/ticdesk/rules.py | 28 +- aleksis/apps/ticdesk/settings.py | 6 - aleksis/apps/ticdesk/tables.py | 31 +- aleksis/apps/ticdesk/urls.py | 54 ++- aleksis/apps/ticdesk/util.py | 13 +- aleksis/apps/ticdesk/views.py | 168 ++++++---- poetry.lock | 64 ++-- tox.ini | 82 +++++ 29 files changed, 949 insertions(+), 471 deletions(-) create mode 100644 .gitlab-ci.yml create mode 100644 tox.ini diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..1224312 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,7 @@ +include: + - project: "AlekSIS/official/AlekSIS" + file: /ci/general.yml + - project: "AlekSIS/official/AlekSIS" + file: /ci/test.yml + - project: "AlekSIS/official/AlekSIS" + file: /ci/build_dist.yml diff --git a/aleksis/apps/ticdesk/__init__.py b/aleksis/apps/ticdesk/__init__.py index b775e19..4ba3a1e 100644 --- a/aleksis/apps/ticdesk/__init__.py +++ b/aleksis/apps/ticdesk/__init__.py @@ -1,3 +1 @@ -from ._version import __version__ - default_app_config = "aleksis.apps.ticdesk.apps.TICDeskConfig" diff --git a/aleksis/apps/ticdesk/filters.py b/aleksis/apps/ticdesk/filters.py index 6cd3acc..9656830 100644 --- a/aleksis/apps/ticdesk/filters.py +++ b/aleksis/apps/ticdesk/filters.py @@ -1,13 +1,14 @@ -from django_filters import FilterSet -from material import Layout, Row from django.utils.translation import gettext_lazy as _ -from .models import EventRegistration, TeckidsMember, Voucher, FeedbackAspect +from django_filters import FilterSet +from material import Layout, Row from aleksis.core.filters import MultipleCharFilter -class EventRegistrationFilter(FilterSet): +from .models import EventRegistration, FeedbackAspect, TeckidsMember, Voucher + +class EventRegistrationFilter(FilterSet): class Meta: model = EventRegistration fields = ["person", "event", "accept_sepa", "date_registred"] @@ -16,19 +17,15 @@ class EventRegistrationFilter(FilterSet): super().__init__(*args, **kwargs) self.form.layout = Layout( - Row("person", "event"), - Row("accept_sepa", "date_registred"), + Row("person", "event"), Row("accept_sepa", "date_registred"), ) class TeckidsMemberFilter(FilterSet): name = MultipleCharFilter( - [ - "person__first_name__icontains", - "person__last_name__icontains", - ], - label = _("Search by name"), + ["person__first_name__icontains", "person__last_name__icontains",], + label=_("Search by name"), ) class Meta: @@ -45,18 +42,12 @@ class TeckidsMemberFilter(FilterSet): class VoucherFilter(FilterSet): event = MultipleCharFilter( - [ - "project__short_name__icontains", - ], - label = _("Search by event"), + ["project__short_name__icontains",], label=_("Search by event"), ) name = MultipleCharFilter( - [ - "person__first_name__icontains", - "person__last_name__icontains", - ], - label = _("Search by name"), + ["person__first_name__icontains", "person__last_name__icontains",], + label=_("Search by name"), ) class Meta: @@ -68,8 +59,8 @@ class VoucherFilter(FilterSet): self.form.layout = Layout(Row("event", "name")) -class FeedbackAspectsFilter(FilterSet): +class FeedbackAspectsFilter(FilterSet): class Meta: model = FeedbackAspect fields = ["aspect"] diff --git a/aleksis/apps/ticdesk/forms.py b/aleksis/apps/ticdesk/forms.py index 2ac0abb..d04ca81 100644 --- a/aleksis/apps/ticdesk/forms.py +++ b/aleksis/apps/ticdesk/forms.py @@ -2,23 +2,28 @@ import re from collections import OrderedDict from django import forms -from django.apps import apps -from django.core import validators from django.utils.translation import ugettext_lazy as _ -from django_select2.forms import ModelSelect2MultipleWidget, Select2Widget import phonenumbers +from django_select2.forms import ModelSelect2MultipleWidget from django_starfield import Stars -from localflavor.generic.countries.sepa import IBAN_SEPA_COUNTRIES -from localflavor.generic.forms import IBANFormField from material import Fieldset, Layout, Row -from .models import Voucher, TeckidsProject, MailAddress, SSHKey, PGPKey, EventRegistration, TeckidsMember, FeedbackAspect - -from aleksis.core.models import Person, Group from aleksis.core.mixins import ExtensibleForm +from aleksis.core.models import Group, Person from aleksis.core.util.core_helpers import get_site_preferences +from .models import ( + EventRegistration, + FeedbackAspect, + MailAddress, + PGPKey, + SSHKey, + TeckidsMember, + TeckidsProject, + Voucher, +) + COMMENT_CHOICES = [ ("first", _("Only first name")), ("first_age", _("First name and age")), @@ -36,7 +41,8 @@ LICENCE_CHOICES = [ ( "CC-BY-SA-4.0+", _( - "Creative Commons with attribution and distribution only under the same conditions, 4.0 or later" + "Creative Commons with attribution and distribution only" + "under the same conditions, 4.0 or later" ), ), ] @@ -82,6 +88,7 @@ def clean_phonenumber(field): return _clean_phonenumber + class EventAdditionalSurveyForm(forms.Form): def __init__(self, project, *args, **kwargs): super().__init__(*args, **kwargs) @@ -128,30 +135,25 @@ class EventAdditionalSurveyForm(forms.Form): class EventFeedbackForm(ExtensibleForm): - class Meta: - model = FeedbackAspect - fields = [] + model = FeedbackAspect + fields = [] layout = Layout( Fieldset( _("Comments"), Row("comment_private", "comment_public", "comment_public_info"), ), - Fieldset( - _("Photos"), - Row("photos", "photos_licence"), - ), - Fieldset( - _("Feedback aspects"), - ), + Fieldset(_("Photos"), Row("photos", "photos_licence"),), + Fieldset(_("Feedback aspects"),), ) comment_private = forms.CharField( required=False, label=_("Comment for the team"), help_text=_( - "This comment is for the team only. You can write down everything you would like to give us as feedback here." + "This comment is for the team only. You can write down everything you" + "would like to give us as feedback here." ), widget=forms.Textarea, ) @@ -160,7 +162,9 @@ class EventFeedbackForm(ExtensibleForm): required=False, label=_("Comment for the website"), help_text=_( - "This comment is for the report on our website. Tell in detail about what you experienced, what you liked, what you learned and everything else you can think of." + "This comment is for the report on our website. Tell in detail about what" + "you experienced, what you liked, what you learned and everything else" + "you can think of." ), widget=forms.Textarea, ) @@ -176,7 +180,8 @@ class EventFeedbackForm(ExtensibleForm): widget=forms.ClearableFileInput(attrs={"multiple": True}), required=False, help_text=_( - "If you want to contribute photos to the report, you can upload them here. You can select multiple files in most file selection dialogs with CTRL + click." + "If you want to contribute photos to the report, you can upload them here. You can" + "select multiple files in most file selection dialogs with CTRL + click." ), ) @@ -192,10 +197,7 @@ class EventFeedbackForm(ExtensibleForm): self._project = project for aspect in project.feedback_aspects.all(): - field = forms.IntegerField( - widget=Stars, - required=False, - ) + field = forms.IntegerField(widget=Stars, required=False,) self.fields[aspect.aspect] = field node = Fieldset(f"{aspect.aspect}", f"{aspect.aspect}") self.add_node_to_layout(node) @@ -205,19 +207,9 @@ class EditEventForm(forms.ModelForm): """Form to create or edit an event.""" layout = Layout( - Fieldset( - _("Base data"), - Row("short_name", "display_name"), - "description", - ), - Fieldset( - _("Persons"), - Row("members", "owners"), - ), - Fieldset( - _("Feedback aspects"), - "feedback_aspects", - ), + Fieldset(_("Base data"), Row("short_name", "display_name"), "description",), + Fieldset(_("Persons"), Row("members", "owners"),), + Fieldset(_("Feedback aspects"), "feedback_aspects",), Fieldset( _("Event settings"), Row("date_event", "date_registration", "date_retraction"), @@ -226,7 +218,6 @@ class EditEventForm(forms.ModelForm): "published", ), ) - class Meta: model = TeckidsProject @@ -244,7 +235,8 @@ class EditEventForm(forms.ModelForm): MAIL_LOCAL_REGEX = r"^[a-z][a-z0-9._-]{1,29}$" MAIL_LOCAL_MESSAGE = _( - "The local part of the email address may only consist of lowercase letters, numbers, periods, hyphens and underscores and must begin with a letter!" + "The local part of the email address may only consist of lowercase letters, numbers," + "periods, hyphens and underscores and must begin with a letter!" ) @@ -322,18 +314,9 @@ class RegisterEventForm(forms.ModelForm): Row("street", "housenumber"), Row("postal_code", "place"), ), - Fieldset( - _("Contact details"), - Row("mobile_number", "email"), - ), - Fieldset( - _("Personal data"), - Row("date_of_birth", "sex"), - ), - Fieldset( - _("School details"), - Row("school", "school_place", "school_class"), - ), + Fieldset(_("Contact details"), Row("mobile_number", "email"),), + Fieldset(_("Personal data"), Row("date_of_birth", "sex"),), + Fieldset(_("School details"), Row("school", "school_place", "school_class"),), Fieldset( _("Guardians personal data"), Row("guardian_first_name", "guardian_last_name"), @@ -348,9 +331,7 @@ class RegisterEventForm(forms.ModelForm): Row("comment", "channel"), ), Fieldset( - _("Financial data"), - "voucher_code", - Row("iban", "donation", "accept_sepa"), + _("Financial data"), "voucher_code", Row("iban", "donation", "accept_sepa"), ), Fieldset( _("Declaration of consent"), @@ -362,99 +343,144 @@ class RegisterEventForm(forms.ModelForm): model = EventRegistration exclude = ["date_registred", "voucher"] help_texts = { - "voucher": _("If you have a voucher for the event, enter the code here. It will be charged automatically."), - "donation": ("Our association would like to offer all children and young people the opportunity to participate in our events. Often, however, the family fee cannot be paid. We therefore have a budget from which we can promote participation after we have carefully examined the necessity and eligibility. We rely on donations for this budget. If you would like to donate a voluntary additional amount for this budget, please indicate this here. We do not permanently save whether and if so in what amount donations are made and also not within the association, e.g. passed on to leisure supervisors."), - "accept_sepa": _("Parents: I authorize the creditor Teckids e.V., Rochusstr. 2-4, 53123 Bonn with creditor ID DE70FZT00001497650, to collect the participant fee from my account once using the SEPA core direct debit. At the same time, I instruct my bank to redeem the SEPA core direct debit withdrawn from my account by Teckids e.V."), - "iban": _("If your parents want to pay by SEPA direct debit, please let them fill out this field."), - "accept_terms": _("Parents: My child filled out the registration form together with me, but myself, and I agree to the participation, the terms of use and the terms and conditions. I am aware that the registration is binding and that withdrawal is only possible in exceptional cases with a valid reason. In addition, I agree to pay the participation fee in advance and agree to the reimbursement guidelines mentioned above."), - "accept_data": _("I consent to the processing of my data as stated in the <a href='https://www.teckids.org/kleingedrucktes/nutzungsbedingungen/'> terms of use </a> and all the data provided is correct. If I am under the age of 16, my parents also agree to this and I can prove this on request (e.g. by making contact with my parents)."), - "accept_general_terms": _("I agree with the <a href='https://www.teckids.org/de/kleingedrucktes/agb-fur-freizeiten/'> AGB </a> and have read them."), + "voucher": _( + "If you have a voucher for the event, enter the code here." + "It will be charged automatically." + ), + "donation": ( + "Our association would like to offer all children and young" + "people the opportunity to participate in our events. Often," + "however, the family fee cannot be paid. We therefore have a" + "budget from which we can promote participation after we have" + "carefully examined the necessity and eligibility. We rely on" + "donations for this budget. If you would like to donate a voluntary" + "additional amount for this budget, please indicate this here. We do" + "not permanently save whether and if so in what amount donations are" + "made and also not within the association, e.g. passed on to leisure supervisors." + ), + "accept_sepa": _( + "Parents: I authorize the creditor Teckids e.V., Rochusstr. 2-4, 53123 Bonn with" + "creditor ID DE70FZT00001497650, to collect the participant fee from my account" + "once using the SEPA core direct debit. At the same time, I instruct my bank to" + "redeem the SEPA core direct debit withdrawn from my account by Teckids e.V." + ), + "iban": _( + "If your parents want to pay by SEPA direct debit," + "please let them fill out this field." + ), + "accept_terms": _( + "Parents: My child filled out the registration form together with me, but myself," + "and I agree to the participation, the terms of use and the terms and conditions." + "I am aware that the registration is binding and that withdrawal is only possible" + "in exceptional cases with a valid reason. In addition, I agree to pay the" + "participation fee in advance and agree to the reimbursement guidelines" + "mentioned above." + ), + "accept_data": _( + "I consent to the processing of my data as stated in the" + "<a href='https://www.teckids.org/kleingedrucktes/nutzungsbedingungen/'>" + "terms of use </a> and all the data provided is correct. If I am under the" + "age of 16, my parents also agree to this and I can prove this on request" + "(e.g. by making contact with my parents)." + ), + "accept_general_terms": _( + "I agree with the" + "<a href='https://www.teckids.org/de/kleingedrucktes/agb-fur-freizeiten/'>" + "AGB </a> and have read them." + ), "channel": _("How did you find out about the event?"), } guardian_first_name = forms.CharField( - label = _("Guardians first name"), - help_text = _("Please enter the first name of the legal guardian who will fill in the registration with you and who can be reached during the event in an emergency."), + label=_("Guardians first name"), + help_text=_( + "Please enter the first name of the legal guardian who will fill in the registration" + "with you and who can be reached during the event in an emergency." + ), ) guardian_last_name = forms.CharField( - label = _("Guardians last name"), - help_text = _("Please enter the last name of the legal guardian who will fill in the registration with you and who can be reached during the event in an emergency."), + label=_("Guardians last name"), + help_text=_( + "Please enter the last name of the legal guardian who will fill in the registration" + "with you and who can be reached during the event in an emergency." + ), ) guardian_mobile_number = forms.CharField( - label = _("Guardians mobile number"), - help_text = _("We need the mobile phone number for emergencies if we urgently need to reach your parents during the event."), + label=_("Guardians mobile number"), + help_text=_( + "We need the mobile phone number for emergencies if we" + "urgently need to reach your parents during the event." + ), ) - guardian_email = forms.EmailField( - label = _("Guardians email address"), - ) + guardian_email = forms.EmailField(label=_("Guardians email address"),) voucher_code = forms.CharField( - label = _("Voucher code"), - help_text = _("If you have a voucher code, type it in here."), - required = False, + label=_("Voucher code"), + help_text=_("If you have a voucher code, type it in here."), + required=False, ) - street = forms.CharField( - label = _("Street"), - ) + street = forms.CharField(label=_("Street"),) - housenumber = forms.CharField( - label = _("Housenumber"), - ) + housenumber = forms.CharField(label=_("Housenumber"),) - postal_code = forms.CharField( - label = _("Postal code"), - ) + postal_code = forms.CharField(label=_("Postal code"),) - place = forms.CharField( - label = _("Place"), - ) + place = forms.CharField(label=_("Place"),) mobile_number = forms.CharField( - label = _("Mobile number"), - required = False, - help_text = _("Your mobile number helps us to reach you in an emergency during the event, e.g. if you are alone with your group at a conference or similar. If you don't have a cell phone, you can leave the field blank."), - validators = [is_phonenumber], + label=_("Mobile number"), + required=False, + help_text=_( + "Your mobile number helps us to reach you in an emergency during the event, e.g." + "if you are alone with your group at a conference or similar. If you don't have a" + "cell phone, you can leave the field blank." + ), + validators=[is_phonenumber], ) - date_of_birth = forms.DateField( - label = _("Date of birth"), - ) + date_of_birth = forms.DateField(label=_("Date of birth"),) sex = forms.ChoiceField( - label = _("Sex"), - help_text = _("For various reasons, e.g. because we have to keep gender segregation during the night for legal reasons, we need to know if you are a boy or a girl. With some names this is not always immediately recognizable, so we ask you to indicate it here."), - choices = Person.SEX_CHOICES, - initial = None, + label=_("Sex"), + help_text=_( + "For various reasons, e.g. because we have to keep gender segregation during the night" + "for legal reasons, we need to know if you are a boy or a girl. With some names this is" + "not always immediately recognizable, so we ask you to indicate it here." + ), + choices=Person.SEX_CHOICES, + initial=None, ) - email = forms.EmailField( - label = _("Email address"), - ) + email = forms.EmailField(label=_("Email address"),) school = forms.CharField( - label = _("School"), - help_text = _("Please enter the name of your school as exactly as it should be written."), + label=_("School"), + help_text=_( + "Please enter the name of your school as exactly as it should be written." + ), ) school_place = forms.CharField( - label = _("School place"), - help_text = _("Enter the place (city) where your school is located (without a district)."), + label=_("School place"), + help_text=_( + "Enter the place (city) where your school is located (without a district)." + ), ) school_class = forms.CharField( - label = _("School class"), - help_text = _("Please enter the class you are going to (e.g. 8a)."), + label=_("School class"), + help_text=_("Please enter the class you are going to (e.g. 8a)."), ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields["event"].disabled = True - self.fields["person"].disabled = True + self.fields["person"].disabled = True self.fields["accept_terms"].required = True self.fields["accept_general_terms"].required = True self.fields["accept_data"].required = True @@ -470,10 +496,7 @@ class EditTeckidsMemberForm(forms.ModelForm): Row("employee_number", "title"), Row("member_since", "member_until"), ), - Fieldset( - _("Financial information"), - Row("dues", "dues_sepa"), - ), + Fieldset(_("Financial information"), Row("dues", "dues_sepa"),), ) class Meta: @@ -481,7 +504,9 @@ class EditTeckidsMemberForm(forms.ModelForm): exclude = [] help_texts = { "employee_number": _("Only change if you know what you're doing!"), - "title": _("Members title. For example: „Systemadministrator, Tutor Spieleprogrammieren“"), + "title": _( + "Members title. For example: „Systemadministrator, Tutor Spieleprogrammieren“" + ), "member_since": _("Start of membership"), "member_until": _("End of membership"), "dues": _("Yearly payed membership dues"), @@ -499,9 +524,7 @@ class EditEventRegistrationForm(forms.ModelForm): Row("comment", "channel"), ), Fieldset( - _("Financial data"), - "voucher_code", - Row("iban", "donation", "accept_sepa"), + _("Financial data"), "voucher_code", Row("iban", "donation", "accept_sepa"), ), Fieldset( _("Declaration of consent"), @@ -512,20 +535,57 @@ class EditEventRegistrationForm(forms.ModelForm): class Meta: model = EventRegistration help_texts = { - "voucher": _("If you have a voucher for the event, enter the code here. It will be charged automatically."), - "donation": ("Our association would like to offer all children and young people the opportunity to participate in our events. Often, however, the family fee cannot be paid. We therefore have a budget from which we can promote participation after we have carefully examined the necessity and eligibility. We rely on donations for this budget. If you would like to donate a voluntary additional amount for this budget, please indicate this here. We do not permanently save whether and if so in what amount donations are made and also not within the association, e.g. passed on to leisure supervisors."), - "accept_sepa": _("Parents: I authorize the creditor Teckids e.V., Rochusstr. 2-4, 53123 Bonn with creditor ID DE70FZT00001497650, to collect the participant fee from my account once using the SEPA core direct debit. At the same time, I instruct my bank to redeem the SEPA core direct debit withdrawn from my account by Teckids e.V."), - "iban": _("If your parents want to pay by SEPA direct debit, please let them fill out this field."), - "accept_terms": _("Parents: My child filled out the registration form together with me, but myself, and I agree to the participation, the terms of use and the terms and conditions. I am aware that the registration is binding and that withdrawal is only possible in exceptional cases with a valid reason. In addition, I agree to pay the participation fee in advance and agree to the reimbursement guidelines mentioned above."), - "accept_data": _("I consent to the processing of my data as stated in the <a href='https://www.teckids.org/kleingedrucktes/nutzungsbedingungen/'> terms of use </a> and all the data provided is correct. If I am under the age of 16, my parents also agree to this and I can prove this on request (e.g. by making contact with my parents)."), - "accept_general_terms": _("I agree with the <a href='https://www.teckids.org/de/kleingedrucktes/agb-fur-freizeiten/'> AGB </a> and have read them."), + "voucher": _( + "If you have a voucher for the event, enter the code here." + "It will be charged automatically." + ), + "donation": ( + "Our association would like to offer all children and young" + "people the opportunity to participate in our events. Often," + "however, the family fee cannot be paid. We therefore have a" + "budget from which we can promote participation after we have" + "carefully examined the necessity and eligibility. We rely on" + "donations for this budget. If you would like to donate a voluntary" + "additional amount for this budget, please indicate this here. We do not" + "permanently save whether and if so in what amount donations are made" + "and also not within the association, e.g. passed on to leisure supervisors." + ), + "accept_sepa": _( + "Parents: I authorize the creditor Teckids e.V., Rochusstr. 2-4, 53123 Bonn with" + "creditor ID DE70FZT00001497650, to collect the participant fee from my account" + "once using the SEPA core direct debit. At the same time, I instruct my bank" + "to redeem the SEPA core direct debit withdrawn from my account by Teckids e.V." + ), + "iban": _( + "If your parents want to pay by SEPA direct debit," + "please let them fill out this field." + ), + "accept_terms": _( + "Parents: My child filled out the registration form together with me, but myself," + "and I agree to the participation, the terms of use and the terms and conditions." + "I am aware that the registration is binding and that withdrawal is only possible" + "in exceptional cases with a valid reason. In addition, I agree to pay the" + "participation fee in advance and agree to the reimbursement" + "guidelines mentioned above." + ), + "accept_data": _( + "I consent to the processing of my data as stated in the" + "<a href='https://www.teckids.org/kleingedrucktes/nutzungsbedingungen/'>" + "terms of use </a> and all the data provided is correct. If I am under" + "the age of 16, my parents also agree to this and I can prove this on" + "request (e.g. by making contact with my parents)." + ), + "accept_general_terms": _( + "I agree with the" + "<a href='https://www.teckids.org/de/kleingedrucktes/agb-fur-freizeiten/'>" + "AGB </a> and have read them." + ), "channel": _("How did you find out about the event?"), } exclude = [] class EditFeedbackAspectForm(forms.ModelForm): - class Meta: model = FeedbackAspect exclude = [] diff --git a/aleksis/apps/ticdesk/menus.py b/aleksis/apps/ticdesk/menus.py index 65688c1..14a51f2 100644 --- a/aleksis/apps/ticdesk/menus.py +++ b/aleksis/apps/ticdesk/menus.py @@ -12,16 +12,8 @@ MENUS = { ("aleksis.core.util.predicates.permission_validator", "core.has_person") ], "submenu": [ - { - "name": _("Mail addresses"), - "url": "manage_mail", - "icon": "email", - }, - { - "name": _("SSH keys"), - "url": "manage_ssh_keys", - "icon": "vpn_key", - }, + {"name": _("Mail addresses"), "url": "manage_mail", "icon": "email",}, + {"name": _("SSH keys"), "url": "manage_ssh_keys", "icon": "vpn_key",}, { "name": _("PGP keys"), "url": "manage_pgp_keys", @@ -146,16 +138,8 @@ MENUS = { ) ], "submenu": [ - { - "name": _("List members"), - "icon": "list", - "url": "members", - }, - { - "name": _("New member"), - "icon": "add", - "url": "create_member", - }, + {"name": _("List members"), "icon": "list", "url": "members",}, + {"name": _("New member"), "icon": "add", "url": "create_member",}, ], }, ], diff --git a/aleksis/apps/ticdesk/migrations/0007_auto_20200728_1145.py b/aleksis/apps/ticdesk/migrations/0007_auto_20200728_1145.py index 268fd55..e8a18d4 100644 --- a/aleksis/apps/ticdesk/migrations/0007_auto_20200728_1145.py +++ b/aleksis/apps/ticdesk/migrations/0007_auto_20200728_1145.py @@ -9,41 +9,118 @@ import django.db.models.deletion class Migration(migrations.Migration): dependencies = [ - ('core', '0004_auto_20200728_1145'), - ('sites', '0002_alter_domain_unique'), - ('ticdesk', '0006_teckidsmember'), + ("core", "0004_auto_20200728_1145"), + ("sites", "0002_alter_domain_unique"), + ("ticdesk", "0006_teckidsmember"), ] operations = [ migrations.AlterModelOptions( - name='globalpermissions', - options={'managed': False, 'permissions': (('view_vouchers', 'Can view vouchers'), ('edit_vouchers', 'Can edit vouchers'), ('delete_vouchers', 'Can delete vouchers'), ('create_vouchers', 'Can create vouchers'), ('edit_events', 'Can edit events'), ('create_events', 'Can create events'), ('delete_events', 'Can delete events'), ('generate_lists', 'Can generate lists'))}, + name="globalpermissions", + options={ + "managed": False, + "permissions": ( + ("view_vouchers", "Can view vouchers"), + ("edit_vouchers", "Can edit vouchers"), + ("delete_vouchers", "Can delete vouchers"), + ("create_vouchers", "Can create vouchers"), + ("edit_events", "Can edit events"), + ("create_events", "Can create events"), + ("delete_events", "Can delete events"), + ("generate_lists", "Can generate lists"), + ), + }, ), migrations.CreateModel( - name='EventRegistration', + name="EventRegistration", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('extended_data', django.contrib.postgres.fields.jsonb.JSONField(default=dict, editable=False)), - ('date_registred', models.DateTimeField(auto_now_add=True, verbose_name='Registration date')), - ('comment', models.TextField(verbose_name='Comment / remarks')), - ('channel', models.CharField(max_length=255, verbose_name='Channel')), - ('donation', models.PositiveIntegerField(verbose_name='Donation')), - ('accept_sepa', models.BooleanField(verbose_name='SEPA direct debit')), - ('iban', models.CharField(max_length=255, verbose_name='IBAN (for SEPA direct debit)')), - ('accept_terms', models.BooleanField(verbose_name='Delcaration of consent by parents')), - ('accept_data', models.BooleanField(verbose_name='Declaration of consent data protection')), - ('accept_general_terms', models.BooleanField(verbose_name='Declatation of consent terms and condition')), - ('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='ticdesk.TeckidsProject', verbose_name='Event')), - ('person', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Person', verbose_name='Person')), - ('site', models.ForeignKey(default=1, editable=False, on_delete=django.db.models.deletion.CASCADE, to='sites.Site')), - ('voucher', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='ticdesk.Voucher', verbose_name='Voucher')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "extended_data", + django.contrib.postgres.fields.jsonb.JSONField( + default=dict, editable=False + ), + ), + ( + "date_registred", + models.DateTimeField( + auto_now_add=True, verbose_name="Registration date" + ), + ), + ("comment", models.TextField(verbose_name="Comment / remarks")), + ("channel", models.CharField(max_length=255, verbose_name="Channel")), + ("donation", models.PositiveIntegerField(verbose_name="Donation")), + ("accept_sepa", models.BooleanField(verbose_name="SEPA direct debit")), + ( + "iban", + models.CharField( + max_length=255, verbose_name="IBAN (for SEPA direct debit)" + ), + ), + ( + "accept_terms", + models.BooleanField( + verbose_name="Delcaration of consent by parents" + ), + ), + ( + "accept_data", + models.BooleanField( + verbose_name="Declaration of consent data protection" + ), + ), + ( + "accept_general_terms", + models.BooleanField( + verbose_name="Declatation of consent terms and condition" + ), + ), + ( + "event", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="ticdesk.TeckidsProject", + verbose_name="Event", + ), + ), + ( + "person", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="core.Person", + verbose_name="Person", + ), + ), + ( + "site", + models.ForeignKey( + default=1, + editable=False, + on_delete=django.db.models.deletion.CASCADE, + to="sites.Site", + ), + ), + ( + "voucher", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="ticdesk.Voucher", + verbose_name="Voucher", + ), + ), ], options={ - 'verbose_name': 'Registration', - 'verbose_name_plural': 'Registrations', + "verbose_name": "Registration", + "verbose_name_plural": "Registrations", }, - managers=[ - ('objects', django.contrib.sites.managers.CurrentSiteManager()), - ], + managers=[("objects", django.contrib.sites.managers.CurrentSiteManager()),], ), ] diff --git a/aleksis/apps/ticdesk/migrations/0008_auto_20200728_1352.py b/aleksis/apps/ticdesk/migrations/0008_auto_20200728_1352.py index 1bdffab..22d621c 100644 --- a/aleksis/apps/ticdesk/migrations/0008_auto_20200728_1352.py +++ b/aleksis/apps/ticdesk/migrations/0008_auto_20200728_1352.py @@ -6,12 +6,16 @@ from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('ticdesk', '0007_auto_20200728_1145'), + ("ticdesk", "0007_auto_20200728_1145"), ] operations = [ migrations.AlterModelOptions( - name='teckidsproject', - options={'ordering': ('date_event',), 'verbose_name': 'Teckids project', 'verbose_name_plural': 'Teckids projects'}, + name="teckidsproject", + options={ + "ordering": ("date_event",), + "verbose_name": "Teckids project", + "verbose_name_plural": "Teckids projects", + }, ), ] diff --git a/aleksis/apps/ticdesk/migrations/0009_auto_20200728_1504.py b/aleksis/apps/ticdesk/migrations/0009_auto_20200728_1504.py index 9a9bedb..9db8982 100644 --- a/aleksis/apps/ticdesk/migrations/0009_auto_20200728_1504.py +++ b/aleksis/apps/ticdesk/migrations/0009_auto_20200728_1504.py @@ -6,13 +6,24 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('ticdesk', '0008_auto_20200728_1352'), + ("ticdesk", "0008_auto_20200728_1352"), ] operations = [ migrations.AlterField( - model_name='eventregistration', - name='channel', - field=models.CharField(choices=[('none', 'No information'), ('internet', 'From internet'), ('school', 'From school'), ('friends', 'From friends'), ('parents', 'From parents'), ('newsletter', 'From newsletter')], max_length=255, verbose_name='Channel'), + model_name="eventregistration", + name="channel", + field=models.CharField( + choices=[ + ("none", "No information"), + ("internet", "From internet"), + ("school", "From school"), + ("friends", "From friends"), + ("parents", "From parents"), + ("newsletter", "From newsletter"), + ], + max_length=255, + verbose_name="Channel", + ), ), ] diff --git a/aleksis/apps/ticdesk/migrations/0010_auto_20200728_2017.py b/aleksis/apps/ticdesk/migrations/0010_auto_20200728_2017.py index 5d6d59d..870b4a6 100644 --- a/aleksis/apps/ticdesk/migrations/0010_auto_20200728_2017.py +++ b/aleksis/apps/ticdesk/migrations/0010_auto_20200728_2017.py @@ -6,28 +6,50 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('ticdesk', '0009_auto_20200728_1504'), + ("ticdesk", "0009_auto_20200728_1504"), ] operations = [ migrations.AlterField( - model_name='eventregistration', - name='channel', - field=models.CharField(blank=True, choices=[('none', 'No information'), ('internet', 'From internet'), ('school', 'From school'), ('friends', 'From friends'), ('parents', 'From parents'), ('newsletter', 'From newsletter')], max_length=255, null=True, verbose_name='Channel'), + model_name="eventregistration", + name="channel", + field=models.CharField( + blank=True, + choices=[ + ("none", "No information"), + ("internet", "From internet"), + ("school", "From school"), + ("friends", "From friends"), + ("parents", "From parents"), + ("newsletter", "From newsletter"), + ], + max_length=255, + null=True, + verbose_name="Channel", + ), ), migrations.AlterField( - model_name='eventregistration', - name='comment', - field=models.TextField(blank=True, null=True, verbose_name='Comment / remarks'), + model_name="eventregistration", + name="comment", + field=models.TextField( + blank=True, null=True, verbose_name="Comment / remarks" + ), ), migrations.AlterField( - model_name='eventregistration', - name='donation', - field=models.PositiveIntegerField(blank=True, null=True, verbose_name='Donation'), + model_name="eventregistration", + name="donation", + field=models.PositiveIntegerField( + blank=True, null=True, verbose_name="Donation" + ), ), migrations.AlterField( - model_name='eventregistration', - name='iban', - field=models.CharField(blank=True, max_length=255, null=True, verbose_name='IBAN (for SEPA direct debit)'), + model_name="eventregistration", + name="iban", + field=models.CharField( + blank=True, + max_length=255, + null=True, + verbose_name="IBAN (for SEPA direct debit)", + ), ), ] diff --git a/aleksis/apps/ticdesk/migrations/0011_auto_20200728_2119.py b/aleksis/apps/ticdesk/migrations/0011_auto_20200728_2119.py index 8094746..fb89126 100644 --- a/aleksis/apps/ticdesk/migrations/0011_auto_20200728_2119.py +++ b/aleksis/apps/ticdesk/migrations/0011_auto_20200728_2119.py @@ -6,12 +6,26 @@ from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('ticdesk', '0010_auto_20200728_2017'), + ("ticdesk", "0010_auto_20200728_2017"), ] operations = [ migrations.AlterModelOptions( - name='globalpermissions', - options={'managed': False, 'permissions': (('view_vouchers', 'Can view vouchers'), ('edit_vouchers', 'Can edit vouchers'), ('delete_vouchers', 'Can delete vouchers'), ('create_vouchers', 'Can create vouchers'), ('edit_events', 'Can edit events'), ('create_events', 'Can create events'), ('delete_events', 'Can delete events'), ('generate_lists', 'Can generate lists'), ('manage_registrations', 'Can manage registrations'), ('view_registrations', 'Can view registrations'))}, + name="globalpermissions", + options={ + "managed": False, + "permissions": ( + ("view_vouchers", "Can view vouchers"), + ("edit_vouchers", "Can edit vouchers"), + ("delete_vouchers", "Can delete vouchers"), + ("create_vouchers", "Can create vouchers"), + ("edit_events", "Can edit events"), + ("create_events", "Can create events"), + ("delete_events", "Can delete events"), + ("generate_lists", "Can generate lists"), + ("manage_registrations", "Can manage registrations"), + ("view_registrations", "Can view registrations"), + ), + }, ), ] diff --git a/aleksis/apps/ticdesk/migrations/0012_auto_20200729_1640.py b/aleksis/apps/ticdesk/migrations/0012_auto_20200729_1640.py index 843b361..7d14d61 100644 --- a/aleksis/apps/ticdesk/migrations/0012_auto_20200729_1640.py +++ b/aleksis/apps/ticdesk/migrations/0012_auto_20200729_1640.py @@ -6,18 +6,24 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('ticdesk', '0011_auto_20200728_2119'), + ("ticdesk", "0011_auto_20200728_2119"), ] operations = [ migrations.AddField( - model_name='teckidsmember', - name='dues', - field=models.PositiveIntegerField(default=60, verbose_name='Membership dues in €'), + model_name="teckidsmember", + name="dues", + field=models.PositiveIntegerField( + default=60, verbose_name="Membership dues in €" + ), ), migrations.AddField( - model_name='teckidsmember', - name='dues_sepa', - field=models.DateField(blank=True, null=True, verbose_name='Membership dues SEPA direct debit mandate'), + model_name="teckidsmember", + name="dues_sepa", + field=models.DateField( + blank=True, + null=True, + verbose_name="Membership dues SEPA direct debit mandate", + ), ), ] diff --git a/aleksis/apps/ticdesk/migrations/0013_auto_20200729_1738.py b/aleksis/apps/ticdesk/migrations/0013_auto_20200729_1738.py index 6345fe0..638db84 100644 --- a/aleksis/apps/ticdesk/migrations/0013_auto_20200729_1738.py +++ b/aleksis/apps/ticdesk/migrations/0013_auto_20200729_1738.py @@ -6,13 +6,13 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('ticdesk', '0012_auto_20200729_1640'), + ("ticdesk", "0012_auto_20200729_1640"), ] operations = [ migrations.AlterField( - model_name='teckidsmember', - name='member_until', - field=models.DateField(blank=True, null=True, verbose_name='Member until'), + model_name="teckidsmember", + name="member_until", + field=models.DateField(blank=True, null=True, verbose_name="Member until"), ), ] diff --git a/aleksis/apps/ticdesk/migrations/0014_auto_20200731_1511.py b/aleksis/apps/ticdesk/migrations/0014_auto_20200731_1511.py index cb42c81..0f619fc 100644 --- a/aleksis/apps/ticdesk/migrations/0014_auto_20200731_1511.py +++ b/aleksis/apps/ticdesk/migrations/0014_auto_20200731_1511.py @@ -7,13 +7,19 @@ import django.db.models.deletion class Migration(migrations.Migration): dependencies = [ - ('ticdesk', '0013_auto_20200729_1738'), + ("ticdesk", "0013_auto_20200729_1738"), ] operations = [ migrations.AlterField( - model_name='eventregistration', - name='voucher', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='ticdesk.Voucher', verbose_name='Voucher'), + model_name="eventregistration", + name="voucher", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="ticdesk.Voucher", + verbose_name="Voucher", + ), ), ] diff --git a/aleksis/apps/ticdesk/migrations/0015_auto_20200802_1340.py b/aleksis/apps/ticdesk/migrations/0015_auto_20200802_1340.py index b8aff0c..2b8e021 100644 --- a/aleksis/apps/ticdesk/migrations/0015_auto_20200802_1340.py +++ b/aleksis/apps/ticdesk/migrations/0015_auto_20200802_1340.py @@ -6,18 +6,19 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('sites', '0002_alter_domain_unique'), - ('ticdesk', '0014_auto_20200731_1511'), + ("sites", "0002_alter_domain_unique"), + ("ticdesk", "0014_auto_20200731_1511"), ] operations = [ - migrations.RenameModel( - old_name='FeedbackAspects', - new_name='FeedbackAspect', - ), + migrations.RenameModel(old_name="FeedbackAspects", new_name="FeedbackAspect",), migrations.AddField( - model_name='teckidsproject', - name='feedback_aspects', - field=models.ManyToManyField(related_name='project', to='ticdesk.FeedbackAspect', verbose_name='Feedback aspects'), + model_name="teckidsproject", + name="feedback_aspects", + field=models.ManyToManyField( + related_name="project", + to="ticdesk.FeedbackAspect", + verbose_name="Feedback aspects", + ), ), ] diff --git a/aleksis/apps/ticdesk/migrations/0016_eventfeedback_feedbackfeedbackaspect.py b/aleksis/apps/ticdesk/migrations/0016_eventfeedback_feedbackfeedbackaspect.py index db9d9ec..f4cdbeb 100644 --- a/aleksis/apps/ticdesk/migrations/0016_eventfeedback_feedbackfeedbackaspect.py +++ b/aleksis/apps/ticdesk/migrations/0016_eventfeedback_feedbackfeedbackaspect.py @@ -9,50 +9,151 @@ import django.db.models.deletion class Migration(migrations.Migration): dependencies = [ - ('core', '0004_auto_20200728_1145'), - ('sites', '0002_alter_domain_unique'), - ('ticdesk', '0015_auto_20200802_1340'), + ("core", "0004_auto_20200728_1145"), + ("sites", "0002_alter_domain_unique"), + ("ticdesk", "0015_auto_20200802_1340"), ] operations = [ migrations.CreateModel( - name='FeedbackFeedbackAspect', + name="FeedbackFeedbackAspect", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('extended_data', django.contrib.postgres.fields.jsonb.JSONField(default=dict, editable=False)), - ('feedback', models.IntegerField()), - ('aspect', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='ticdesk.FeedbackAspect')), - ('person', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Person')), - ('site', models.ForeignKey(default=1, editable=False, on_delete=django.db.models.deletion.CASCADE, to='sites.Site')), - ], - options={ - 'abstract': False, - }, - managers=[ - ('objects', django.contrib.sites.managers.CurrentSiteManager()), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "extended_data", + django.contrib.postgres.fields.jsonb.JSONField( + default=dict, editable=False + ), + ), + ("feedback", models.IntegerField()), + ( + "aspect", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="ticdesk.FeedbackAspect", + ), + ), + ( + "person", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="core.Person" + ), + ), + ( + "site", + models.ForeignKey( + default=1, + editable=False, + on_delete=django.db.models.deletion.CASCADE, + to="sites.Site", + ), + ), ], + options={"abstract": False,}, + managers=[("objects", django.contrib.sites.managers.CurrentSiteManager()),], ), migrations.CreateModel( - name='EventFeedback', + name="EventFeedback", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('extended_data', django.contrib.postgres.fields.jsonb.JSONField(default=dict, editable=False)), - ('comment_team', models.TextField(verbose_name='Comment for the team')), - ('comment_public', models.TextField(verbose_name='Comment for the website')), - ('comment_public_info', models.CharField(choices=[('first', 'Only first name'), ('first_age', 'First name and age'), ('first_last_age', 'First name, last name and age')], max_length=255, verbose_name='Comment info')), - ('photos', models.FileField(upload_to='feedback_photos/', verbose_name='Photos')), - ('photo_licence', models.CharField(choices=[('CC-BY-4.0+', 'Creative Commons with attribution, 4.0 or later'), ('CC-BY-SA-4.0+', 'Creative Commons with attribution and distribution only under the same conditions, 4.0 or later')], max_length=255, verbose_name='Photo licence')), - ('feedback', models.ManyToManyField(to='ticdesk.FeedbackFeedbackAspect')), - ('person', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='event_feedback', to='core.Person', verbose_name='Person')), - ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='feedback', to='ticdesk.TeckidsProject', verbose_name='Project')), - ('site', models.ForeignKey(default=1, editable=False, on_delete=django.db.models.deletion.CASCADE, to='sites.Site')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "extended_data", + django.contrib.postgres.fields.jsonb.JSONField( + default=dict, editable=False + ), + ), + ("comment_team", models.TextField(verbose_name="Comment for the team")), + ( + "comment_public", + models.TextField(verbose_name="Comment for the website"), + ), + ( + "comment_public_info", + models.CharField( + choices=[ + ("first", "Only first name"), + ("first_age", "First name and age"), + ("first_last_age", "First name, last name and age"), + ], + max_length=255, + verbose_name="Comment info", + ), + ), + ( + "photos", + models.FileField( + upload_to="feedback_photos/", verbose_name="Photos" + ), + ), + ( + "photo_licence", + models.CharField( + choices=[ + ( + "CC-BY-4.0+", + "Creative Commons with attribution, 4.0 or later", + ), + ( + "CC-BY-SA-4.0+", + "Creative Commons with attribution and distribution only under the same conditions, 4.0 or later", + ), + ], + max_length=255, + verbose_name="Photo licence", + ), + ), + ( + "feedback", + models.ManyToManyField(to="ticdesk.FeedbackFeedbackAspect"), + ), + ( + "person", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="event_feedback", + to="core.Person", + verbose_name="Person", + ), + ), + ( + "project", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="feedback", + to="ticdesk.TeckidsProject", + verbose_name="Project", + ), + ), + ( + "site", + models.ForeignKey( + default=1, + editable=False, + on_delete=django.db.models.deletion.CASCADE, + to="sites.Site", + ), + ), ], options={ - 'verbose_name': 'Event feedback', - 'verbose_name_plural': 'Event feedbacks', + "verbose_name": "Event feedback", + "verbose_name_plural": "Event feedbacks", }, - managers=[ - ('objects', django.contrib.sites.managers.CurrentSiteManager()), - ], + managers=[("objects", django.contrib.sites.managers.CurrentSiteManager()),], ), ] diff --git a/aleksis/apps/ticdesk/migrations/0017_auto_20200802_1507.py b/aleksis/apps/ticdesk/migrations/0017_auto_20200802_1507.py index 19f8163..52aa5ef 100644 --- a/aleksis/apps/ticdesk/migrations/0017_auto_20200802_1507.py +++ b/aleksis/apps/ticdesk/migrations/0017_auto_20200802_1507.py @@ -6,23 +6,32 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('ticdesk', '0016_eventfeedback_feedbackfeedbackaspect'), + ("ticdesk", "0016_eventfeedback_feedbackfeedbackaspect"), ] operations = [ migrations.AlterField( - model_name='eventfeedback', - name='comment_public', - field=models.TextField(blank=True, null=True, verbose_name='Comment for the website'), + model_name="eventfeedback", + name="comment_public", + field=models.TextField( + blank=True, null=True, verbose_name="Comment for the website" + ), ), migrations.AlterField( - model_name='eventfeedback', - name='comment_team', - field=models.TextField(blank=True, null=True, verbose_name='Comment for the team'), + model_name="eventfeedback", + name="comment_team", + field=models.TextField( + blank=True, null=True, verbose_name="Comment for the team" + ), ), migrations.AlterField( - model_name='eventfeedback', - name='photos', - field=models.FileField(blank=True, null=True, upload_to='feedback_photos/', verbose_name='Photos'), + model_name="eventfeedback", + name="photos", + field=models.FileField( + blank=True, + null=True, + upload_to="feedback_photos/", + verbose_name="Photos", + ), ), ] diff --git a/aleksis/apps/ticdesk/migrations/0018_auto_20200802_1646.py b/aleksis/apps/ticdesk/migrations/0018_auto_20200802_1646.py index b625246..e7e0ebd 100644 --- a/aleksis/apps/ticdesk/migrations/0018_auto_20200802_1646.py +++ b/aleksis/apps/ticdesk/migrations/0018_auto_20200802_1646.py @@ -6,26 +6,13 @@ from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('ticdesk', '0017_auto_20200802_1507'), + ("ticdesk", "0017_auto_20200802_1507"), ] operations = [ - migrations.RemoveField( - model_name='feedbackfeedbackaspect', - name='aspect', - ), - migrations.RemoveField( - model_name='feedbackfeedbackaspect', - name='person', - ), - migrations.RemoveField( - model_name='feedbackfeedbackaspect', - name='site', - ), - migrations.DeleteModel( - name='EventFeedback', - ), - migrations.DeleteModel( - name='FeedbackFeedbackAspect', - ), + migrations.RemoveField(model_name="feedbackfeedbackaspect", name="aspect",), + migrations.RemoveField(model_name="feedbackfeedbackaspect", name="person",), + migrations.RemoveField(model_name="feedbackfeedbackaspect", name="site",), + migrations.DeleteModel(name="EventFeedback",), + migrations.DeleteModel(name="FeedbackFeedbackAspect",), ] diff --git a/aleksis/apps/ticdesk/model_extensions.py b/aleksis/apps/ticdesk/model_extensions.py index a848c13..863b95e 100644 --- a/aleksis/apps/ticdesk/model_extensions.py +++ b/aleksis/apps/ticdesk/model_extensions.py @@ -1,22 +1,24 @@ -from django.utils import timezone from django.utils.translation import gettext_lazy as _ -from jsonstore import CharField, DateField, IntegerField +from jsonstore import CharField -from aleksis.core.models import Group, Person +from aleksis.core.models import Person from .models import TeckidsMember + @Person.property_ def is_member_of(self, group): """ Check if person is member of a given group """ return group in self.member_of.all() + @Person.property_ def is_member(self) -> bool: """Check if person is still a member.""" - return (TeckidsMember.objects.filter(person=self).exists()) + return TeckidsMember.objects.filter(person=self).exists() + # Additional fields for persons Person.field(school=CharField(verbose_name=_("Name of school"))) diff --git a/aleksis/apps/ticdesk/models.py b/aleksis/apps/ticdesk/models.py index f937d96..6c51171 100644 --- a/aleksis/apps/ticdesk/models.py +++ b/aleksis/apps/ticdesk/models.py @@ -3,7 +3,7 @@ from django.utils import timezone from django.utils.translation import gettext_lazy as _ from aleksis.core.mixins import ExtensibleModel, PureDjangoModel -from aleksis.core.models import Person, Group +from aleksis.core.models import Person class TeckidsMember(ExtensibleModel): @@ -11,11 +11,19 @@ class TeckidsMember(ExtensibleModel): unique=True, verbose_name=_("Employee number") ) member_since = models.DateField(verbose_name=_("Member since")) - member_until = models.DateField(verbose_name=_("Member until"), blank=True, null=True) + member_until = models.DateField( + verbose_name=_("Member until"), blank=True, null=True + ) title = models.TextField(verbose_name=_("Title / Role")) - dues = models.PositiveIntegerField(verbose_name=_("Membership dues in €"), default=60) - dues_sepa = models.DateField(verbose_name=_("Membership dues SEPA direct debit mandate"), blank=True, null=True) + dues = models.PositiveIntegerField( + verbose_name=_("Membership dues in €"), default=60 + ) + dues_sepa = models.DateField( + verbose_name=_("Membership dues SEPA direct debit mandate"), + blank=True, + null=True, + ) person = models.ForeignKey(Person, on_delete=models.CASCADE) def __str__(self) -> str: @@ -133,7 +141,9 @@ class TeckidsProject(ExtensibleModel): def clean(self): if not self.gid_number: - self.gid_number = TeckidsProject.objects.order_by("-gid_number")[0].gid_number + 1 + self.gid_number = ( + TeckidsProject.objects.order_by("-gid_number")[0].gid_number + 1 + ) super(TeckidsProject, self).clean() @@ -241,6 +251,7 @@ class Voucher(ExtensibleModel): def __str__(self) -> str: return self.code + class GlobalPermissions(models.Model, PureDjangoModel): class Meta: managed = False @@ -257,6 +268,7 @@ class GlobalPermissions(models.Model, PureDjangoModel): ("view_registrations", _("Can view registrations")), ) + class EventRegistration(ExtensibleModel): class Meta: verbose_name = _("Registration") @@ -271,21 +283,54 @@ class EventRegistration(ExtensibleModel): ("newsletter", _("From newsletter")), ] - event = models.ForeignKey(TeckidsProject, on_delete=models.CASCADE, verbose_name=_("Event")) - person = models.ForeignKey(Person, on_delete=models.CASCADE, verbose_name=_("Person")) - date_registred = models.DateTimeField(auto_now_add=True, verbose_name=_("Registration date")) + event = models.ForeignKey( + TeckidsProject, on_delete=models.CASCADE, verbose_name=_("Event") + ) + person = models.ForeignKey( + Person, on_delete=models.CASCADE, verbose_name=_("Person") + ) + date_registred = models.DateTimeField( + auto_now_add=True, verbose_name=_("Registration date") + ) - comment = models.TextField(verbose_name=_("Comment / remarks"), blank=True, null=True) - channel = models.CharField(verbose_name=_("Channel"), max_length=255, choices=CHANNEL_CHOICES, blank=True, null=True) - voucher = models.ForeignKey(Voucher, on_delete=models.CASCADE, verbose_name=_("Voucher"), blank=True, null=True) - donation = models.PositiveIntegerField(verbose_name=_("Donation"), blank=True, null=True) + comment = models.TextField( + verbose_name=_("Comment / remarks"), blank=True, null=True + ) + channel = models.CharField( + verbose_name=_("Channel"), + max_length=255, + choices=CHANNEL_CHOICES, + blank=True, + null=True, + ) + voucher = models.ForeignKey( + Voucher, + on_delete=models.CASCADE, + verbose_name=_("Voucher"), + blank=True, + null=True, + ) + donation = models.PositiveIntegerField( + verbose_name=_("Donation"), blank=True, null=True + ) accept_sepa = models.BooleanField(verbose_name=_("SEPA direct debit")) - iban = models.CharField(max_length=255, verbose_name=_("IBAN (for SEPA direct debit)"), blank=True, null=True) + iban = models.CharField( + max_length=255, + verbose_name=_("IBAN (for SEPA direct debit)"), + blank=True, + null=True, + ) - accept_terms = models.BooleanField(verbose_name=_("Delcaration of consent by parents")) - accept_data = models.BooleanField(verbose_name=_("Declaration of consent data protection")) - accept_general_terms = models.BooleanField(verbose_name=_("Declatation of consent terms and condition")) + accept_terms = models.BooleanField( + verbose_name=_("Delcaration of consent by parents") + ) + accept_data = models.BooleanField( + verbose_name=_("Declaration of consent data protection") + ) + accept_general_terms = models.BooleanField( + verbose_name=_("Declatation of consent terms and condition") + ) def __str__(self) -> str: return f"{self.event}, {self.person.first_name} {self.person.last_name}" diff --git a/aleksis/apps/ticdesk/predicates.py b/aleksis/apps/ticdesk/predicates.py index a10b80b..fed88c5 100644 --- a/aleksis/apps/ticdesk/predicates.py +++ b/aleksis/apps/ticdesk/predicates.py @@ -5,7 +5,7 @@ from rules import predicate from aleksis.core.models import Group, Person from aleksis.core.util.predicates import check_object_permission -from .models import Voucher, SSHKey, PGPKey +from .models import PGPKey, SSHKey, Voucher User = get_user_model() @@ -25,12 +25,14 @@ def see_owned_groups_members(user: User, person: Person) -> bool: return Person.member_of.filter(id__in=groups_list).exists() + @predicate def is_own_voucher(user: User, voucher: Voucher) -> bool: """Predicate which checks if the voucher belongs to the user.""" return voucher.person == user.person + @predicate def is_own_ssh_key(user: User, ssh_key: SSHKey) -> bool: """Predicate which checks if the ssh_key belongs to the user.""" diff --git a/aleksis/apps/ticdesk/preferences.py b/aleksis/apps/ticdesk/preferences.py index 51fa746..de1f87e 100644 --- a/aleksis/apps/ticdesk/preferences.py +++ b/aleksis/apps/ticdesk/preferences.py @@ -4,7 +4,6 @@ from dynamic_preferences.preferences import Section from dynamic_preferences.types import StringPreference from aleksis.core.registries import site_preferences_registry -from aleksis.core.util.core_helpers import get_site_preferences ticdesk = Section("ticdesk") diff --git a/aleksis/apps/ticdesk/rules.py b/aleksis/apps/ticdesk/rules.py index f499cfb..b56d8c3 100644 --- a/aleksis/apps/ticdesk/rules.py +++ b/aleksis/apps/ticdesk/rules.py @@ -1,17 +1,23 @@ from rules import add_perm -from .models import Voucher, TeckidsProject, EventRegistration, TeckidsMember, FeedbackAspect -from .predicates import see_group_by_grouptype, see_owned_groups_members, is_own_voucher, is_own_ssh_key, is_own_pgp_key - -from aleksis.core.models import Announcement, Group, Person +from aleksis.core.models import Group from aleksis.core.util.predicates import ( has_any_object, - has_object_perm, has_global_perm, + has_object_perm, has_person, is_group_member, ) +from .models import EventRegistration, FeedbackAspect, TeckidsMember, TeckidsProject, Voucher +from .predicates import ( + is_own_pgp_key, + is_own_ssh_key, + is_own_voucher, + see_group_by_grouptype, + see_owned_groups_members, +) + # View vouchers view_vouchers_predicate = has_person & ( has_global_perm("ticdesk.view_vouchers") @@ -113,21 +119,15 @@ manage_teckids_members_predicate = has_person & ( add_perm("ticdesk.manage_teckids_members", manage_teckids_members_predicate) # Is own voucher? -is_own_voucher_predicate = has_person & ( - is_own_voucher -) +is_own_voucher_predicate = has_person & (is_own_voucher) add_perm("ticdesk.is_own_voucher", is_own_voucher_predicate) # Is own ssh key? -is_own_ssh_key_predicate = has_person & ( - is_own_ssh_key -) +is_own_ssh_key_predicate = has_person & (is_own_ssh_key) add_perm("ticdesk.is_own_ssh_key", is_own_ssh_key_predicate) # Is own pgp key? -is_own_pgp_key_predicate = has_person & ( - is_own_pgp_key -) +is_own_pgp_key_predicate = has_person & (is_own_pgp_key) add_perm("ticdesk.is_own_pgp_key", is_own_pgp_key_predicate) diff --git a/aleksis/apps/ticdesk/settings.py b/aleksis/apps/ticdesk/settings.py index e6c0ac1..9378041 100644 --- a/aleksis/apps/ticdesk/settings.py +++ b/aleksis/apps/ticdesk/settings.py @@ -1,9 +1,3 @@ -import os - -from django.utils.translation import gettext_lazy as _ - -from ._version import __version__ as VERSION - INSTALLED_APPS = [ "django_extensions", "django_starfield", diff --git a/aleksis/apps/ticdesk/tables.py b/aleksis/apps/ticdesk/tables.py index 7b9d5ce..2e9fc94 100644 --- a/aleksis/apps/ticdesk/tables.py +++ b/aleksis/apps/ticdesk/tables.py @@ -14,7 +14,10 @@ class EventsTable(tables.Table): date_registration = tables.Column(verbose_name=_("Registration until")) short_name = tables.LinkColumn( - "register_event_by_id", args=[A("id")], verbose_name=_("Register"), text=_("Register") + "register_event_by_id", + args=[A("id")], + verbose_name=_("Register"), + text=_("Register"), ) @@ -26,7 +29,10 @@ class ParticipatedEventsTable(tables.Table): date_event = tables.Column(verbose_name=_("Date")) short_name = tables.LinkColumn( - "feedback_event_by_id", args=[A("id")], verbose_name=_("Feedback"), text=_("Feedback") + "feedback_event_by_id", + args=[A("id")], + verbose_name=_("Feedback"), + text=_("Feedback"), ) @@ -53,7 +59,10 @@ class VouchersTable(tables.Table): code = tables.Column(verbose_name=_("Code")) person = tables.Column(verbose_name=_("Person")) deleted = tables.LinkColumn( - "delete_voucher_by_id", args=[A("id")], verbose_name=_("Delete"), text=_("Delete") + "delete_voucher_by_id", + args=[A("id")], + verbose_name=_("Delete"), + text=_("Delete"), ) edit = tables.LinkColumn( "edit_voucher_by_id", args=[A("id")], verbose_name=_("Edit"), text=_("Edit") @@ -62,6 +71,7 @@ class VouchersTable(tables.Table): "print_voucher_by_id", args=[A("id")], verbose_name=_("Print"), text=_("Print") ) + class EventRegistrationsTable(tables.Table): class Meta: attrs = {"class": "responsive-table highlight"} @@ -70,7 +80,10 @@ class EventRegistrationsTable(tables.Table): event = tables.Column() date_registred = tables.Column() view = tables.LinkColumn( - "registration_by_id", args=[A("id")], verbose_name=_("View registration"), text=_("View") + "registration_by_id", + args=[A("id")], + verbose_name=_("View registration"), + text=_("View"), ) @@ -83,7 +96,10 @@ class TeckidsMemberTable(tables.Table): member_since = tables.Column() member_until = tables.Column() edit = tables.LinkColumn( - "edit_member_by_id", args=[A("id")], verbose_name=_("Edit member"), text=_("Edit") + "edit_member_by_id", + args=[A("id")], + verbose_name=_("Edit member"), + text=_("Edit"), ) @@ -94,5 +110,8 @@ class FeedbackAspectsTable(tables.Table): aspect = tables.Column() edit = tables.LinkColumn( - "edit_feedback_aspect_by_id", args=[A("id")], verbose_name=_("Edit"), text=_("Edit") + "edit_feedback_aspect_by_id", + args=[A("id")], + verbose_name=_("Edit"), + text=_("Edit"), ) diff --git a/aleksis/apps/ticdesk/urls.py b/aleksis/apps/ticdesk/urls.py index 511ebe4..ec5744f 100644 --- a/aleksis/apps/ticdesk/urls.py +++ b/aleksis/apps/ticdesk/urls.py @@ -3,7 +3,11 @@ from django.urls import path from . import views urlpatterns = [ - path("event/<int:id_>/additional", views.register_event_additional, name="register_event_additional_by_id",), + path( + "event/<int:id_>/additional", + views.register_event_additional, + name="register_event_additional_by_id", + ), path("event/<int:id_>/edit", views.edit_event, name="edit_event_by_id"), path("event/<int:id_>/feedback", views.feedback_event, name="feedback_event_by_id"), path("event/<int:id_>/register", views.register_event, name="register_event_by_id"), @@ -11,24 +15,54 @@ urlpatterns = [ path("events/manage", views.manage_events, name="manage_events"), path("events/", views.events, name="events"), path("vouchers/create", views.edit_voucher, name="create_vouchers"), - path("vouchers/<int:id_>/delete", views.delete_voucher, name="delete_voucher_by_id"), + path( + "vouchers/<int:id_>/delete", views.delete_voucher, name="delete_voucher_by_id" + ), path("vouchers/<int:id_>/edit", views.edit_voucher, name="edit_voucher_by_id"), path("vouchers/<int:id_>/print", views.print_voucher, name="print_voucher_by_id"), path("vouchers/", views.vouchers, name="vouchers"), path("manage/mails", views.manage_mail, name="manage_mail"), path("manage/ssh_keys", views.manage_ssh_keys, name="manage_ssh_keys"), path("manage/pgp_keys", views.manage_pgp_keys, name="manage_pgp_keys"), - path("manage/ssh_keys/<int:id_>/delete", views.delete_sshkey, name="delete_sshkey_by_id"), - path("manage/pgp_keys/<int:id_>/delete", views.delete_pgpkey, name="delete_pgpkey_by_id"), + path( + "manage/ssh_keys/<int:id_>/delete", + views.delete_sshkey, + name="delete_sshkey_by_id", + ), + path( + "manage/pgp_keys/<int:id_>/delete", + views.delete_pgpkey, + name="delete_pgpkey_by_id", + ), path("event/lists/generate", views.generate_lists, name="generate_lists"), path("event/registrations/list", views.registrations, name="registrations"), - path("event/registrations/<int:id_>", views.registration, name="registration_by_id"), - path("event/registrations/<int:id_>/edit", views.edit_registration, name="edit_registration_by_id"), - path("event/registrations/<int:id_>/delete", views.delete_registration, name="delete_registration_by_id"), + path( + "event/registrations/<int:id_>", views.registration, name="registration_by_id" + ), + path( + "event/registrations/<int:id_>/edit", + views.edit_registration, + name="edit_registration_by_id", + ), + path( + "event/registrations/<int:id_>/delete", + views.delete_registration, + name="delete_registration_by_id", + ), path("members/list", views.members, name="members"), path("members/create", views.edit_member, name="create_member"), path("members/<int:id_>/edit", views.edit_member, name="edit_member_by_id"), - path("event/feedback_aspects/list", views.feedback_aspects, name="feedback_aspects"), - path("event/feedback_aspects/create", views.edit_feedback_aspect, name="create_feedback_aspect"), - path("event/feedback_aspects/<int:id_>/edit", views.edit_feedback_aspect, name="edit_feedback_aspect_by_id"), + path( + "event/feedback_aspects/list", views.feedback_aspects, name="feedback_aspects" + ), + path( + "event/feedback_aspects/create", + views.edit_feedback_aspect, + name="create_feedback_aspect", + ), + path( + "event/feedback_aspects/<int:id_>/edit", + views.edit_feedback_aspect, + name="edit_feedback_aspect_by_id", + ), ] diff --git a/aleksis/apps/ticdesk/util.py b/aleksis/apps/ticdesk/util.py index 50562ec..cfc51db 100644 --- a/aleksis/apps/ticdesk/util.py +++ b/aleksis/apps/ticdesk/util.py @@ -1,22 +1,13 @@ import os import random import string -import hashlib -from base64 import b64encode from tempfile import mkstemp from textwrap import wrap -from django.conf import settings -from django.forms import fields from django import forms -from django.utils.translation import ugettext as _ - -import hashlib -from base64 import b64encode +from django.conf import settings -import pexpect import requests -from pam import pam def subscribe_mailinglist(listname, mail): @@ -94,6 +85,6 @@ def upload_file_to_media_url(file, subdir="", prefix="upload_"): def generate_code(): alphabet = string.ascii_uppercase + string.digits length = 8 - code = ''.join(random.choice(alphabet) for _ in range(length)) + code = "".join(random.choice(alphabet) for _ in range(length)) return code diff --git a/aleksis/apps/ticdesk/views.py b/aleksis/apps/ticdesk/views.py index d5e0156..4d5ff12 100644 --- a/aleksis/apps/ticdesk/views.py +++ b/aleksis/apps/ticdesk/views.py @@ -3,63 +3,62 @@ import re from datetime import datetime from typing import Optional -from django.apps import apps from django.contrib.auth.decorators import login_required -from django.core.exceptions import ObjectDoesNotExist, PermissionDenied from django.core.mail import EmailMessage -from django.shortcuts import render, redirect from django.http import HttpRequest, HttpResponse +from django.shortcuts import redirect, render from django.utils.translation import ugettext as _ -from django.views.decorators.debug import sensitive_post_parameters +import pytz import reversion +from django_tables2 import RequestConfig from rules.contrib.views import permission_required -from templated_email import send_templated_mail -import pytz -from django_tables2 import RequestConfig -from ldap import INVALID_SYNTAX +from aleksis.core.models import Activity, Person +from aleksis.core.util import messages +from aleksis.core.util.core_helpers import objectgetter_optional +from .filters import ( + EventRegistrationFilter, + FeedbackAspectsFilter, + TeckidsMemberFilter, + VoucherFilter, +) from .forms import ( - EventAdditionalSurveyForm, - EventFeedbackForm, - RegisterEventForm, - EditVoucherForm, EditEventForm, - EditSSHKeyForm, - EditPGPKeyForm, - MailAddForm, - GenerateListForm, - EditTeckidsMemberForm, EditEventRegistrationForm, EditFeedbackAspectForm, + EditPGPKeyForm, + EditSSHKeyForm, + EditTeckidsMemberForm, + EditVoucherForm, + EventAdditionalSurveyForm, + EventFeedbackForm, + GenerateListForm, + MailAddForm, + RegisterEventForm, ) from .models import ( - RegistrationField, - TeckidsProject, - Voucher, + EventRegistration, + FeedbackAspect, MailAddress, - SSHKey, PGPKey, - EventRegistration, + RegistrationField, + SSHKey, TeckidsMember, - FeedbackAspect, + TeckidsProject, + Voucher, ) from .tables import ( + EventRegistrationsTable, EventsTable, + FeedbackAspectsTable, ManageEventsTable, ParticipatedEventsTable, - VouchersTable, - EventRegistrationsTable, TeckidsMemberTable, - FeedbackAspectsTable, + VouchersTable, ) -from .util import form_to_text_table, upload_file_to_media_url, generate_code -from .filters import EventRegistrationFilter, TeckidsMemberFilter, VoucherFilter, FeedbackAspectsFilter - -from aleksis.core.util.core_helpers import objectgetter_optional -from aleksis.core.util import messages -from aleksis.core.models import Activity, Person +from .util import form_to_text_table, generate_code, upload_file_to_media_url def events(request): @@ -77,9 +76,7 @@ def events(request): if request.user.is_authenticated: # Get all events the person participated in. current_person = Person.objects.get(user__username=request.user.username) - participated_events = TeckidsProject.objects.filter( - members=current_person - ) + participated_events = TeckidsProject.objects.filter(members=current_person) # Build table participated_events_table = ParticipatedEventsTable(participated_events) @@ -115,12 +112,14 @@ def register_event(request, id_): } if current_person.guardians.first(): - initial.update({ - "guardian_first_name": current_person.guardians.first().first_name, - "guardian_last_name": current_person.guardians.first().last_name, - "guardian_mobile_number": current_person.guardians.first().mobile_number, - "guardian_email": current_person.guardians.first().email, - }) + initial.update( + { + "guardian_first_name": current_person.guardians.first().first_name, + "guardian_last_name": current_person.guardians.first().last_name, + "guardian_mobile_number": current_person.guardians.first().mobile_number, + "guardian_email": current_person.guardians.first().email, + } + ) register_form = RegisterEventForm(initial=initial) @@ -149,9 +148,13 @@ def register_event(request, id_): current_person.school = register_form.cleaned_data["school"] current_person.school_class = register_form.cleaned_data["school_class"] current_person.school_place = register_form.cleaned_data["school_place"] - current_person.mobile_number = register_form.cleaned_data["mobile_number"] + current_person.mobile_number = register_form.cleaned_data[ + "mobile_number" + ] current_person.sex = register_form.cleaned_data["sex"] - current_person.date_of_birth = register_form.cleaned_data["date_of_birth"] + current_person.date_of_birth = register_form.cleaned_data[ + "date_of_birth" + ] with reversion.create_revision(): current_person.save() @@ -175,10 +178,10 @@ def register_event(request, id_): or "guardian_email" in register_form.changed_data ): guardian = Person.objects.get_or_create( - first_name = register_form.cleaned_data["guardian_first_name"], - last_name = register_form.cleaned_data["guardian_last_name"], - mobile_number = register_form.cleaned_data["guardian_mobile_number"], - email = register_form.cleaned_data["guardian_email"], + first_name=register_form.cleaned_data["guardian_first_name"], + last_name=register_form.cleaned_data["guardian_last_name"], + mobile_number=register_form.cleaned_data["guardian_mobile_number"], + email=register_form.cleaned_data["guardian_email"], ) current_person.guardians.add(guardian[0]) @@ -193,7 +196,9 @@ def register_event(request, id_): with reversion.create_revision(): registration = register_form.save(commit=True) if "voucher_code" in register_form.changed_data: - voucher = Voucher.objects.get(code=register_form.cleaned_data["voucher_code"]) + voucher = Voucher.objects.get( + code=register_form.cleaned_data["voucher_code"] + ) if voucher: registration.voucher = voucher with reversion.create_revision(): @@ -207,9 +212,7 @@ def register_event(request, id_): message.to = [ "orga@teckids.org", ] - message.subject = _("New event:") % ( - event, - ) + message.subject = _("New event:") % (event,) message.extra_headers = { "X-OTRS-CustomerUser": current_person.user.username, } @@ -219,7 +222,14 @@ def register_event(request, id_): # Send message message.send() - messages.success(request, _("You have successfully registered for the event. Please give us up to two days to process your registration. You will then receive an email from us.")) + messages.success( + request, + _( + "You have successfully registered for the event. Please give us" + "up to two days to process your registration. You will then" + "receive an email from us." + ), + ) act = Activity( title=_("You registred for an event"), @@ -325,12 +335,14 @@ def feedback_event(request, id_): if request.method == "POST": if feedback_form.is_valid(): - # Handle photo uploads, if any + # Handle photo uploads, if any photo_urls = [] for file in request.FILES.getlist("photos"): - url = upload_file_to_media_url(file, "ticdesk/teckids_projects/feedback/photos") + url = upload_file_to_media_url( + file, "ticdesk/teckids_projects/feedback/photos" + ) photo_urls.append(url) - + # Produce e-mail to registration queue message = EmailMessage() @@ -452,7 +464,7 @@ def delete_voucher(request, id_): act = Activity( title=_("You deleted a voucher!"), - description=_("You deleted the voucher with ID %s" % current_voucher.id ), + description=_("You deleted the voucher with ID %s" % current_voucher.id), app="TIC-Desk", user=request.user.person, ) @@ -490,7 +502,10 @@ def edit_voucher(request: HttpRequest, id_: Optional[int] = None) -> HttpRespons act = Activity( title=_("You have created a voucher."), - description=_("You have created a voucher for %s for %s" % (voucher.person, voucher.project)), + description=_( + "You have created a voucher for %s for %s" + % (voucher.person, voucher.project) + ), app="TIC-Desk", user=request.user.person, ) @@ -561,7 +576,9 @@ your Teckids-Team act = Activity( title=_("You have added an email address"), - description=_("You have added the email address %s to your profile." % mail), + description=_( + "You have added the email address %s to your profile." % mail + ), app="TIC-Desk", user=request.user.person, ) @@ -778,12 +795,15 @@ def registrations(request: HttpRequest) -> HttpResponse: @permission_required( - "ticdesk.view_registration", fn=objectgetter_optional(EventRegistration, "request.user.person", True) + "ticdesk.view_registration", + fn=objectgetter_optional(EventRegistration, "request.user.person", True), ) def registration(request: HttpRequest, id_) -> HttpResponse: context = {} - registration = objectgetter_optional(EventRegistration, "request.user.person", True)(request, id_) + registration = objectgetter_optional( + EventRegistration, "request.user.person", True + )(request, id_) context["registration"] = registration @@ -811,7 +831,8 @@ def members(request: HttpRequest) -> HttpResponse: @permission_required( - "ticdesk.manage_teckids_member", fn=objectgetter_optional(TeckidsMember, None, False) + "ticdesk.manage_teckids_member", + fn=objectgetter_optional(TeckidsMember, None, False), ) def edit_member(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse: """View to edit or create a member.""" @@ -842,7 +863,8 @@ def edit_member(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse @permission_required( - "ticdesk.delete_registrations", fn=objectgetter_optional(EventRegistration, None, False) + "ticdesk.delete_registrations", + fn=objectgetter_optional(EventRegistration, None, False), ) def delete_registration(request: HttpRequest, id_) -> HttpResponse: context = {} @@ -862,14 +884,17 @@ def delete_registration(request: HttpRequest, id_) -> HttpResponse: @permission_required( - "ticdesk.manage_registrations", fn=objectgetter_optional(EventRegistration, None, False) + "ticdesk.manage_registrations", + fn=objectgetter_optional(EventRegistration, None, False), ) def edit_registration(request: HttpRequest, id_) -> HttpResponse: context = {} registration = objectgetter_optional(EventRegistration, None, False)(request, id_) - edit_event_registration_form = EditEventRegistrationForm(request.POST or None, instance=registration) + edit_event_registration_form = EditEventRegistrationForm( + request.POST or None, instance=registration + ) if request.method == "POST": if edit_event_registration_form.is_valid(): @@ -906,7 +931,9 @@ def feedback_aspects(request: HttpRequest) -> HttpResponse: feedback_aspects = FeedbackAspect.objects.all() # Get filter - feedback_aspects_filter = FeedbackAspectsFilter(request.GET, queryset=feedback_aspects) + feedback_aspects_filter = FeedbackAspectsFilter( + request.GET, queryset=feedback_aspects + ) context["feedback_aspects_filter"] = feedback_aspects_filter # Build table @@ -918,9 +945,12 @@ def feedback_aspects(request: HttpRequest) -> HttpResponse: @permission_required( - "ticdesk.edit_feedback_aspect", fn=objectgetter_optional(FeedbackAspect, None, False) + "ticdesk.edit_feedback_aspect", + fn=objectgetter_optional(FeedbackAspect, None, False), ) -def edit_feedback_aspect(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse: +def edit_feedback_aspect( + request: HttpRequest, id_: Optional[int] = None +) -> HttpResponse: """View to edit or create an feedback_aspect.""" context = {} @@ -929,7 +959,9 @@ def edit_feedback_aspect(request: HttpRequest, id_: Optional[int] = None) -> Htt if id_: # Edit form for existing feedback_aspect - edit_feedback_aspect_form = EditFeedbackAspectForm(request.POST or None, instance=feedback_aspect) + edit_feedback_aspect_form = EditFeedbackAspectForm( + request.POST or None, instance=feedback_aspect + ) else: # Empty form to create a new feedback_aspect edit_feedback_aspect_form = EditFeedbackAspectForm(request.POST or None) diff --git a/poetry.lock b/poetry.lock index 12ee907..ee20fe9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -244,10 +244,10 @@ description = "A high-level Python Web framework that encourages rapid developme name = "django" optional = false python-versions = ">=3.6" -version = "3.0.8" +version = "3.1" [package.dependencies] -asgiref = ">=3.2,<4.0" +asgiref = ">=3.2.10,<3.3.0" pytz = "*" sqlparse = ">=0.2.2" @@ -373,11 +373,12 @@ category = "main" description = "Yet another Django audit log app, hopefully the simplest one." name = "django-easy-audit" optional = false -python-versions = "*" -version = "1.3.0a3" +python-versions = ">=3.5" +version = "1.3.0a5" [package.dependencies] beautifulsoup4 = "*" +django = ">=2.2,<3.2" [[package]] category = "main" @@ -486,7 +487,7 @@ description = "A Django utility application that returns client's real IP addres name = "django-ipware" optional = false python-versions = "*" -version = "3.0.0" +version = "3.0.1" [[package]] category = "main" @@ -547,7 +548,7 @@ description = "Material design for django forms and admin" name = "django-material" optional = false python-versions = "*" -version = "1.6.7" +version = "1.7.0" [package.dependencies] six = "*" @@ -831,8 +832,8 @@ category = "main" description = "Faker is a Python package that generates fake data for you." name = "faker" optional = false -python-versions = ">=3.4" -version = "4.1.1" +python-versions = ">=3.5" +version = "4.1.2" [package.dependencies] python-dateutil = ">=2.4" @@ -943,7 +944,7 @@ description = "Python version of Google's common library for parsing, formatting name = "phonenumbers" optional = false python-versions = "*" -version = "8.12.7" +version = "8.12.8" [[package]] category = "main" @@ -1185,7 +1186,7 @@ description = "A simple tool/library for working with SPDX license definitions." name = "spdx-license-list" optional = false python-versions = "*" -version = "0.5.0" +version = "0.5.1" [[package]] category = "main" @@ -1225,7 +1226,7 @@ description = "Fast, Extensible Progress Meter" name = "tqdm" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*" -version = "4.48.0" +version = "4.48.2" [package.extras] dev = ["py-make (>=0.1.0)", "twine", "argopt", "pydoc-markdown"] @@ -1236,7 +1237,7 @@ description = "Twilio API client and TwiML generator" name = "twilio" optional = false python-versions = "*" -version = "6.44.1" +version = "6.44.2" [package.dependencies] PyJWT = ">=1.4.2" @@ -1274,11 +1275,10 @@ description = "A library for verifying YubiKey OTP tokens, both locally and thro name = "yubiotp" optional = false python-versions = "*" -version = "0.2.2.post1" +version = "1.0.0.post1" [package.dependencies] pycryptodome = "*" -six = "*" [metadata] content-hash = "ffa383cf197c6943613647026c3ed301d09a7522dee39765fb4a01bb894c988f" @@ -1346,8 +1346,8 @@ decorator = [ {file = "decorator-4.4.2.tar.gz", hash = "sha256:e3a62f0520172440ca0dcc823749319382e377f37f140a0b99ef45fecb84bfe7"}, ] django = [ - {file = "Django-3.0.8-py3-none-any.whl", hash = "sha256:5457fc953ec560c5521b41fad9e6734a4668b7ba205832191bbdff40ec61073c"}, - {file = "Django-3.0.8.tar.gz", hash = "sha256:31a5fbbea5fc71c99e288ec0b2f00302a0a92c44b13ede80b73a6a4d6d205582"}, + {file = "Django-3.1-py3-none-any.whl", hash = "sha256:1a63f5bb6ff4d7c42f62a519edc2adbb37f9b78068a5a862beff858b68e3dc8b"}, + {file = "Django-3.1.tar.gz", hash = "sha256:2d390268a13c655c97e0e2ede9d117007996db692c1bb93eabebd4fb7ea7012b"}, ] django-any-js = [ {file = "django-any-js-1.0.3.post0.tar.gz", hash = "sha256:1da88b44b861b0f54f6b8ea0eb4c7c4fa1a5772e9a4320532cd4e0871a4e23f7"}, @@ -1388,8 +1388,8 @@ django-dynamic-preferences = [ {file = "django_dynamic_preferences-1.10-py2.py3-none-any.whl", hash = "sha256:d5852c720c1989a67d87669035e11f6c033e7a507de6ec9bd28941cba24a2dc4"}, ] django-easy-audit = [ - {file = "django-easy-audit-1.3.0a3.tar.gz", hash = "sha256:80e9ed3f11d8927ecd5fa7e03e3aeebd87729d6feba60f9b26b554237dbe3508"}, - {file = "django_easy_audit-1.3.0a3-py3-none-any.whl", hash = "sha256:2b3d067d81392bb18d2b6bb09e67ce4367e73f767d3f4e067af010d496dc657c"}, + {file = "django-easy-audit-1.3.0a5.tar.gz", hash = "sha256:bb6c0291c360fe305d5cdbbc02d9bdec82885788a675871f80ec1b2b0fd6d443"}, + {file = "django_easy_audit-1.3.0a5-py3-none-any.whl", hash = "sha256:01f66d19b15b19c377754848157f87dc78fe88cd1ed9bd7314d24438fb95504a"}, ] django-favicon-plus-reloaded = [ {file = "django-favicon-plus-reloaded-1.0.4.tar.gz", hash = "sha256:90c761c636a338e6e9fb1d086649d82095085f92cff816c9cf074607f28c85a5"}, @@ -1427,7 +1427,7 @@ django-impersonate = [ {file = "django-impersonate-1.5.1.tar.gz", hash = "sha256:7c786ffaa7a5dd430f9277b53a64676c470b684eee5aa52c3b483298860d09b4"}, ] django-ipware = [ - {file = "django-ipware-3.0.0.tar.gz", hash = "sha256:161605eb011439550dd3ee496d0e999720b13f01952be25ea9e88982fbe48e83"}, + {file = "django-ipware-3.0.1.tar.gz", hash = "sha256:73a640a5bff00aa7503a35e92e462001cfabb07d73d649c262f117423beee953"}, ] django-js-asset = [ {file = "django-js-asset-1.2.2.tar.gz", hash = "sha256:c163ae80d2e0b22d8fb598047cd0dcef31f81830e127cfecae278ad574167260"}, @@ -1448,8 +1448,8 @@ django-maintenance-mode = [ {file = "django_maintenance_mode-0.14.0-py2-none-any.whl", hash = "sha256:b4cc24a469ed10897826a28f05d64e6166a58d130e4940ac124ce198cd4cc778"}, ] django-material = [ - {file = "django-material-1.6.7.tar.gz", hash = "sha256:3cc68b34348634f019bf529f3e0b99b1474ab36ec9b50040f5e557b5b65add1d"}, - {file = "django_material-1.6.7-py2.py3-none-any.whl", hash = "sha256:9da268532c92c270b512d9610c9723a07dbfea06db98434dac8aa1dd2910778f"}, + {file = "django-material-1.7.0.tar.gz", hash = "sha256:8d8e76605aa77de3d37d8ae4db1835479e484f1530485fd6b66535244f64131b"}, + {file = "django_material-1.7.0-py2.py3-none-any.whl", hash = "sha256:ff36170e400158a22f9b675e1c07d42267bf1a92122518f68db0c2bf3410096d"}, ] django-menu-generator = [ {file = "django-menu-generator-1.0.4.tar.gz", hash = "sha256:ce71a5055c16933c8aff64fb36c21e5cf8b6d505733aceed1252f8b99369a378"}, @@ -1523,8 +1523,8 @@ easy-thumbnails = [ {file = "easy-thumbnails-2.7.tar.gz", hash = "sha256:e4e7a0dd4001f56bfd4058428f2c91eafe27d33ef3b8b33ac4e013b159b9ff91"}, ] faker = [ - {file = "Faker-4.1.1-py3-none-any.whl", hash = "sha256:1290f589648bc470b8d98fff1fdff773fe3f46b4ca2cac73ac74668b12cf008e"}, - {file = "Faker-4.1.1.tar.gz", hash = "sha256:c006b3664c270a2cfd4785c5e41ff263d48101c4e920b5961cf9c237131d8418"}, + {file = "Faker-4.1.2-py3-none-any.whl", hash = "sha256:bc4b8c908dfcd84e4fe5d9fa2e52fbe17546515fb8f126909b98c47badf05658"}, + {file = "Faker-4.1.2.tar.gz", hash = "sha256:ff188c416864e3f7d8becd8f9ee683a4b4101a2a2d2bcdcb3e84bb1bdd06eaae"}, ] funcsigs = [ {file = "funcsigs-1.0.2-py2.py3-none-any.whl", hash = "sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca"}, @@ -1575,8 +1575,8 @@ pexpect = [ {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, ] phonenumbers = [ - {file = "phonenumbers-8.12.7-py2.py3-none-any.whl", hash = "sha256:772d69e620f85bb089d27c4e2bbf718c49ad327459accf9463ac65dbab67695c"}, - {file = "phonenumbers-8.12.7.tar.gz", hash = "sha256:652c418f8e97c8438f227a524ddf8d7d325c4a47e4924ce865b827c24ec3194d"}, + {file = "phonenumbers-8.12.8-py2.py3-none-any.whl", hash = "sha256:991504a61ea37d14f49f4f30f361e348ff6e6a3306db33ee87ae21b2e55aa0e6"}, + {file = "phonenumbers-8.12.8.tar.gz", hash = "sha256:3a8b8f7b60ea00b83ca588b5ca57e48d9a3c223aa42f1a3d5fa88566424216c3"}, ] pillow = [ {file = "Pillow-7.2.0-cp35-cp35m-macosx_10_10_intel.whl", hash = "sha256:1ca594126d3c4def54babee699c055a913efb01e106c309fa6b04405d474d5ae"}, @@ -1749,8 +1749,8 @@ soupsieve = [ {file = "soupsieve-1.9.6.tar.gz", hash = "sha256:7985bacc98c34923a439967c1a602dc4f1e15f923b6fcf02344184f86cc7efaa"}, ] spdx-license-list = [ - {file = "spdx_license_list-0.5.0-py3-none-any.whl", hash = "sha256:65c9f598dee3249d529300eb08800f8bf3d0d902868669146ada65192ecd0507"}, - {file = "spdx_license_list-0.5.0.tar.gz", hash = "sha256:40cd53ff16401bab7059e6d1ef61839196b12079929a2763a50145d3b6949bc1"}, + {file = "spdx_license_list-0.5.1-py3-none-any.whl", hash = "sha256:32f1401e0077b46ba8b3d9c648b6503ef1d49c41aab51aa13816be2dde3b4a13"}, + {file = "spdx_license_list-0.5.1.tar.gz", hash = "sha256:64cb5de37724c64cdeccafa2ae68667ff8ccdb7b688f51c1c2be82d7ebe3a112"}, ] sqlparse = [ {file = "sqlparse-0.3.1-py2.py3-none-any.whl", hash = "sha256:022fb9c87b524d1f7862b3037e541f68597a730a8843245c349fc93e1643dc4e"}, @@ -1768,11 +1768,11 @@ toml = [ {file = "toml-0.10.1.tar.gz", hash = "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f"}, ] tqdm = [ - {file = "tqdm-4.48.0-py2.py3-none-any.whl", hash = "sha256:fcb7cb5b729b60a27f300b15c1ffd4744f080fb483b88f31dc8654b082cc8ea5"}, - {file = "tqdm-4.48.0.tar.gz", hash = "sha256:6baa75a88582b1db6d34ce4690da5501d2a1cb65c34664840a456b2c9f794d29"}, + {file = "tqdm-4.48.2-py2.py3-none-any.whl", hash = "sha256:1a336d2b829be50e46b84668691e0a2719f26c97c62846298dd5ae2937e4d5cf"}, + {file = "tqdm-4.48.2.tar.gz", hash = "sha256:564d632ea2b9cb52979f7956e093e831c28d441c11751682f84c86fc46e4fd21"}, ] twilio = [ - {file = "twilio-6.44.1.tar.gz", hash = "sha256:a84b6a4e8f6c739cf3fa429033ad522d07c78e3788800e68fe5195d83db4f03a"}, + {file = "twilio-6.44.2.tar.gz", hash = "sha256:db0c1ed249ad672007cbe7109e8a2cbe30c4ed660beba740976baa32f0a8574a"}, ] urllib3 = [ {file = "urllib3-1.25.10-py2.py3-none-any.whl", hash = "sha256:e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461"}, @@ -1783,6 +1783,6 @@ webencodings = [ {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, ] yubiotp = [ - {file = "YubiOTP-0.2.2.post1-py2.py3-none-any.whl", hash = "sha256:7e281801b24678f4bda855ce8ab975a7688a912f5a6cb22b6c2b16263a93cbd2"}, - {file = "YubiOTP-0.2.2.post1.tar.gz", hash = "sha256:de83b1560226e38b5923f6ab919f962c8c2abb7c722104cb45b2b6db2ac86e40"}, + {file = "YubiOTP-1.0.0.post1-py2.py3-none-any.whl", hash = "sha256:7ad57011866e0bc6c6d179ffbc3926fcc0e82d410178a6d01ba4da0f88332878"}, + {file = "YubiOTP-1.0.0.post1.tar.gz", hash = "sha256:c13825f7b76a69afb92f19521f4dea9f5031d70f45123b505dc2e0ac03132065"}, ] diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..6d8918e --- /dev/null +++ b/tox.ini @@ -0,0 +1,82 @@ +[tox] +skipsdist = True +skip_missing_interpreters = true +envlist = py37,py38 + +[testenv] +whitelist_externals = poetry + sudo +skip_install = true +envdir = {toxworkdir}/globalenv +commands_pre = + - poetry install +commands = + - poetry run pytest --cov=. {posargs} aleksis/ + +[testenv:selenium] +setenv = + TEST_SCREENSHOT_PATH = {env:TEST_SCREENSHOT_PATH:.tox/screenshots} + TEST_SELENIUM_HUB = {env:TEST_SELENIUM_HUB:http://127.0.0.1:4444/wd/hub} + TEST_SELENIUM_BROWSERS = {env:TEST_SELENIUM_BROWSERS:chrome,firefox} + TEST_HOST = {env:TEST_HOST:172.17.0.1} + +[testenv:lint] +commands = + - poetry run black --check --diff aleksis/ + - poetry run isort -c --diff --stdout -rc aleksis/ + poetry run flake8 {posargs} aleksis/ + +[testenv:security] +commands = + poetry show --no-dev + poetry run safety check --full-report + +[testenv:build] +commands_pre = +commands = poetry build + +[testenv:docs] +commands = poetry run make -C docs/ html {posargs} + +[testenv:reformat] +commands = + poetry run isort -rc aleksis/ + poetry run black aleksis/ + +[flake8] +max_line_length = 100 +exclude = migrations,tests +ignore = BLK100,E203,E231,W503,D100,D101,D102,D103,D104,D105,D106,D107,RST215,RST214,F821,F841,S106,T100,T101,DJ05,F634 + +[isort] +line_length = 100 +multi_line_output = 3 +include_trailing_comma = 1 +default_section = THIRDPARTY +known_first_party = aleksis +known_django = django +skip = migrations +sections = FUTURE,STDLIB,DJANGO,THIRDPARTY,FIRSTPARTY,LOCALFOLDER + +[mypy] +plugins = mypy_django_plugin.main +python_version = 3.8 +platform = linux +show_column_numbers = True +follow_imports = skip +ignore_missing_imports = True +cache_dir = /dev/null + +[mypy.plugins.django-stubs] +django_settings_module = aleksis.core.settings + +[pytest] +DJANGO_SETTINGS_MODULE = aleksis.core.settings +junit_family = legacy + +[coverage:run] +omit = + */migrations/* + */tests/* + .tox/* + manage.py -- GitLab