diff --git a/club/admin.py b/club/admin.py
index 04265245..0622cb16 100644
--- a/club/admin.py
+++ b/club/admin.py
@@ -19,8 +19,8 @@ from club.models import Club, Membership
@admin.register(Club)
class ClubAdmin(admin.ModelAdmin):
- list_display = ("name", "unix_name", "parent", "is_active")
- search_fields = ("name", "unix_name")
+ list_display = ("name", "slug_name", "parent", "is_active")
+ search_fields = ("name", "slug_name")
autocomplete_fields = (
"parent",
"board_group",
diff --git a/club/migrations/0011_auto_20180426_2013.py b/club/migrations/0011_auto_20180426_2013.py
index c10fe7b7..1dba79c2 100644
--- a/club/migrations/0011_auto_20180426_2013.py
+++ b/club/migrations/0011_auto_20180426_2013.py
@@ -1,10 +1,9 @@
from __future__ import unicode_literals
import django.db.models.deletion
+from django.conf import settings
from django.db import migrations, models
-import club.models
-
class Migration(migrations.Migration):
dependencies = [("club", "0010_auto_20170912_2028")]
@@ -15,7 +14,7 @@ class Migration(migrations.Migration):
name="owner_group",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
- default=club.models.get_default_owner_group,
+ default=lambda: settings.SITH_ROOT_USER_ID,
related_name="owned_club",
to="core.Group",
),
diff --git a/club/migrations/0014_alter_club_options_rename_unix_name_club_slug_name_and_more.py b/club/migrations/0014_alter_club_options_rename_unix_name_club_slug_name_and_more.py
new file mode 100644
index 00000000..c6b4460f
--- /dev/null
+++ b/club/migrations/0014_alter_club_options_rename_unix_name_club_slug_name_and_more.py
@@ -0,0 +1,75 @@
+# Generated by Django 4.2.17 on 2025-02-28 20:34
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+import core.fields
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("core", "0044_alter_userban_options"),
+ ("club", "0013_alter_club_board_group_alter_club_members_group_and_more"),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(name="club", options={"ordering": ["name"]}),
+ migrations.RenameField(
+ model_name="club",
+ old_name="unix_name",
+ new_name="slug_name",
+ ),
+ migrations.AlterField(
+ model_name="club",
+ name="name",
+ field=models.CharField(unique=True, max_length=64, verbose_name="name"),
+ ),
+ migrations.AlterField(
+ model_name="club",
+ name="slug_name",
+ field=models.SlugField(
+ editable=False, max_length=30, unique=True, verbose_name="slug name"
+ ),
+ ),
+ migrations.AlterField(
+ model_name="club",
+ name="id",
+ field=models.AutoField(
+ auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
+ ),
+ ),
+ migrations.AlterField(
+ model_name="club",
+ name="logo",
+ field=core.fields.ResizedImageField(
+ blank=True,
+ force_format="WEBP",
+ height=200,
+ null=True,
+ upload_to="club_logos",
+ verbose_name="logo",
+ width=200,
+ ),
+ ),
+ migrations.AlterField(
+ model_name="club",
+ name="page",
+ field=models.OneToOneField(
+ blank=True,
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="club",
+ to="core.page",
+ ),
+ ),
+ migrations.AlterField(
+ model_name="club",
+ name="short_description",
+ field=models.CharField(
+ blank=True,
+ default="",
+ help_text="A summary of what your club does. This will be displayed on the club list page.",
+ max_length=1000,
+ verbose_name="short description",
+ ),
+ ),
+ ]
diff --git a/club/models.py b/club/models.py
index 4184715a..e7e99cda 100644
--- a/club/models.py
+++ b/club/models.py
@@ -26,7 +26,6 @@ from __future__ import annotations
from typing import Iterable, Self
from django.conf import settings
-from django.core import validators
from django.core.cache import cache
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.core.validators import RegexValidator, validate_email
@@ -35,48 +34,43 @@ from django.db.models import Exists, F, OuterRef, Q
from django.urls import reverse
from django.utils import timezone
from django.utils.functional import cached_property
+from django.utils.text import slugify
from django.utils.timezone import localdate
from django.utils.translation import gettext_lazy as _
+from core.fields import ResizedImageField
from core.models import Group, Notification, Page, SithFile, User
-# Create your models here.
-
-
-# This function prevents generating migration upon settings change
-def get_default_owner_group():
- return settings.SITH_GROUP_ROOT_ID
-
class Club(models.Model):
"""The Club class, made as a tree to allow nice tidy organization."""
- id = models.AutoField(primary_key=True, db_index=True)
- name = models.CharField(_("name"), max_length=64)
+ name = models.CharField(_("name"), unique=True, max_length=64)
parent = models.ForeignKey(
"Club", related_name="children", null=True, blank=True, on_delete=models.CASCADE
)
- unix_name = models.CharField(
- _("unix name"),
- max_length=30,
- unique=True,
- validators=[
- validators.RegexValidator(
- r"^[a-z0-9][a-z0-9._-]*[a-z0-9]$",
- _(
- "Enter a valid unix name. This value may contain only "
- "letters, numbers ./-/_ characters."
- ),
- )
- ],
- error_messages={"unique": _("A club with that unix name already exists.")},
+ slug_name = models.SlugField(
+ _("slug name"), max_length=30, unique=True, editable=False
)
- logo = models.ImageField(
- upload_to="club_logos", verbose_name=_("logo"), null=True, blank=True
+ logo = ResizedImageField(
+ upload_to="club_logos",
+ verbose_name=_("logo"),
+ null=True,
+ blank=True,
+ force_format="WEBP",
+ height=200,
+ width=200,
)
is_active = models.BooleanField(_("is active"), default=True)
short_description = models.CharField(
- _("short description"), max_length=1000, default="", blank=True, null=True
+ _("short description"),
+ max_length=1000,
+ default="",
+ blank=True,
+ help_text=_(
+ "A summary of what your club does. "
+ "This will be displayed on the club list page."
+ ),
)
address = models.CharField(_("address"), max_length=254)
home = models.OneToOneField(
@@ -88,7 +82,7 @@ class Club(models.Model):
on_delete=models.SET_NULL,
)
page = models.OneToOneField(
- Page, related_name="club", blank=True, null=True, on_delete=models.CASCADE
+ Page, related_name="club", blank=True, on_delete=models.CASCADE
)
members_group = models.OneToOneField(
Group, related_name="club", on_delete=models.PROTECT
@@ -98,7 +92,7 @@ class Club(models.Model):
)
class Meta:
- ordering = ["name", "unix_name"]
+ ordering = ["name"]
def __str__(self):
return self.name
@@ -106,10 +100,12 @@ class Club(models.Model):
@transaction.atomic()
def save(self, *args, **kwargs):
creation = self._state.adding
+ if (slug := slugify(self.name)[:30]) != self.slug_name:
+ self.slug_name = slug
if not creation:
db_club = Club.objects.get(id=self.id)
- if self.unix_name != db_club.unix_name:
- self.home.name = self.unix_name
+ if self.name != db_club.name:
+ self.home.name = self.slug_name
self.home.save()
if self.name != db_club.name:
self.board_group.name = f"{self.name} - Bureau"
@@ -123,11 +119,9 @@ class Club(models.Model):
self.members_group = Group.objects.create(
name=f"{self.name} - Membres", is_manually_manageable=False
)
- super().save(*args, **kwargs)
- if creation:
self.make_home()
self.make_page()
- cache.set(f"sith_club_{self.unix_name}", self)
+ super().save(*args, **kwargs)
def get_absolute_url(self):
return reverse("club:club_view", kwargs={"club_id": self.id})
@@ -155,49 +149,37 @@ class Club(models.Model):
def make_home(self) -> None:
if self.home:
return
- home_root = SithFile.objects.filter(parent=None, name="clubs").first()
- root = User.objects.filter(username="root").first()
- if home_root and root:
- home = SithFile(parent=home_root, name=self.unix_name, owner=root)
- home.save()
- self.home = home
- self.save()
+ home_root = SithFile.objects.get(parent=None, name="clubs")
+ root = User.objects.get(id=settings.SITH_ROOT_USER_ID)
+ self.home = SithFile.objects.create(
+ parent=home_root, name=self.slug_name, owner=root
+ )
def make_page(self) -> None:
- root = User.objects.filter(username="root").first()
- if not self.page:
- club_root = Page.objects.filter(name=settings.SITH_CLUB_ROOT_PAGE).first()
- if root and club_root:
- public = Group.objects.filter(id=settings.SITH_GROUP_PUBLIC_ID).first()
- p = Page(name=self.unix_name)
- p.parent = club_root
- p.save(force_lock=True)
- if public:
- p.view_groups.add(public)
- p.save(force_lock=True)
- if self.parent and self.parent.page:
- p.parent = self.parent.page
- self.page = p
- self.save()
- elif self.page and self.page.name != self.unix_name:
- self.page.unset_lock()
- self.page.name = self.unix_name
- self.page.save(force_lock=True)
- elif (
- self.page
- and self.parent
- and self.parent.page
- and self.page.parent != self.parent.page
- ):
- self.page.unset_lock()
+ page_name = self.slug_name
+ if not self.page_id:
+ # Club.page is a OneToOneField, so if we are inside this condition
+ # then self._meta.state.adding is True.
+ club_root = Page.objects.get(name=settings.SITH_CLUB_ROOT_PAGE)
+ public = Group.objects.get(id=settings.SITH_GROUP_PUBLIC_ID)
+ p = Page(name=page_name, parent=club_root)
+ p.save(force_lock=True)
+ p.view_groups.add(public)
+ if self.parent and self.parent.page_id:
+ p.parent_id = self.parent.page_id
+ self.page = p
+ return
+ self.page.unset_lock()
+ if self.page.name != page_name:
+ self.page.name = page_name
+ elif self.parent and self.parent.page and self.page.parent != self.parent.page:
self.page.parent = self.parent.page
- self.page.save(force_lock=True)
+ self.page.save(force_lock=True)
def delete(self, *args, **kwargs) -> tuple[int, dict[str, int]]:
# Invalidate the cache of this club and of its memberships
for membership in self.members.ongoing().select_related("user"):
cache.delete(f"membership_{self.id}_{membership.user.id}")
- cache.delete(f"sith_club_{self.unix_name}")
self.board_group.delete()
self.members_group.delete()
return super().delete(*args, **kwargs)
diff --git a/club/templates/club/club_detail.jinja b/club/templates/club/club_detail.jinja
index 42e93b81..2d2c5719 100644
--- a/club/templates/club/club_detail.jinja
+++ b/club/templates/club/club_detail.jinja
@@ -4,7 +4,7 @@
{% block content %}
{% if club.logo %}
-
+
{% endif %}
{% if page_revision %}
{{ page_revision|markdown }}
diff --git a/club/templates/club/club_tools.jinja b/club/templates/club/club_tools.jinja
index fa9584fa..db0c22f6 100644
--- a/club/templates/club/club_tools.jinja
+++ b/club/templates/club/club_tools.jinja
@@ -16,7 +16,7 @@
{% trans %}Counters:{% endtrans %}
- {% if object.unix_name == settings.SITH_LAUNDERETTE_MANAGER['unix_name'] %}
+ {% if object.id == settings.SITH_LAUNDERETTE_CLUB_ID %}
{% for l in Launderette.objects.all() %}
- {{ l }}
{% endfor %}
@@ -37,7 +37,7 @@
{% endfor %}
{% endif %}
- {% if object.unix_name == settings.SITH_LAUNDERETTE_MANAGER['unix_name'] %}
+ {% if object.id == settings.SITH_LAUNDERETTE_CLUB_ID %}
{% trans %}Manage launderettes{% endtrans %}
{% endif %}
diff --git a/club/tests.py b/club/tests.py
index a9b7e2e6..be3cc655 100644
--- a/club/tests.py
+++ b/club/tests.py
@@ -27,7 +27,6 @@ from club.forms import MailingForm
from club.models import Club, Mailing, Membership
from core.baker_recipes import subscriber_user
from core.models import AnonymousUser, User
-from sith.settings import SITH_BAR_MANAGER, SITH_MAIN_CLUB_ID
class TestClub(TestCase):
@@ -64,12 +63,8 @@ class TestClub(TestCase):
# not subscribed
cls.public = User.objects.get(username="public")
- cls.ae = Club.objects.filter(pk=SITH_MAIN_CLUB_ID)[0]
- cls.club = Club.objects.create(
- name="Fake Club",
- unix_name="fake-club",
- address="5 rue de la République, 90000 Belfort",
- )
+ cls.ae = Club.objects.get(pk=settings.SITH_MAIN_CLUB_ID)
+ cls.club = baker.make(Club)
cls.members_url = reverse("club:club_members", kwargs={"club_id": cls.club.id})
a_month_ago = now() - timedelta(days=30)
yesterday = now() - timedelta(days=1)
@@ -579,13 +574,11 @@ class TestMailingForm(TestCase):
cls.krophil = User.objects.get(username="krophil")
cls.comunity = User.objects.get(username="comunity")
cls.root = User.objects.get(username="root")
- cls.bdf = Club.objects.get(unix_name=SITH_BAR_MANAGER["unix_name"])
- cls.mail_url = reverse("club:mailing", kwargs={"club_id": cls.bdf.id})
-
- def setUp(self):
+ cls.club = Club.objects.get(id=settings.SITH_PDF_CLUB_ID)
+ cls.mail_url = reverse("club:mailing", kwargs={"club_id": cls.club.id})
Membership(
- user=self.rbatsbak,
- club=self.bdf,
+ user=cls.rbatsbak,
+ club=cls.club,
start_date=timezone.now(),
role=settings.SITH_CLUB_ROLES_ID["Board member"],
).save()
@@ -894,13 +887,13 @@ class TestClubSellingView(TestCase):
@classmethod
def setUpTestData(cls):
- cls.ae = Club.objects.get(unix_name="ae")
- cls.skia = User.objects.get(username="skia")
+ cls.club = baker.make(Club)
+ cls.admin = baker.make(User, is_superuser=True)
def test_page_not_internal_error(self):
"""Test that the page does not return and internal error."""
- self.client.force_login(self.skia)
+ self.client.force_login(self.admin)
response = self.client.get(
- reverse("club:club_sellings", kwargs={"club_id": self.ae.id})
+ reverse("club:club_sellings", kwargs={"club_id": self.club.id})
)
assert response.status_code == 200
diff --git a/club/views.py b/club/views.py
index 6d37ea83..e03df328 100644
--- a/club/views.py
+++ b/club/views.py
@@ -39,10 +39,16 @@ from django.urls import reverse, reverse_lazy
from django.utils import timezone
from django.utils.translation import gettext as _t
from django.utils.translation import gettext_lazy as _
-from django.views.generic import DetailView, ListView, TemplateView, View
+from django.views.generic import DetailView, ListView, View
from django.views.generic.edit import CreateView, DeleteView, UpdateView
-from club.forms import ClubEditForm, ClubMemberForm, MailingForm, SellingsForm
+from club.forms import (
+ ClubAdminEditForm,
+ ClubEditForm,
+ ClubMemberForm,
+ MailingForm,
+ SellingsForm,
+)
from club.models import Club, Mailing, MailingSubscription, Membership
from com.views import (
PosterCreateBaseView,
@@ -78,23 +84,23 @@ class ClubTabsMixin(TabedViewMixin):
}
]
if self.request.user.can_view(self.object):
- tab_list.append(
- {
- "url": reverse(
- "club:club_members", kwargs={"club_id": self.object.id}
- ),
- "slug": "members",
- "name": _("Members"),
- }
- )
- tab_list.append(
- {
- "url": reverse(
- "club:club_old_members", kwargs={"club_id": self.object.id}
- ),
- "slug": "elderlies",
- "name": _("Old members"),
- }
+ tab_list.extend(
+ [
+ {
+ "url": reverse(
+ "club:club_members", kwargs={"club_id": self.object.id}
+ ),
+ "slug": "members",
+ "name": _("Members"),
+ },
+ {
+ "url": reverse(
+ "club:club_old_members", kwargs={"club_id": self.object.id}
+ ),
+ "slug": "elderlies",
+ "name": _("Old members"),
+ },
+ ]
)
if self.object.page:
tab_list.append(
@@ -134,30 +140,30 @@ class ClubTabsMixin(TabedViewMixin):
"name": _("Edit club page"),
}
)
- tab_list.append(
- {
- "url": reverse(
- "club:club_sellings", kwargs={"club_id": self.object.id}
- ),
- "slug": "sellings",
- "name": _("Sellings"),
- }
- )
- tab_list.append(
- {
- "url": reverse("club:mailing", kwargs={"club_id": self.object.id}),
- "slug": "mailing",
- "name": _("Mailing list"),
- }
- )
- tab_list.append(
- {
- "url": reverse(
- "club:poster_list", kwargs={"club_id": self.object.id}
- ),
- "slug": "posters",
- "name": _("Posters list"),
- }
+ tab_list.extend(
+ [
+ {
+ "url": reverse(
+ "club:club_sellings", kwargs={"club_id": self.object.id}
+ ),
+ "slug": "sellings",
+ "name": _("Sellings"),
+ },
+ {
+ "url": reverse(
+ "club:mailing", kwargs={"club_id": self.object.id}
+ ),
+ "slug": "mailing",
+ "name": _("Mailing list"),
+ },
+ {
+ "url": reverse(
+ "club:poster_list", kwargs={"club_id": self.object.id}
+ ),
+ "slug": "posters",
+ "name": _("Posters list"),
+ },
+ ]
)
if self.request.user.is_owner(self.object):
tab_list.append(
@@ -189,8 +195,11 @@ class ClubView(ClubTabsMixin, DetailView):
def get_context_data(self, **kwargs):
kwargs = super().get_context_data(**kwargs)
- if self.object.page and self.object.page.revisions.exists():
- kwargs["page_revision"] = self.object.page.revisions.last().content
+ kwargs["page_revision"] = (
+ PageRev.objects.filter(page_id=self.object.page_id)
+ .order_by("-date")
+ .first()
+ )
return kwargs
@@ -466,7 +475,7 @@ class ClubEditPropView(ClubTabsMixin, CanEditPropMixin, UpdateView):
model = Club
pk_url_kwarg = "club_id"
- fields = ["name", "unix_name", "parent", "is_active"]
+ fields = ["name", "parent", "is_active"]
template_name = "core/edit.jinja"
current_tab = "props"
@@ -476,8 +485,8 @@ class ClubCreateView(PermissionRequiredMixin, CreateView):
model = Club
pk_url_kwarg = "club_id"
- fields = ["name", "unix_name", "parent"]
- template_name = "core/edit.jinja"
+ fields = ["name", "parent"]
+ template_name = "core/create.jinja"
permission_required = "club.add_club"
@@ -533,26 +542,19 @@ class ClubMailingView(ClubTabsMixin, CanEditMixin, DetailFormView):
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
- kwargs["club_id"] = self.get_object().id
+ kwargs["club_id"] = self.object.id
kwargs["user_id"] = self.request.user.id
- kwargs["mailings"] = self.mailings
+ kwargs["mailings"] = self.object.mailings.all()
return kwargs
- def dispatch(self, request, *args, **kwargs):
- self.mailings = Mailing.objects.filter(club_id=self.get_object().id).all()
- return super().dispatch(request, *args, **kwargs)
-
def get_context_data(self, **kwargs):
kwargs = super().get_context_data(**kwargs)
- kwargs["club"] = self.get_object()
+ mailings = list(self.object.mailings.all())
+ kwargs["club"] = self.object
kwargs["user"] = self.request.user
- kwargs["mailings"] = self.mailings
- kwargs["mailings_moderated"] = (
- kwargs["mailings"].exclude(is_moderated=False).all()
- )
- kwargs["mailings_not_moderated"] = (
- kwargs["mailings"].exclude(is_moderated=True).all()
- )
+ kwargs["mailings"] = mailings
+ kwargs["mailings_moderated"] = [m for m in mailings if m.is_moderated]
+ kwargs["mailings_not_moderated"] = [m for m in mailings if not m.is_moderated]
kwargs["form_actions"] = {
"NEW_MALING": self.form_class.ACTION_NEW_MAILING,
"NEW_SUBSCRIPTION": self.form_class.ACTION_NEW_SUBSCRIPTION,
@@ -563,7 +565,7 @@ class ClubMailingView(ClubTabsMixin, CanEditMixin, DetailFormView):
def add_new_mailing(self, cleaned_data) -> ValidationError | None:
"""Create a new mailing list from the form."""
mailing = Mailing(
- club=self.get_object(),
+ club=self.object,
email=cleaned_data["mailing_email"],
moderator=self.request.user,
is_moderated=False,
@@ -640,7 +642,7 @@ class ClubMailingView(ClubTabsMixin, CanEditMixin, DetailFormView):
return resp
def get_success_url(self, **kwargs):
- return reverse_lazy("club:mailing", kwargs={"club_id": self.get_object().id})
+ return reverse("club:mailing", kwargs={"club_id": self.object.id})
class MailingDeleteView(CanEditMixin, DeleteView):
diff --git a/core/management/commands/populate.py b/core/management/commands/populate.py
index 21fde2e5..7e13f28e 100644
--- a/core/management/commands/populate.py
+++ b/core/management/commands/populate.py
@@ -120,10 +120,7 @@ class Command(BaseCommand):
club_root = SithFile.objects.create(name="clubs", owner=root)
sas = SithFile.objects.create(name="SAS", owner=root)
main_club = Club.objects.create(
- id=1,
- name=settings.SITH_MAIN_CLUB["name"],
- unix_name=settings.SITH_MAIN_CLUB["unix_name"],
- address=settings.SITH_MAIN_CLUB["address"],
+ id=1, name="AE", address="6 Boulevard Anatole France, 90000 Belfort"
)
main_club.board_group.permissions.add(
*Permission.objects.filter(
@@ -131,16 +128,14 @@ class Command(BaseCommand):
)
)
bar_club = Club.objects.create(
- id=2,
- name=settings.SITH_BAR_MANAGER["name"],
- unix_name=settings.SITH_BAR_MANAGER["unix_name"],
- address=settings.SITH_BAR_MANAGER["address"],
+ id=settings.SITH_PDF_CLUB_ID,
+ name="PdF",
+ address="6 Boulevard Anatole France, 90000 Belfort",
)
Club.objects.create(
- id=84,
- name=settings.SITH_LAUNDERETTE_MANAGER["name"],
- unix_name=settings.SITH_LAUNDERETTE_MANAGER["unix_name"],
- address=settings.SITH_LAUNDERETTE_MANAGER["address"],
+ id=settings.SITH_LAUNDERETTE_CLUB_ID,
+ name="Laverie",
+ address="6 Boulevard Anatole France, 90000 Belfort",
)
self.reset_index("club")
@@ -353,31 +348,17 @@ Welcome to the wiki page!
# Clubs
Club.objects.create(
- name="Bibo'UT",
- unix_name="bibout",
- address="46 de la Boustifaille",
- parent=main_club,
+ name="Bibo'UT", address="46 de la Boustifaille", parent=main_club
)
guyut = Club.objects.create(
- name="Guy'UT",
- unix_name="guyut",
- address="42 de la Boustifaille",
- parent=main_club,
- )
- Club.objects.create(
- name="Woenzel'UT", unix_name="woenzel", address="Woenzel", parent=guyut
+ name="Guy'UT", address="42 de la Boustifaille", parent=main_club
)
+ Club.objects.create(name="Woenzel'UT", address="Woenzel", parent=guyut)
troll = Club.objects.create(
- name="Troll Penché",
- unix_name="troll",
- address="Terre Du Milieu",
- parent=main_club,
+ name="Troll Penché", address="Terre Du Milieu", parent=main_club
)
refound = Club.objects.create(
- name="Carte AE",
- unix_name="carte_ae",
- address="Jamais imprimée",
- parent=main_club,
+ name="Carte AE", address="Jamais imprimée", parent=main_club
)
Membership.objects.create(user=skia, club=main_club, role=3)
diff --git a/core/management/commands/populate_more.py b/core/management/commands/populate_more.py
index 7acec959..447b6b98 100644
--- a/core/management/commands/populate_more.py
+++ b/core/management/commands/populate_more.py
@@ -64,12 +64,12 @@ class Command(BaseCommand):
)
)
self.make_club(
- Club.objects.get(unix_name="ae"),
+ Club.objects.get(id=settings.SITH_MAIN_CLUB_ID),
random.sample(subscribers_now, k=min(30, len(subscribers_now))),
random.sample(old_subscribers, k=min(60, len(old_subscribers))),
)
self.make_club(
- Club.objects.get(unix_name="troll"),
+ Club.objects.get(name="Troll Penché"),
random.sample(subscribers_now, k=min(20, len(subscribers_now))),
random.sample(old_subscribers, k=min(80, len(old_subscribers))),
)
@@ -235,7 +235,7 @@ class Command(BaseCommand):
categories = list(
ProductType.objects.filter(name__in=[c.name for c in categories])
)
- ae = Club.objects.get(unix_name="ae")
+ ae = Club.objects.get(id=settings.SITH_MAIN_CLUB_ID)
other_clubs = random.sample(list(Club.objects.all()), k=3)
groups = list(
Group.objects.filter(name__in=["Subscribers", "Old subscribers", "Public"])
diff --git a/core/models.py b/core/models.py
index 4748f311..1af12405 100644
--- a/core/models.py
+++ b/core/models.py
@@ -421,13 +421,9 @@ class User(AbstractUser):
def is_launderette_manager(self):
from club.models import Club
- return (
- Club.objects.filter(
- unix_name=settings.SITH_LAUNDERETTE_MANAGER["unix_name"]
- )
- .first()
- .get_membership_for(self)
- )
+ return Club.objects.get(
+ id=settings.SITH_LAUNDERETTE_CLUB_ID
+ ).get_membership_for(self)
@cached_property
def is_banned_alcohol(self) -> bool:
diff --git a/core/templates/core/user_detail.jinja b/core/templates/core/user_detail.jinja
index 5fceb126..771ead72 100644
--- a/core/templates/core/user_detail.jinja
+++ b/core/templates/core/user_detail.jinja
@@ -132,111 +132,104 @@
- {% if
- user == profile
- or user.memberships.ongoing().exists()
- or user.is_board_member
- or user.is_in_group(name=settings.SITH_BAR_MANAGER_BOARD_GROUP)
- %}
- {# if the user is member of a club, he can view the subscription state #}
-
- {% if profile.is_subscribed %}
- {% if user == profile or user.is_root or user.is_board_member %}
-
- {{ user_subscription(profile) }}
-
- {% endif %}
- {% if user == profile or user.is_root or user.is_board_member or user.is_launderette_manager %}
-
- {# Shows tokens bought by the user #}
- {{ show_tokens(profile) }}
- {# Shows slots took by the user #}
- {{ show_slots(profile) }}
-
- {% endif %}
- {% else %}
-
- {% trans %}Not subscribed{% endtrans %}
- {% if user.is_board_member %}
-
- {% trans %}New subscription{% endtrans %}
-
+ {% if user == profile or user.memberships.ongoing().exists() %}
+ {# if the user is member of a club, he can view the subscription state #}
+
+ {% if profile.is_subscribed %}
+ {% if user == profile or user.is_root or user.is_board_member %}
+
+ {{ user_subscription(profile) }}
+
{% endif %}
+ {% if user == profile or user.is_root or user.is_board_member or user.is_launderette_manager %}
+
+ {{ show_tokens(profile) }}
+ {{ show_slots(profile) }}
+
+ {% endif %}
+ {% else %}
+
{% endif %}
-
-{% endif %}
-
-{% if profile.was_subscribed and (user == profile or user.has_perm("subscription.view_subscription")) %}
-
-
-
-
-
-
- {% trans %}Subscription start{% endtrans %} |
- {% trans %}Subscription end{% endtrans %} |
- {% trans %}Subscription type{% endtrans %} |
- {% trans %}Payment method{% endtrans %} |
-
-
- {% for sub in profile.subscriptions.all() %}
-
- {{ sub.subscription_start }} |
- {{ sub.subscription_end }} |
- {{ sub.subscription_type }} |
- {{ sub.get_payment_method_display() }} |
-
- {% endfor %}
-
-
-
-
-{% endif %}
-
-
- {% if user.is_root or user.is_board_member %}
-
- {% if profile.gifts.exists() %}
- {% set gifts = profile.gifts.order_by("-date")|list %}
-
+
+ {% if profile.was_subscribed and (user == profile or user.has_perm("subscription.view_subscription")) %}
-
- {% for gift in gifts %}
- - {{ gift }}
-
-
-
-
+
+
+
+ {% trans %}Subscription start{% endtrans %} |
+ {% trans %}Subscription end{% endtrans %} |
+ {% trans %}Subscription type{% endtrans %} |
+ {% trans %}Payment method{% endtrans %} |
+
+
+ {% for sub in profile.subscriptions.all() %}
+
+ {{ sub.subscription_start }} |
+ {{ sub.subscription_end }} |
+ {{ sub.subscription_type }} |
+ {{ sub.get_payment_method_display() }} |
+
{% endfor %}
-
+
- {% else %}
-
{% trans %}No gift given yet{% endtrans %}
+
+
{% endif %}
+
+
+ {% if user.is_root or user.is_board_member %}
+
+ {% if profile.gifts.exists() %}
+ {% set gifts = profile.gifts.order_by("-date")|list %}
+
+
+
+
+
+ {% for gift in gifts %}
+ - {{ gift }}
+
+
+
+
+ {% endfor %}
+
+
+ {% else %}
+
{% trans %}No gift given yet{% endtrans %}
+ {% endif %}
+
+ {% endif %}
- {% endif %}
-
{% endblock %}
diff --git a/core/views/user.py b/core/views/user.py
index 8e7b092c..cc75f36d 100644
--- a/core/views/user.py
+++ b/core/views/user.py
@@ -251,17 +251,7 @@ class UserTabsMixin(TabedViewMixin):
if (
hasattr(user, "customer")
and user.customer
- and (
- user == self.request.user
- or self.request.user.is_in_group(
- pk=settings.SITH_GROUP_ACCOUNTING_ADMIN_ID
- )
- or self.request.user.is_in_group(
- name=settings.SITH_BAR_MANAGER["unix_name"]
- + settings.SITH_BOARD_SUFFIX
- )
- or self.request.user.is_root
- )
+ and (user == self.request.user or user.has_perm("counter.view_customer"))
):
tab_list.append(
{
@@ -370,12 +360,7 @@ class UserStatsView(UserTabsMixin, CanViewMixin, DetailView):
raise Http404
if not (
- profile == request.user
- or request.user.is_in_group(pk=settings.SITH_GROUP_ACCOUNTING_ADMIN_ID)
- or request.user.is_in_group(
- name=settings.SITH_BAR_MANAGER["unix_name"] + settings.SITH_BOARD_SUFFIX
- )
- or request.user.is_root
+ profile == request.user or request.user.has_perm("counter.view_customer")
):
raise PermissionDenied
@@ -599,14 +584,9 @@ class UserAccountBase(UserTabsMixin, DetailView):
current_tab = "account"
queryset = User.objects.select_related("customer")
- def dispatch(self, request, *arg, **kwargs): # Manually validates the rights
- if (
- kwargs.get("user_id") == request.user.id
- or request.user.is_in_group(pk=settings.SITH_GROUP_ACCOUNTING_ADMIN_ID)
- or request.user.is_in_group(
- name=settings.SITH_BAR_MANAGER["unix_name"] + settings.SITH_BOARD_SUFFIX
- )
- or request.user.is_root
+ def dispatch(self, request, *arg, **kwargs):
+ if kwargs.get("user_id") == request.user.id or request.user.has_perm(
+ "counter.view_customer"
):
return super().dispatch(request, *arg, **kwargs)
raise PermissionDenied
diff --git a/counter/models.py b/counter/models.py
index 1467c9f4..efa74fb1 100644
--- a/counter/models.py
+++ b/counter/models.py
@@ -44,7 +44,6 @@ from core.fields import ResizedImageField
from core.models import Group, Notification, User
from core.utils import get_start_of_semester
from counter.apps import PAYMENT_METHOD
-from sith.settings import SITH_MAIN_CLUB
from subscription.models import Subscription
@@ -519,13 +518,6 @@ class Counter(models.Model):
return reverse("eboutic:main")
return reverse("counter:details", kwargs={"counter_id": self.id})
- def __getattribute__(self, name: str):
- if name == "edit_groups":
- return Group.objects.filter(
- name=self.club.unix_name + settings.SITH_BOARD_SUFFIX
- ).all()
- return object.__getattribute__(self, name)
-
def is_owned_by(self, user: User) -> bool:
if user.is_anonymous:
return False
@@ -569,7 +561,7 @@ class Counter(models.Model):
if self.type != "BAR":
return False
# at least one of the barmen is in the AE board
- ae = Club.objects.get(unix_name=SITH_MAIN_CLUB["unix_name"])
+ ae = Club.objects.get(id=settings.SITH_MAIN_CLUB_ID)
return any(ae.get_membership_for(barman) for barman in self.barmen_list)
def get_top_barmen(self) -> QuerySet:
diff --git a/counter/tests/test_counter.py b/counter/tests/test_counter.py
index d50bb6c4..ab2ab946 100644
--- a/counter/tests/test_counter.py
+++ b/counter/tests/test_counter.py
@@ -783,7 +783,7 @@ class TestCounterStats(TestCase):
s = Selling(
label=barbar.name,
product=barbar,
- club=Club.objects.get(name=settings.SITH_MAIN_CLUB["name"]),
+ club=baker.make(Club),
counter=cls.counter,
unit_price=2,
seller=cls.skia,
diff --git a/galaxy/management/commands/generate_galaxy_test_data.py b/galaxy/management/commands/generate_galaxy_test_data.py
index d0dea4a5..ada43a36 100644
--- a/galaxy/management/commands/generate_galaxy_test_data.py
+++ b/galaxy/management/commands/generate_galaxy_test_data.py
@@ -86,7 +86,7 @@ class Command(BaseCommand):
self.logger.info("The Galaxy is being populated by the Sith.")
self.logger.info("Cleaning old Galaxy population")
- Club.objects.filter(unix_name__startswith="galaxy-").delete()
+ Club.objects.filter(name__startswith="galaxy-").delete()
Group.objects.filter(name__startswith="galaxy-").delete()
Page.objects.filter(name__startswith="galaxy-").delete()
User.objects.filter(username__startswith="galaxy-").delete()
diff --git a/launderette/models.py b/launderette/models.py
index 5d6977e2..81357768 100644
--- a/launderette/models.py
+++ b/launderette/models.py
@@ -47,16 +47,12 @@ class Launderette(models.Model):
"""Method to see if that object can be edited by the given user."""
if user.is_anonymous:
return False
- launderette_club = Club.objects.filter(
- unix_name=settings.SITH_LAUNDERETTE_MANAGER["unix_name"]
- ).first()
+ launderette_club = Club.objects.get(id=settings.SITH_LAUNDERETTE_CLUB_ID)
m = launderette_club.get_membership_for(user)
return bool(m and m.role >= 9)
def can_be_edited_by(self, user):
- launderette_club = Club.objects.filter(
- unix_name=settings.SITH_LAUNDERETTE_MANAGER["unix_name"]
- ).first()
+ launderette_club = Club.objects.get(id=settings.SITH_LAUNDERETTE_CLUB_ID)
m = launderette_club.get_membership_for(user)
return bool(m and m.role >= 2)
@@ -105,9 +101,7 @@ class Machine(models.Model):
"""Method to see if that object can be edited by the given user."""
if user.is_anonymous:
return False
- launderette_club = Club.objects.filter(
- unix_name=settings.SITH_LAUNDERETTE_MANAGER["unix_name"]
- ).first()
+ launderette_club = Club.objects.get(id=settings.SITH_LAUNDERETTE_CLUB_ID)
m = launderette_club.get_membership_for(user)
return bool(m and m.role >= 9)
@@ -154,9 +148,7 @@ class Token(models.Model):
"""Method to see if that object can be edited by the given user."""
if user.is_anonymous:
return False
- launderette_club = Club.objects.filter(
- unix_name=settings.SITH_LAUNDERETTE_MANAGER["unix_name"]
- ).first()
+ launderette_club = Club.objects.get(id=settings.SITH_LAUNDERETTE_CLUB_ID)
m = launderette_club.get_membership_for(user)
return bool(m and m.role >= 9)
diff --git a/launderette/views.py b/launderette/views.py
index 92a81dad..1b0f111b 100644
--- a/launderette/views.py
+++ b/launderette/views.py
@@ -196,9 +196,7 @@ class LaunderetteCreateView(PermissionRequiredMixin, CreateView):
permission_required = "launderette.add_launderette"
def form_valid(self, form):
- club = Club.objects.filter(
- unix_name=settings.SITH_LAUNDERETTE_MANAGER["unix_name"]
- ).first()
+ club = Club.objects.get(id=settings.SITH_LAUNDERETTE_CLUB_ID)
c = Counter(name=form.instance.name, club=club, type="OFFICE")
c.save()
form.instance.counter = c
diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po
index 19b164df..79841e95 100644
--- a/locale/fr/LC_MESSAGES/django.po
+++ b/locale/fr/LC_MESSAGES/django.po
@@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2025-02-25 16:38+0100\n"
+"POT-Creation-Date: 2025-03-01 10:56+0100\n"
"PO-Revision-Date: 2016-07-18\n"
"Last-Translator: Maréchal \n"
@@ -656,11 +656,11 @@ msgid "Linked operation:"
msgstr "Opération liée : "
#: accounting/templates/accounting/operation_edit.jinja
-#: com/templates/com/news_edit.jinja com/templates/com/poster_edit.jinja
-#: com/templates/com/screen_edit.jinja com/templates/com/weekmail.jinja
-#: core/templates/core/create.jinja core/templates/core/edit.jinja
-#: core/templates/core/file_edit.jinja core/templates/core/macros_pages.jinja
-#: core/templates/core/page_prop.jinja
+#: club/templates/club/edit_club.jinja com/templates/com/news_edit.jinja
+#: com/templates/com/poster_edit.jinja com/templates/com/screen_edit.jinja
+#: com/templates/com/weekmail.jinja core/templates/core/create.jinja
+#: core/templates/core/edit.jinja core/templates/core/file_edit.jinja
+#: core/templates/core/macros_pages.jinja core/templates/core/page_prop.jinja
#: core/templates/core/user_godfathers.jinja
#: core/templates/core/user_godfathers_tree.jinja
#: core/templates/core/user_preferences.jinja
@@ -882,20 +882,8 @@ msgid "You do not have the permission to do that"
msgstr "Vous n'avez pas la permission de faire cela"
#: club/models.py
-msgid "unix name"
-msgstr "nom unix"
-
-#: club/models.py
-msgid ""
-"Enter a valid unix name. This value may contain only letters, numbers ./-/_ "
-"characters."
-msgstr ""
-"Entrez un nom UNIX valide. Cette valeur peut contenir uniquement des "
-"lettres, des nombres, et les caractères ./-/_"
-
-#: club/models.py
-msgid "A club with that unix name already exists."
-msgstr "Un club avec ce nom UNIX existe déjà."
+msgid "slug name"
+msgstr "nom slug"
#: club/models.py
msgid "logo"
@@ -909,6 +897,14 @@ msgstr "actif"
msgid "short description"
msgstr "description courte"
+#: club/models.py
+msgid ""
+"A summary of what your club does. This will be displayed on the club list "
+"page."
+msgstr ""
+"Un résumé des activités des activités de votre club. Ceci sera affiché sur "
+"la page de la liste des clubs."
+
#: club/models.py core/models.py
msgid "address"
msgstr "Adresse"
@@ -988,7 +984,7 @@ msgstr "inactif"
msgid "New club"
msgstr "Nouveau club"
-#: club/templates/club/club_list.jinja club/templates/club/stats.jinja
+#: club/templates/club/club_list.jinja
msgid "There is no club in this website."
msgstr "Il n'y a pas de club dans ce site web."
@@ -1059,7 +1055,7 @@ msgstr "Suivant"
msgid "Sales"
msgstr "Ventes"
-#: club/templates/club/club_sellings.jinja club/templates/club/stats.jinja
+#: club/templates/club/club_sellings.jinja
#: counter/templates/counter/cash_summary_list.jinja
msgid "Show"
msgstr "Montrer"
@@ -1160,6 +1156,35 @@ msgstr "Comptabilité : "
msgid "Manage launderettes"
msgstr "Gestion des laveries"
+#: club/templates/club/edit_club.jinja core/templates/core/edit.jinja
+#, python-format
+msgid "Edit %(name)s"
+msgstr "Éditer %(name)s"
+
+#: club/templates/club/edit_club.jinja
+msgid "Club properties"
+msgstr "Propriétés du club"
+
+#: club/templates/club/edit_club.jinja
+msgid ""
+"The following form fields are linked to the core properties of a club. Only "
+"admin users can see and edit them."
+msgstr ""
+"Les champs de formulaire suivants sont liées aux propriétés essentielles d'un "
+"club. Seuls les administrateurs peuvent voir et modifier ceux-ci."
+
+#: club/templates/club/edit_club.jinja
+msgid "Club informations"
+msgstr "Informations du club"
+
+#: club/templates/club/edit_club.jinja
+msgid ""
+"The following form fields are linked to the basic description of a club. All "
+"board members of this club can see and edit them."
+msgstr ""
+"Les champs de formulaire suivants sont liées à la description basique d'un club. "
+"Tous les membres du bureau du club peuvent voir et modifier ceux-ci."
+
#: club/templates/club/mailing.jinja
msgid "Mailing lists"
msgstr "Mailing listes"
@@ -1218,10 +1243,6 @@ msgstr "Créer une liste de diffusion"
msgid "No page existing for this club"
msgstr "Aucune page n'existe pour ce club"
-#: club/templates/club/stats.jinja
-msgid "Club stats"
-msgstr "Statistiques du club"
-
#: club/views.py
msgid "Members"
msgstr "Membres"
@@ -2427,11 +2448,6 @@ msgstr "Confirmation"
msgid "Cancel"
msgstr "Annuler"
-#: core/templates/core/edit.jinja
-#, python-format
-msgid "Edit %(name)s"
-msgstr "Éditer %(name)s"
-
#: core/templates/core/file.jinja core/templates/core/file_list.jinja
msgid "File list"
msgstr "Liste de fichiers"
@@ -2837,6 +2853,7 @@ msgid "Users"
msgstr "Utilisateurs"
#: core/templates/core/search.jinja core/views/user.py
+#: counter/templates/counter/product_list.jinja
msgid "Clubs"
msgstr "Clubs"
@@ -3182,7 +3199,7 @@ msgid "Bans"
msgstr "Bans"
#: core/templates/core/user_tools.jinja counter/forms.py
-#: counter/views/mixins.py
+#: counter/templates/counter/product_list.jinja counter/views/mixins.py
msgid "Counters"
msgstr "Comptoirs"
diff --git a/rootplace/tests/test_merge_users.py b/rootplace/tests/test_merge_users.py
index ad66fdd8..f26e16db 100644
--- a/rootplace/tests/test_merge_users.py
+++ b/rootplace/tests/test_merge_users.py
@@ -18,6 +18,7 @@ from django.conf import settings
from django.test import TestCase
from django.urls import reverse
from django.utils.timezone import localtime, now
+from model_bakery import baker
from club.models import Club
from core.models import Group, User
@@ -28,7 +29,7 @@ from subscription.models import Subscription
class TestMergeUser(TestCase):
@classmethod
def setUpTestData(cls):
- cls.ae = Club.objects.get(unix_name="ae")
+ cls.club = baker.make(Club)
cls.eboutic = Counter.objects.get(name="Eboutic")
cls.barbar = Product.objects.get(code="BARB")
cls.barbar.selling_price = 2
@@ -97,7 +98,7 @@ class TestMergeUser(TestCase):
Selling(
label="barbar",
counter=self.eboutic,
- club=self.ae,
+ club=self.club,
product=self.barbar,
customer=self.to_keep.customer,
seller=self.root,
@@ -108,7 +109,7 @@ class TestMergeUser(TestCase):
Selling(
label="barbar",
counter=self.eboutic,
- club=self.ae,
+ club=self.club,
product=self.barbar,
customer=self.to_delete.customer,
seller=self.root,
@@ -180,7 +181,7 @@ class TestMergeUser(TestCase):
Selling(
label="barbar",
counter=self.eboutic,
- club=self.ae,
+ club=self.club,
product=self.barbar,
customer=self.to_delete.customer,
seller=self.root,
@@ -208,7 +209,7 @@ class TestMergeUser(TestCase):
Selling(
label="barbar",
counter=self.eboutic,
- club=self.ae,
+ club=self.club,
product=self.barbar,
customer=self.to_keep.customer,
seller=self.root,
diff --git a/sith/settings.py b/sith/settings.py
index 8191251f..41a70070 100644
--- a/sith/settings.py
+++ b/sith/settings.py
@@ -332,27 +332,9 @@ SITH_TWITTER = "@ae_utbm"
SITH_ENABLE_GALAXY = False
# AE configuration
-# TODO: keep only that first setting, with the ID, and do the same for the other clubs
SITH_MAIN_CLUB_ID = env.int("SITH_MAIN_CLUB_ID", default=1)
-SITH_MAIN_CLUB = {
- "name": "AE",
- "unix_name": "ae",
- "address": "6 Boulevard Anatole France, 90000 Belfort",
-}
-
-# Bar managers
-SITH_BAR_MANAGER = {
- "name": "Pdf",
- "unix_name": "pdfesti",
- "address": "6 Boulevard Anatole France, 90000 Belfort",
-}
-
-# Launderette managers
-SITH_LAUNDERETTE_MANAGER = {
- "name": "Laverie",
- "unix_name": "laverie",
- "address": "6 Boulevard Anatole France, 90000 Belfort",
-}
+SITH_PDF_CLUB_ID = env.int("SITH_PDF_CLUB_ID", default=2)
+SITH_LAUNDERETTE_CLUB_ID = env.int("SITH_LAUNDERETTE_CLUB_ID", default=84)
# Main root for club pages
SITH_CLUB_ROOT_PAGE = "clubs"
@@ -405,10 +387,6 @@ SITH_SAS_IMAGES_PER_PAGE = 60
SITH_BOARD_SUFFIX = "-bureau"
SITH_MEMBER_SUFFIX = "-membres"
-SITH_MAIN_BOARD_GROUP = SITH_MAIN_CLUB["unix_name"] + SITH_BOARD_SUFFIX
-SITH_MAIN_MEMBERS_GROUP = SITH_MAIN_CLUB["unix_name"] + SITH_MEMBER_SUFFIX
-SITH_BAR_MANAGER_BOARD_GROUP = SITH_BAR_MANAGER["unix_name"] + SITH_BOARD_SUFFIX
-
SITH_PROFILE_DEPARTMENTS = [
("TC", _("TC")),
("IMSI", _("IMSI")),