diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..1224312a5b823986789b4fc125f52636e261b300 --- /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 b775e19287f6e0321177dede767fefeedfe20c6a..4ba3a1e22b2df0bbf451591be828c40f282e4408 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 6cd3acc50fbc90fe0b2bf949169e3b2a5682bd9d..9656830ab729094ebd0d6b406fbdfc2571af5b27 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 2ac0abbf3015dd70b0fba0792e026d9ea8508257..d04ca81d7f05077e9b2fe5a0e5660da5b5790066 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 65688c198bb9942df00977093e25b4a4c110c38b..14a51f27393ba5708a70f0223387813c5c4f544e 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 268fd5540eb20b88076b2b46a3a1e06e698bbbb5..e8a18d46e0c829284c654864393c2b8b551fea30 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 1bdffab7b454c62cfb881f7b7e641b3064d76099..22d621c36970716cbfba9c57163d0943b83769a6 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 9a9bedb01f3d51ac7485f20ceeed183668c90ca6..9db8982dd4272e4ae752c4b1137ef05592221fcf 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 5d6d59d29872fc463a2b3d8ba377be16efa57d0a..870b4a6c024b2268f41a5018849859d8c0b72704 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 8094746ead0e3b7416153b3fa65921be2eac7694..fb89126cac28e669855ef113baa2e28313b4d8cb 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 843b3616f786c4d9538e5c1b26f1b58cf623e0b3..7d14d61007d95c08f9d5c4136a69096bd5ab6178 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 6345fe029b1ac7711038f9618d7b7f8a2cba3344..638db843c3df1035067b52a2d178ff4475f8659b 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 cb42c819ab92f8ceda5f469f1d1fd11f28e7c228..0f619fcccf4c5754a3a2be5395d31e8eb2d4ae49 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 b8aff0c96679cf6edb39b606a0876ad872e15da5..2b8e0219e541293d2f9d819a048afed43bea2200 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 db9d9ec2bb2a93cdace3c16eb58ecdf5eee6f647..f4cdbeb9e81cc44cbc7a885f4c8a9f197bec8727 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 19f8163c103ed7f73e233b3bd6111c1e60af6b05..52aa5efacee7f57b57b33926119308e639325b49 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 b625246971e1eeea2965bc88d8e20adf54fb988f..e7e0ebd7f8e6f321de2555ac9e99d249a675a0bf 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 a848c13d8b856d06cf5aa1ed95c8035f632d9036..863b95ef6ae25a9ec35e884fbb059d5733a0926c 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 f937d964531fbd118f25e8e5bc6b71b969907ac2..6c5117189240351e5f11a95344aa7e2aba4ed302 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 a10b80bac760479394298284bbca30c29c24b34f..fed88c5f40fc05afd94f265e82d4b4e0c657601e 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 51fa746eecda442eaecb613448dd5f71b6c820cd..de1f87ed449fa56bf0db710c14d4f67970ab03fe 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 f499cfbd3e11b3e43dd5ae936f5d5090e3c643cc..b56d8c30bdc9fe30c50a311cbd543325ca5c13b0 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 e6c0ac128d29a4e00844e23d6ad2613a5709e74d..9378041b837cfc1fd52088c639bce8c7113132c7 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 7b9d5ce4a7b769037e22101561e004535f38e05a..2e9fc94b991bf205dc8a869faf61650987dd4353 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 511ebe47f03e3977d2a2c8ab587d8d69b08f3ff5..ec5744fda6305464c6dfdcf87136818eec90c7ac 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 50562ec3c8588a15019bd6765fd3663410cdbc25..cfc51db11ae79cd0a1fdb288eff7cbc897369cc3 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 d5e0156a1752c0dee617c6a45d785796d4295f1b..4d5ff12e4b554e3be3e61fe0b4e2605f32539227 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 12ee907e41027fdb4724f06d11b69688af8ea0a1..ee20fe9dfc8f4a4c928cd7d6bf95806e82ab8a6f 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 0000000000000000000000000000000000000000..6d8918eb4505e640979bd64c0238aef48148ce94 --- /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