diff --git a/core/templates/core/user_preferences.jinja b/core/templates/core/user_preferences.jinja index 9525de20..97416f47 100644 --- a/core/templates/core/user_preferences.jinja +++ b/core/templates/core/user_preferences.jinja @@ -22,6 +22,24 @@

{% trans trombi=user.trombi_user.trombi %}You already choose to be in that Trombi: {{ trombi }}.{% endtrans %} {% trans %}Go to my Trombi tools{% endtrans %}

{% endif %} +{% if profile.customer %} +

{% trans %}Student cards{% endtrans %}

+

{% trans %}You can add a card by asking at a counter or add it yourself here. If you want to manually add a student card yourself, you'll need a NFC reader. We store the UID of the card which is 14 characters long.{% endtrans %}

+
+ {% csrf_token %} + {{ student_card_form.as_p() }} +

+
+{% if profile.customer.student_cards.exists() %} + +{% else %} +

{% trans %}No student cards registered.{% endtrans %}

+{% endif %} +{% endif %} {% endblock %} diff --git a/core/views/user.py b/core/views/user.py index fb9e6455..019cda0a 100644 --- a/core/views/user.py +++ b/core/views/user.py @@ -64,6 +64,7 @@ from core.views.forms import ( ) from core.models import User, SithFile, Preferences, Gift from subscription.models import Subscription +from counter.views import StudentCardForm from trombi.views import UserTrombiForm @@ -741,6 +742,8 @@ class UserPreferencesView(UserTabsMixin, CanEditMixin, UpdateView): kwargs = super(UserPreferencesView, self).get_context_data(**kwargs) if not hasattr(self.object, "trombi_user"): kwargs["trombi_form"] = UserTrombiForm() + if self.object.customer: + kwargs["student_card_form"] = StudentCardForm() return kwargs diff --git a/counter/models.py b/counter/models.py index 0d373d36..693b277b 100644 --- a/counter/models.py +++ b/counter/models.py @@ -91,22 +91,7 @@ class Customer(models.Model): """ Add a new student card on the customer account """ - # If you are comming from a counter, only your connection to the counter is checked, not your right on the user to avoid wierd conflicts - if counter != None and ( - counter.type != "BAR" - or not ( - "counter_token" in request.session.keys() - and request.session["counter_token"] == counter.token - ) - or len(counter.get_barmen_list()) < 1 - ): - raise PermissionDenied - # If you are not comming from a counter, your permissions are checked - if not ( - request.user.id == self.user.id - or request.user.is_board_member - or request.user.is_root - ): + if not StudentCard.check_creation_permission(request, self, counter): raise PermissionDenied StudentCard(customer=self, uid=uid).save() @@ -769,6 +754,38 @@ class StudentCard(models.Model): UID_SIZE = 14 + @staticmethod + def is_valid(uid): + return len(uid) == StudentCard.UID_SIZE + + @staticmethod + def __comming_from_right_counter(request, counter): + return ( + counter.type == "BAR" + and "counter_token" in request.session.keys() + and request.session["counter_token"] == counter.token + and len(counter.get_barmen_list()) > 0 + ) + + @staticmethod + def __user_has_rights(customer, user): + return user.pk == customer.user.pk or user.is_board_member or user.is_root + + @staticmethod + def check_creation_permission(request, customer, counter=None): + """ + If you are comming from a counter, only your connection to the counter is checked, not your right on the user to avoid wierd conflicts + If you are not comming from a counter, your permissions are checked + """ + if counter: + return StudentCard.__comming_from_right_counter(request, counter) + return StudentCard.__user_has_rights(customer, request.user) + + def can_edit(self, obj): + if isinstance(obj, User): + return StudentCard.__user_has_rights(self.customer, obj) + return False + uid = models.CharField( _("uid"), max_length=14, unique=True, validators=[MinLengthValidator(4)] ) diff --git a/counter/templates/counter/counter_click.jinja b/counter/templates/counter/counter_click.jinja index 521ec4c9..ed40e584 100644 --- a/counter/templates/counter/counter_click.jinja +++ b/counter/templates/counter/counter_click.jinja @@ -40,6 +40,16 @@ {% endif %} +
{% trans %}Registered cards{% endtrans %}
+ {% if customer.student_cards.exists() %} + + {% else %} + {% trans %}No card registered{% endtrans %} + {% endif %}
{% trans %}Selling{% endtrans %}
diff --git a/counter/urls.py b/counter/urls.py index 9b99b604..fe3d90fa 100644 --- a/counter/urls.py +++ b/counter/urls.py @@ -56,6 +56,16 @@ urlpatterns = [ EticketPDFView.as_view(), name="eticket_pdf", ), + url( + r"^customer/(?P[0-9]+)/card/add$", + StudentCardFormView.as_view(), + name="add_student_card", + ), + url( + r"^customer/(?P[0-9]+)/card/delete/(?P[0-9]+)/$", + StudentCardDeleteView.as_view(), + name="delete_student_card", + ), url(r"^admin/(?P[0-9]+)$", CounterEditView.as_view(), name="admin"), url( r"^admin/(?P[0-9]+)/prop$", diff --git a/counter/views.py b/counter/views.py index 439eb87d..10a12eec 100644 --- a/counter/views.py +++ b/counter/views.py @@ -33,6 +33,7 @@ from django.views.generic.edit import ( DeleteView, ProcessFormView, FormMixin, + FormView, ) from django.forms.models import modelform_factory from django.forms import CheckboxSelectMultiple @@ -50,7 +51,7 @@ from datetime import date, timedelta, datetime from ajax_select.fields import AutoCompleteSelectField, AutoCompleteSelectMultipleField from ajax_select import make_ajax_field -from core.views import CanViewMixin, TabedViewMixin +from core.views import CanViewMixin, TabedViewMixin, CanEditMixin from core.views.forms import LoginForm, SelectDate, SelectDateTime from core.models import User from subscription.models import Subscription @@ -100,6 +101,45 @@ class CounterAdminMixin(View): return super(CounterAdminMixin, self).dispatch(request, *args, **kwargs) +class StudentCardForm(forms.ModelForm): + """ + Form for adding student cards + Only used for user profile since CounterClick is to complicated + """ + + class Meta: + model = StudentCard + fields = ["uid"] + + def clean(self): + cleaned_data = super(StudentCardForm, self).clean() + uid = cleaned_data.get("uid") + if not StudentCard.is_valid(uid): + raise forms.ValidationError(_("This uid is invalid"), code="invalid") + return cleaned_data + + +class StudentCardDeleteView(DeleteView): + """ + View used to delete a card from a user + """ + + model = StudentCard + template_name = "core/delete_confirm.jinja" + pk_url_kwarg = "card_id" + + def dispatch(self, request, *args, **kwargs): + self.customer = get_object_or_404(Customer, pk=kwargs["customer_id"]) + if not self.get_object().can_edit(self.customer.user): + raise PermissionDenied + return super(StudentCardDeleteView, self).dispatch(request, *args, **kwargs) + + def get_success_url(self, **kwargs): + return reverse_lazy( + "core:user_prefs", kwargs={"user_id": self.customer.user.pk} + ) + + class GetUserForm(forms.Form): """ The Form class aims at providing a valid user_id field in its cleaned data, in order to pass it to some view, @@ -109,7 +149,9 @@ class GetUserForm(forms.Form): some nickname, first name, or last name (TODO) """ - code = forms.CharField(label="Code", max_length=10, required=False) + code = forms.CharField( + label="Code", max_length=StudentCard.UID_SIZE, required=False + ) id = AutoCompleteSelectField( "users", required=False, label=_("Select user"), help_text=None ) @@ -534,7 +576,7 @@ class CounterClick(CounterTabsMixin, CanViewMixin, DetailView): """ uid = request.POST["student_card_uid"] uid = str(uid) - if len(uid) != StudentCard.UID_SIZE: + if not StudentCard.is_valid(uid): request.session["not_valid_student_card_uid"] = True return False @@ -1788,3 +1830,27 @@ class CounterRefillingListView(CounterAdminTabsMixin, CounterAdminMixin, ListVie kwargs = super(CounterRefillingListView, self).get_context_data(**kwargs) kwargs["counter"] = self.counter return kwargs + + +class StudentCardFormView(FormView): + """ + Add a new student card + """ + + form_class = StudentCardForm + template_name = "core/create.jinja" + + def dispatch(self, request, *args, **kwargs): + self.customer = get_object_or_404(Customer, pk=kwargs["customer_id"]) + return super(StudentCardFormView, self).dispatch(request, *args, **kwargs) + + def form_valid(self, form): + data = form.clean() + res = super(FormView, self).form_valid(form) + self.customer.add_student_card(data["uid"], self.request) + return res + + def get_success_url(self, **kwargs): + return reverse_lazy( + "core:user_prefs", kwargs={"user_id": self.customer.user.pk} + )