mirror of
https://github.com/ae-utbm/sith.git
synced 2024-11-22 06:03:20 +00:00
Remove student card creation from CounterClick view and use fragment instead
This commit is contained in:
parent
9991f5dc64
commit
0aa17279f0
@ -6,7 +6,16 @@
|
|||||||
**/
|
**/
|
||||||
export function registerComponent(name: string, options?: ElementDefinitionOptions) {
|
export function registerComponent(name: string, options?: ElementDefinitionOptions) {
|
||||||
return (component: CustomElementConstructor) => {
|
return (component: CustomElementConstructor) => {
|
||||||
window.customElements.define(name, component, options);
|
try {
|
||||||
|
window.customElements.define(name, component, options);
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof DOMException) {
|
||||||
|
// biome-ignore lint/suspicious/noConsole: it's handy to troobleshot
|
||||||
|
console.warn(e.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,9 +45,7 @@ class BillingInfoForm(forms.ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class StudentCardForm(forms.ModelForm):
|
class StudentCardForm(forms.ModelForm):
|
||||||
"""Form for adding student cards
|
"""Form for adding student cards"""
|
||||||
Only used for user profile since CounterClick is to complicated.
|
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = StudentCard
|
model = StudentCard
|
||||||
@ -114,14 +112,6 @@ class GetUserForm(forms.Form):
|
|||||||
return cleaned_data
|
return cleaned_data
|
||||||
|
|
||||||
|
|
||||||
class NFCCardForm(forms.Form):
|
|
||||||
student_card_uid = forms.CharField(
|
|
||||||
max_length=StudentCard.UID_SIZE,
|
|
||||||
required=False,
|
|
||||||
widget=NFCTextInput,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class RefillForm(forms.ModelForm):
|
class RefillForm(forms.ModelForm):
|
||||||
error_css_class = "error"
|
error_css_class = "error"
|
||||||
required_css_class = "required"
|
required_css_class = "required"
|
||||||
|
26
counter/templates/counter/add_student_card_fragment.jinja
Normal file
26
counter/templates/counter/add_student_card_fragment.jinja
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<div id="student_card_form">
|
||||||
|
<h3>{% trans %}Add a student card{% endtrans %}</h3>
|
||||||
|
<form>
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form.as_p() }}
|
||||||
|
<button
|
||||||
|
hx-post="{{ action }}"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
hx-target="#student_card_form"
|
||||||
|
>
|
||||||
|
{% trans %}Go{% endtrans %}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
<h6>{% trans %}Registered cards{% endtrans %}</h6>
|
||||||
|
{% if student_cards %}
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
{% for card in student_cards %}
|
||||||
|
<li>{{ card.uid }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% else %}
|
||||||
|
{% trans %}No card registered{% endtrans %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
@ -29,27 +29,12 @@
|
|||||||
{{ user_mini_profile(customer.user) }}
|
{{ user_mini_profile(customer.user) }}
|
||||||
{{ user_subscription(customer.user) }}
|
{{ user_subscription(customer.user) }}
|
||||||
<p>{% trans %}Amount: {% endtrans %}{{ customer.amount }} €</p>
|
<p>{% trans %}Amount: {% endtrans %}{{ customer.amount }} €</p>
|
||||||
<form method="post" action="{{ url('counter:click', counter_id=counter.id, user_id=customer.user.id) }}">
|
|
||||||
{% csrf_token %}
|
|
||||||
<input type="hidden" name="action" value="add_student_card">
|
|
||||||
{% trans %}Add a student card{% endtrans %}
|
|
||||||
{{ student_card_input.student_card_uid }}
|
|
||||||
{% if request.session['not_valid_student_card_uid'] %}
|
|
||||||
<p><strong>{% trans %}This is not a valid student card UID{% endtrans %}</strong></p>
|
|
||||||
{% endif %}
|
|
||||||
<input type="submit" value="{% trans %}Go{% endtrans %}"/>
|
|
||||||
</form>
|
|
||||||
<h6>{% trans %}Registered cards{% endtrans %}</h6>
|
|
||||||
{% if student_cards %}
|
|
||||||
|
|
||||||
<ul>
|
<div
|
||||||
{% for card in student_cards %}
|
hx-get="{{ url('counter:add_student_card_fragment', counter_id=counter.id, customer_id=customer.pk) }}"
|
||||||
<li>{{ card.uid }}</li>
|
hx-trigger="load"
|
||||||
{% endfor %}
|
hx-swap="outerHTML"
|
||||||
</ul>
|
></div>
|
||||||
{% else %}
|
|
||||||
{% trans %}No card registered{% endtrans %}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="click_form">
|
<div id="click_form">
|
||||||
|
@ -168,6 +168,7 @@ class TestStudentCard(TestCase):
|
|||||||
cls.root = User.objects.get(username="root")
|
cls.root = User.objects.get(username="root")
|
||||||
|
|
||||||
cls.counter = Counter.objects.get(id=2)
|
cls.counter = Counter.objects.get(id=2)
|
||||||
|
cls.ae_counter = Counter.objects.get(name="AE")
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
# Auto login on counter
|
# Auto login on counter
|
||||||
@ -191,94 +192,144 @@ class TestStudentCard(TestCase):
|
|||||||
# Test card with mixed letters and numbers
|
# Test card with mixed letters and numbers
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
reverse(
|
reverse(
|
||||||
"counter:click",
|
"counter:add_student_card_fragment",
|
||||||
kwargs={"counter_id": self.counter.id, "user_id": self.sli.id},
|
kwargs={
|
||||||
|
"counter_id": self.counter.id,
|
||||||
|
"customer_id": self.sli.customer.pk,
|
||||||
|
},
|
||||||
),
|
),
|
||||||
{"student_card_uid": "8B90734A802A8F", "action": "add_student_card"},
|
{"uid": "8B90734A802A8F"},
|
||||||
)
|
)
|
||||||
self.assertContains(response, text="8B90734A802A8F")
|
assert response.status_code == 302
|
||||||
|
self.assertContains(self.client.get(response.url), text="8B90734A802A8F")
|
||||||
|
|
||||||
# Test card with only numbers
|
# Test card with only numbers
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
reverse(
|
reverse(
|
||||||
"counter:click",
|
"counter:add_student_card_fragment",
|
||||||
kwargs={"counter_id": self.counter.id, "user_id": self.sli.id},
|
kwargs={
|
||||||
|
"counter_id": self.counter.id,
|
||||||
|
"customer_id": self.sli.customer.pk,
|
||||||
|
},
|
||||||
),
|
),
|
||||||
{"student_card_uid": "04786547890123", "action": "add_student_card"},
|
{"uid": "04786547890123"},
|
||||||
)
|
)
|
||||||
self.assertContains(response, text="04786547890123")
|
assert response.status_code == 302
|
||||||
|
self.assertContains(self.client.get(response.url), text="04786547890123")
|
||||||
|
|
||||||
# Test card with only letters
|
# Test card with only letters
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
reverse(
|
reverse(
|
||||||
"counter:click",
|
"counter:add_student_card_fragment",
|
||||||
kwargs={"counter_id": self.counter.id, "user_id": self.sli.id},
|
kwargs={
|
||||||
|
"counter_id": self.counter.id,
|
||||||
|
"customer_id": self.sli.customer.pk,
|
||||||
|
},
|
||||||
),
|
),
|
||||||
{"student_card_uid": "ABCAAAFAAFAAAB", "action": "add_student_card"},
|
{"uid": "ABCAAAFAAFAAAB"},
|
||||||
)
|
)
|
||||||
self.assertContains(response, text="ABCAAAFAAFAAAB")
|
assert response.status_code == 302
|
||||||
|
self.assertContains(self.client.get(response.url), text="ABCAAAFAAFAAAB")
|
||||||
|
|
||||||
def test_add_student_card_from_counter_fail(self):
|
def test_add_student_card_from_counter_fail(self):
|
||||||
# UID too short
|
# UID too short
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
reverse(
|
reverse(
|
||||||
"counter:click",
|
"counter:add_student_card_fragment",
|
||||||
kwargs={"counter_id": self.counter.id, "user_id": self.sli.id},
|
kwargs={
|
||||||
|
"counter_id": self.counter.id,
|
||||||
|
"customer_id": self.sli.customer.pk,
|
||||||
|
},
|
||||||
),
|
),
|
||||||
{"student_card_uid": "8B90734A802A8", "action": "add_student_card"},
|
{"uid": "8B90734A802A8"},
|
||||||
)
|
|
||||||
self.assertContains(
|
|
||||||
response, text="Ce n'est pas un UID de carte étudiante valide"
|
|
||||||
)
|
)
|
||||||
|
self.assertContains(response, text="Cet UID est invalide")
|
||||||
|
|
||||||
# UID too long
|
# UID too long
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
reverse(
|
reverse(
|
||||||
"counter:click",
|
"counter:add_student_card_fragment",
|
||||||
kwargs={"counter_id": self.counter.id, "user_id": self.sli.id},
|
kwargs={
|
||||||
|
"counter_id": self.counter.id,
|
||||||
|
"customer_id": self.sli.customer.pk,
|
||||||
|
},
|
||||||
),
|
),
|
||||||
{"student_card_uid": "8B90734A802A8FA", "action": "add_student_card"},
|
{"uid": "8B90734A802A8FA"},
|
||||||
)
|
)
|
||||||
|
self.assertContains(response, text="Cet UID est invalide")
|
||||||
self.assertContains(
|
self.assertContains(
|
||||||
response, text="Ce n'est pas un UID de carte étudiante valide"
|
response,
|
||||||
|
text="Assurez-vous que cette valeur comporte au plus 14 caractères (actuellement 15).",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Test with already existing card
|
# Test with already existing card
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
reverse(
|
reverse(
|
||||||
"counter:click",
|
"counter:add_student_card_fragment",
|
||||||
kwargs={"counter_id": self.counter.id, "user_id": self.sli.id},
|
kwargs={
|
||||||
|
"counter_id": self.counter.id,
|
||||||
|
"customer_id": self.sli.customer.pk,
|
||||||
|
},
|
||||||
),
|
),
|
||||||
{"student_card_uid": "9A89B82018B0A0", "action": "add_student_card"},
|
{"uid": "9A89B82018B0A0"},
|
||||||
)
|
)
|
||||||
|
self.assertContains(response, text="Cet UID est invalide")
|
||||||
self.assertContains(
|
self.assertContains(
|
||||||
response, text="Ce n'est pas un UID de carte étudiante valide"
|
response, text="Un objet Student card avec ce champ Uid existe déjà."
|
||||||
)
|
)
|
||||||
|
|
||||||
# Test with lowercase
|
# Test with lowercase
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
reverse(
|
reverse(
|
||||||
"counter:click",
|
"counter:add_student_card_fragment",
|
||||||
kwargs={"counter_id": self.counter.id, "user_id": self.sli.id},
|
kwargs={
|
||||||
|
"counter_id": self.counter.id,
|
||||||
|
"customer_id": self.sli.customer.pk,
|
||||||
|
},
|
||||||
),
|
),
|
||||||
{"student_card_uid": "8b90734a802a9f", "action": "add_student_card"},
|
{"uid": "8b90734a802a9f"},
|
||||||
)
|
|
||||||
self.assertContains(
|
|
||||||
response, text="Ce n'est pas un UID de carte étudiante valide"
|
|
||||||
)
|
)
|
||||||
|
self.assertContains(response, text="Cet UID est invalide")
|
||||||
|
|
||||||
# Test with white spaces
|
# Test with white spaces
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
reverse(
|
reverse(
|
||||||
"counter:click",
|
"counter:add_student_card_fragment",
|
||||||
kwargs={"counter_id": self.counter.id, "user_id": self.sli.id},
|
kwargs={
|
||||||
|
"counter_id": self.counter.id,
|
||||||
|
"customer_id": self.sli.customer.pk,
|
||||||
|
},
|
||||||
),
|
),
|
||||||
{"student_card_uid": " ", "action": "add_student_card"},
|
{"uid": " "},
|
||||||
)
|
)
|
||||||
self.assertContains(
|
self.assertContains(response, text="Cet UID est invalide")
|
||||||
response, text="Ce n'est pas un UID de carte étudiante valide"
|
self.assertContains(response, text="Ce champ est obligatoire.")
|
||||||
|
|
||||||
|
def test_add_student_card_from_counter_unauthorized(self):
|
||||||
|
# Send to a counter where you aren't logged in
|
||||||
|
self.client.post(
|
||||||
|
reverse("counter:logout", args=[self.counter.id]),
|
||||||
|
{"user_id": self.krophil.id},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def send_valid_request(client, counter_id):
|
||||||
|
return client.post(
|
||||||
|
reverse(
|
||||||
|
"counter:add_student_card_fragment",
|
||||||
|
kwargs={
|
||||||
|
"counter_id": counter_id,
|
||||||
|
"customer_id": self.sli.customer.pk,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
{"uid": "8B90734A802A8F"},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert send_valid_request(self.client, self.counter.id).status_code == 403
|
||||||
|
|
||||||
|
# Send to a non bar counter
|
||||||
|
self.client.force_login(self.skia)
|
||||||
|
assert send_valid_request(self.client, self.ae_counter.id)
|
||||||
|
|
||||||
def test_delete_student_card_with_owner(self):
|
def test_delete_student_card_with_owner(self):
|
||||||
self.client.force_login(self.sli)
|
self.client.force_login(self.sli)
|
||||||
self.client.post(
|
self.client.post(
|
||||||
|
@ -45,6 +45,7 @@ from counter.views import (
|
|||||||
RefillingDeleteView,
|
RefillingDeleteView,
|
||||||
SellingDeleteView,
|
SellingDeleteView,
|
||||||
StudentCardDeleteView,
|
StudentCardDeleteView,
|
||||||
|
StudentCardFormFragmentView,
|
||||||
StudentCardFormView,
|
StudentCardFormView,
|
||||||
counter_login,
|
counter_login,
|
||||||
counter_logout,
|
counter_logout,
|
||||||
@ -73,6 +74,11 @@ urlpatterns = [
|
|||||||
StudentCardFormView.as_view(),
|
StudentCardFormView.as_view(),
|
||||||
name="add_student_card",
|
name="add_student_card",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"customer/<int:customer_id>/card/add/counter/<int:counter_id>/",
|
||||||
|
StudentCardFormFragmentView.as_view(),
|
||||||
|
name="add_student_card_fragment",
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"customer/<int:customer_id>/card/delete/<int:card_id>/",
|
"customer/<int:customer_id>/card/delete/<int:card_id>/",
|
||||||
StudentCardDeleteView.as_view(),
|
StudentCardDeleteView.as_view(),
|
||||||
|
@ -53,14 +53,13 @@ from django.views.generic.edit import (
|
|||||||
|
|
||||||
from accounting.models import CurrencyField
|
from accounting.models import CurrencyField
|
||||||
from core.utils import get_semester_code, get_start_of_semester
|
from core.utils import get_semester_code, get_start_of_semester
|
||||||
from core.views import CanEditMixin, CanViewMixin, TabedViewMixin
|
from core.views import AllowFragment, CanEditMixin, CanViewMixin, TabedViewMixin
|
||||||
from core.views.forms import LoginForm
|
from core.views.forms import LoginForm
|
||||||
from counter.forms import (
|
from counter.forms import (
|
||||||
CashSummaryFormBase,
|
CashSummaryFormBase,
|
||||||
CounterEditForm,
|
CounterEditForm,
|
||||||
EticketForm,
|
EticketForm,
|
||||||
GetUserForm,
|
GetUserForm,
|
||||||
NFCCardForm,
|
|
||||||
ProductEditForm,
|
ProductEditForm,
|
||||||
RefillForm,
|
RefillForm,
|
||||||
StudentCardForm,
|
StudentCardForm,
|
||||||
@ -330,7 +329,6 @@ class CounterClick(CounterTabsMixin, CanViewMixin, DetailView):
|
|||||||
request.session["too_young"] = False
|
request.session["too_young"] = False
|
||||||
request.session["not_allowed"] = False
|
request.session["not_allowed"] = False
|
||||||
request.session["no_age"] = False
|
request.session["no_age"] = False
|
||||||
request.session["not_valid_student_card_uid"] = False
|
|
||||||
if self.object.type != "BAR":
|
if self.object.type != "BAR":
|
||||||
self.operator = request.user
|
self.operator = request.user
|
||||||
elif self.customer_is_barman():
|
elif self.customer_is_barman():
|
||||||
@ -342,8 +340,6 @@ class CounterClick(CounterTabsMixin, CanViewMixin, DetailView):
|
|||||||
action = parse_qs(request.body.decode()).get("action", [""])[0]
|
action = parse_qs(request.body.decode()).get("action", [""])[0]
|
||||||
if action == "add_product":
|
if action == "add_product":
|
||||||
self.add_product(request)
|
self.add_product(request)
|
||||||
elif action == "add_student_card":
|
|
||||||
self.add_student_card(request)
|
|
||||||
elif action == "del_product":
|
elif action == "del_product":
|
||||||
self.del_product(request)
|
self.del_product(request)
|
||||||
elif action == "refill":
|
elif action == "refill":
|
||||||
@ -480,23 +476,6 @@ class CounterClick(CounterTabsMixin, CanViewMixin, DetailView):
|
|||||||
request.session.modified = True
|
request.session.modified = True
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def add_student_card(self, request):
|
|
||||||
"""Add a new student card on the customer account."""
|
|
||||||
uid = str(request.POST["student_card_uid"])
|
|
||||||
if not StudentCard.is_valid(uid):
|
|
||||||
request.session["not_valid_student_card_uid"] = True
|
|
||||||
return False
|
|
||||||
|
|
||||||
if not (
|
|
||||||
self.object.type == "BAR"
|
|
||||||
and "counter_token" in request.session
|
|
||||||
and request.session["counter_token"] == self.object.token
|
|
||||||
and self.object.is_open
|
|
||||||
):
|
|
||||||
raise PermissionDenied
|
|
||||||
StudentCard(customer=self.customer, uid=uid).save()
|
|
||||||
return True
|
|
||||||
|
|
||||||
def del_product(self, request):
|
def del_product(self, request):
|
||||||
"""Delete a product from the basket."""
|
"""Delete a product from the basket."""
|
||||||
pid = parse_qs(request.body.decode())["product_id"][0]
|
pid = parse_qs(request.body.decode())["product_id"][0]
|
||||||
@ -627,11 +606,8 @@ class CounterClick(CounterTabsMixin, CanViewMixin, DetailView):
|
|||||||
product
|
product
|
||||||
)
|
)
|
||||||
kwargs["customer"] = self.customer
|
kwargs["customer"] = self.customer
|
||||||
kwargs["student_cards"] = self.customer.student_cards.all()
|
|
||||||
kwargs["student_card_input"] = NFCCardForm()
|
|
||||||
kwargs["basket_total"] = self.sum_basket(self.request)
|
kwargs["basket_total"] = self.sum_basket(self.request)
|
||||||
kwargs["refill_form"] = self.refill_form or RefillForm()
|
kwargs["refill_form"] = self.refill_form or RefillForm()
|
||||||
kwargs["student_card_max_uid_size"] = StudentCard.UID_SIZE
|
|
||||||
kwargs["barmens_can_refill"] = self.object.can_refill()
|
kwargs["barmens_can_refill"] = self.object.can_refill()
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
@ -1513,7 +1489,7 @@ class CounterRefillingListView(CounterAdminTabsMixin, CounterAdminMixin, ListVie
|
|||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
class StudentCardFormView(FormView):
|
class StudentCardFormView(AllowFragment, FormView):
|
||||||
"""Add a new student card."""
|
"""Add a new student card."""
|
||||||
|
|
||||||
form_class = StudentCardForm
|
form_class = StudentCardForm
|
||||||
@ -1535,3 +1511,52 @@ class StudentCardFormView(FormView):
|
|||||||
return reverse_lazy(
|
return reverse_lazy(
|
||||||
"core:user_prefs", kwargs={"user_id": self.customer.user.pk}
|
"core:user_prefs", kwargs={"user_id": self.customer.user.pk}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class StudentCardFormFragmentView(FormView):
|
||||||
|
"""
|
||||||
|
Add a new student card from a counter
|
||||||
|
This is a fragment only view which integrates with counter_click.jinja
|
||||||
|
"""
|
||||||
|
|
||||||
|
form_class = StudentCardForm
|
||||||
|
template_name = "counter/add_student_card_fragment.jinja"
|
||||||
|
|
||||||
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
self.counter = get_object_or_404(
|
||||||
|
Counter.objects.annotate_is_open(), pk=kwargs["counter_id"]
|
||||||
|
)
|
||||||
|
self.customer = get_object_or_404(
|
||||||
|
Customer.objects.prefetch_related("student_cards"), pk=kwargs["customer_id"]
|
||||||
|
)
|
||||||
|
if not (
|
||||||
|
self.counter.type == "BAR"
|
||||||
|
and "counter_token" in request.session
|
||||||
|
and request.session["counter_token"] == self.counter.token
|
||||||
|
and self.counter.is_open
|
||||||
|
):
|
||||||
|
raise PermissionDenied
|
||||||
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
data = form.clean()
|
||||||
|
res = super(FormView, self).form_valid(form)
|
||||||
|
StudentCard(customer=self.customer, uid=data["uid"]).save()
|
||||||
|
return res
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context["counter"] = self.counter
|
||||||
|
context["customer"] = self.customer
|
||||||
|
context["action"] = self.request.path
|
||||||
|
context["student_cards"] = self.customer.student_cards.all()
|
||||||
|
return context
|
||||||
|
|
||||||
|
def get_success_url(self, **kwargs):
|
||||||
|
return reverse_lazy(
|
||||||
|
"counter:add_student_card_fragment",
|
||||||
|
kwargs={
|
||||||
|
"customer_id": self.customer.pk,
|
||||||
|
"counter_id": self.counter.id,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user