mirror of
https://github.com/ae-utbm/sith.git
synced 2026-03-13 15:15:03 +00:00
Merge pull request #1311 from ae-utbm/counter-products
Restrict products that non-admins can add to counter
This commit is contained in:
@@ -24,6 +24,7 @@ from core.views.forms import (
|
|||||||
)
|
)
|
||||||
from core.views.widgets.ajax_select import (
|
from core.views.widgets.ajax_select import (
|
||||||
AutoCompleteSelect,
|
AutoCompleteSelect,
|
||||||
|
AutoCompleteSelectMultiple,
|
||||||
AutoCompleteSelectMultipleGroup,
|
AutoCompleteSelectMultipleGroup,
|
||||||
AutoCompleteSelectMultipleUser,
|
AutoCompleteSelectMultipleUser,
|
||||||
AutoCompleteSelectUser,
|
AutoCompleteSelectUser,
|
||||||
@@ -170,11 +171,21 @@ class CounterEditForm(forms.ModelForm):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = Counter
|
model = Counter
|
||||||
fields = ["sellers", "products"]
|
fields = ["sellers", "products"]
|
||||||
|
widgets = {"sellers": AutoCompleteSelectMultipleUser}
|
||||||
|
|
||||||
widgets = {
|
def __init__(self, *args, user: User, instance: Counter, **kwargs):
|
||||||
"sellers": AutoCompleteSelectMultipleUser,
|
super().__init__(*args, instance=instance, **kwargs)
|
||||||
"products": AutoCompleteSelectMultipleProduct,
|
if user.has_perm("counter.change_counter"):
|
||||||
}
|
self.fields["products"].widget = AutoCompleteSelectMultipleProduct()
|
||||||
|
else:
|
||||||
|
self.fields["products"].widget = AutoCompleteSelectMultiple()
|
||||||
|
self.fields["products"].queryset = Product.objects.filter(
|
||||||
|
Q(club_id=instance.club_id) | Q(counters=instance), archived=False
|
||||||
|
).distinct()
|
||||||
|
self.fields["products"].help_text = _(
|
||||||
|
"If you want to add a product that is not owned by "
|
||||||
|
"your club to this counter, you should ask an admin."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ScheduledProductActionForm(forms.ModelForm):
|
class ScheduledProductActionForm(forms.ModelForm):
|
||||||
|
|||||||
62
counter/tests/test_counter_admin.py
Normal file
62
counter/tests/test_counter_admin.py
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
from django.contrib.auth.models import Permission
|
||||||
|
from django.test import TestCase
|
||||||
|
from model_bakery import baker
|
||||||
|
|
||||||
|
from club.models import Membership
|
||||||
|
from core.baker_recipes import subscriber_user
|
||||||
|
from core.models import User
|
||||||
|
from counter.baker_recipes import product_recipe
|
||||||
|
from counter.forms import CounterEditForm
|
||||||
|
from counter.models import Counter
|
||||||
|
|
||||||
|
|
||||||
|
class TestEditCounterProducts(TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
cls.counter = baker.make(Counter)
|
||||||
|
cls.products = product_recipe.make(_quantity=5, _bulk_create=True)
|
||||||
|
cls.counter.products.add(*cls.products)
|
||||||
|
|
||||||
|
def test_admin(self):
|
||||||
|
"""Test that an admin can add and remove products"""
|
||||||
|
user = baker.make(
|
||||||
|
User, user_permissions=[Permission.objects.get(codename="change_counter")]
|
||||||
|
)
|
||||||
|
new_product = product_recipe.make()
|
||||||
|
form = CounterEditForm(
|
||||||
|
data={"sellers": [], "products": [*self.products[1:], new_product]},
|
||||||
|
user=user,
|
||||||
|
instance=self.counter,
|
||||||
|
)
|
||||||
|
assert form.is_valid()
|
||||||
|
form.save()
|
||||||
|
assert set(self.counter.products.all()) == {*self.products[1:], new_product}
|
||||||
|
|
||||||
|
def test_club_board_id(self):
|
||||||
|
"""Test that people from counter club board can only add their own products."""
|
||||||
|
club = self.counter.club
|
||||||
|
user = subscriber_user.make()
|
||||||
|
baker.make(Membership, user=user, club=club, end_date=None)
|
||||||
|
new_product = product_recipe.make(club=club)
|
||||||
|
form = CounterEditForm(
|
||||||
|
data={"sellers": [], "products": [*self.products[1:], new_product]},
|
||||||
|
user=user,
|
||||||
|
instance=self.counter,
|
||||||
|
)
|
||||||
|
assert form.is_valid()
|
||||||
|
form.save()
|
||||||
|
assert set(self.counter.products.all()) == {*self.products[1:], new_product}
|
||||||
|
|
||||||
|
new_product = product_recipe.make() # product not owned by the club
|
||||||
|
form = CounterEditForm(
|
||||||
|
data={"sellers": [], "products": [*self.products[1:], new_product]},
|
||||||
|
user=user,
|
||||||
|
instance=self.counter,
|
||||||
|
)
|
||||||
|
assert not form.is_valid()
|
||||||
|
assert form.errors == {
|
||||||
|
"products": [
|
||||||
|
"Sélectionnez un choix valide. "
|
||||||
|
f"{new_product.id} n\u2019en fait pas partie."
|
||||||
|
],
|
||||||
|
}
|
||||||
@@ -58,7 +58,7 @@ class CounterListView(CounterAdminTabsMixin, CanViewMixin, ListView):
|
|||||||
current_tab = "counters"
|
current_tab = "counters"
|
||||||
|
|
||||||
|
|
||||||
class CounterEditView(CounterAdminTabsMixin, CounterAdminMixin, UpdateView):
|
class CounterEditView(CounterAdminTabsMixin, UserPassesTestMixin, UpdateView):
|
||||||
"""Edit a counter's main informations (for the counter's manager)."""
|
"""Edit a counter's main informations (for the counter's manager)."""
|
||||||
|
|
||||||
model = Counter
|
model = Counter
|
||||||
@@ -67,10 +67,14 @@ class CounterEditView(CounterAdminTabsMixin, CounterAdminMixin, UpdateView):
|
|||||||
template_name = "core/edit.jinja"
|
template_name = "core/edit.jinja"
|
||||||
current_tab = "counters"
|
current_tab = "counters"
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def test_func(self):
|
||||||
obj = self.get_object()
|
if self.request.user.has_perm("counter.change_counter"):
|
||||||
self.edit_club.append(obj.club)
|
return True
|
||||||
return super().dispatch(request, *args, **kwargs)
|
obj = self.get_object(queryset=self.get_queryset().select_related("club"))
|
||||||
|
return obj.club.has_rights_in_club(self.request.user)
|
||||||
|
|
||||||
|
def get_form_kwargs(self):
|
||||||
|
return super().get_form_kwargs() | {"user": self.request.user}
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
return reverse_lazy("counter:admin", kwargs={"counter_id": self.object.id})
|
return reverse_lazy("counter:admin", kwargs={"counter_id": self.object.id})
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-02-14 15:21+0100\n"
|
"POT-Creation-Date: 2026-03-07 15:47+0100\n"
|
||||||
"PO-Revision-Date: 2016-07-18\n"
|
"PO-Revision-Date: 2016-07-18\n"
|
||||||
"Last-Translator: Maréchal <thomas.girod@utbm.fr\n"
|
"Last-Translator: Maréchal <thomas.girod@utbm.fr\n"
|
||||||
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
||||||
@@ -2937,6 +2937,14 @@ msgstr "Cet UID est invalide"
|
|||||||
msgid "User not found"
|
msgid "User not found"
|
||||||
msgstr "Utilisateur non trouvé"
|
msgstr "Utilisateur non trouvé"
|
||||||
|
|
||||||
|
#: counter/forms.py
|
||||||
|
msgid ""
|
||||||
|
"If you want to add a product that is not owned by your club to this counter, "
|
||||||
|
"you should ask an admin."
|
||||||
|
msgstr ""
|
||||||
|
"Si vous souhaitez ajouter sur ce comptoir un produit qui n'appartient pas à "
|
||||||
|
"votre club, vous devriez demander à un admin."
|
||||||
|
|
||||||
#: counter/forms.py
|
#: counter/forms.py
|
||||||
msgid "Date and time of action"
|
msgid "Date and time of action"
|
||||||
msgstr "Date et heure de l'action"
|
msgstr "Date et heure de l'action"
|
||||||
|
|||||||
Reference in New Issue
Block a user