Merge 91d976855b15226f134beffb095126d927c5bd73 into bb3dfb7e8a87e4c4ca61d2ee095bb6c3f7ffc115

This commit is contained in:
thomas girod 2025-03-14 12:26:17 +00:00 committed by GitHub
commit 51de1bef4f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 502 additions and 505 deletions

View File

@ -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",

View File

@ -34,13 +34,20 @@ from counter.models import Counter
class ClubEditForm(forms.ModelForm):
error_css_class = "error"
required_css_class = "required"
class Meta:
model = Club
fields = ["address", "logo", "short_description"]
widgets = {"short_description": forms.Textarea()}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["short_description"].widget = forms.Textarea()
class ClubAdminEditForm(ClubEditForm):
admin_fields = ["name", "parent", "is_active"]
class Meta(ClubEditForm.Meta):
fields = ["name", "parent", "is_active", *ClubEditForm.Meta.fields]
class MailingForm(forms.Form):

View File

@ -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",
),

View File

@ -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",
),
),
]

View File

@ -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)

View File

@ -4,7 +4,7 @@
{% block content %}
<div id="club_detail">
{% if club.logo %}
<div class="club_logo"><img src="{{ club.logo.url }}" alt="{{ club.unix_name }}"></div>
<div class="club_logo"><img src="{{ club.logo.url }}" alt="{{ club.name }}"></div>
{% endif %}
{% if page_revision %}
{{ page_revision|markdown }}

View File

@ -16,7 +16,7 @@
</ul>
<h4>{% trans %}Counters:{% endtrans %}</h4>
<ul>
{% if object.unix_name == settings.SITH_LAUNDERETTE_MANAGER['unix_name'] %}
{% if object.id == settings.SITH_LAUNDERETTE_CLUB_ID %}
{% for l in Launderette.objects.all() %}
<li><a href="{{ url('launderette:main_click', launderette_id=l.id) }}">{{ l }}</a></li>
{% endfor %}
@ -37,7 +37,7 @@
{% endfor %}
</ul>
{% endif %}
{% if object.unix_name == settings.SITH_LAUNDERETTE_MANAGER['unix_name'] %}
{% if object.id == settings.SITH_LAUNDERETTE_CLUB_ID %}
<li><a href="{{ url('launderette:launderette_list') }}">{% trans %}Manage launderettes{% endtrans %}</a></li>
{% endif %}
</div>

View File

@ -0,0 +1,54 @@
{% extends "core/base.jinja" %}
{% block title %}
{% trans name=object %}Edit {{ name }}{% endtrans %}
{% endblock %}
{% block content %}
<h2>{% trans name=object %}Edit {{ name }}{% endtrans %}</h2>
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.non_field_errors() }}
{% if form.admin_fields %}
{# If the user is admin, display the admin fields,
and explicitly separate them from the non-admin ones,
with some help text.
Non-admin users will only see the regular form fields,
so they don't need thoses explanations #}
<h3>{% trans %}Club properties{% endtrans %}</h3>
<p class="helptext">
{% trans trimmed %}
The following form fields are linked to the core properties of a club.
Only admin users can see and edit them.
{% endtrans %}
</p>
<fieldset class="required margin-bottom">
{% for field_name in form.admin_fields %}
{% set field = form.pop(field_name) %}
<div class="form-group">
{{ field.errors }}
{{ field.label_tag() }}
{{ field }}
</div>
{# Remove the the admin fields from the form.
The remaining non-admin fields will be rendered
at once with a simple {{ form.as_p() }} #}
{% set _ = form.fields.pop(field_name) %}
{% endfor %}
</fieldset>
<h3>{% trans %}Club informations{% endtrans %}</h3>
<p class="helptext">
{% trans trimmed %}
The following form fields are linked to the basic description of a club.
All board members of this club can see and edit them.
{% endtrans %}
</p>
{% endif %}
{{ form.as_p() }}
<p><input type="submit" value="{% trans %}Save{% endtrans %}" /></p>
</form>
{% endblock content %}

View File

@ -1,49 +0,0 @@
{% extends "core/base.jinja" %}
{% block title %}
{% trans %}Club stats{% endtrans %}
{% endblock %}
{% block content %}
{% if club_list %}
<h3>{% trans %}Club stats{% endtrans %}</h3>
<form action="" method="GET">
{% csrf_token %}
<p>
<select name="branch">
{% for b in settings.SITH_PROFILE_DEPARTMENTS %}
<option value="{{ b[0] }}">{{ b[0] }}</option>
{% endfor %}
</select>
</p>
<p><input type="submit" value="{% trans %}Show{% endtrans %}" /></p>
</form>
<table>
<thead>
<tr>
<td>Club</td>
<td>Member number</td>
<td>Old member number</td>
</tr>
</thead>
<tbody>
{% for c in club_list.order_by('id') %}
{% set members = c.members.all() %}
{% if request.GET['branch'] %}
{% set members = members.filter(user__department=request.GET['branch']) %}
{% endif %}
<tr>
<td>{{ c.get_display_name() }}</td>
<td>{{ members.filter(end_date=None, role__gt=settings.SITH_MAXIMUM_FREE_ROLE).count() }}</td>
<td>{{ members.exclude(end_date=None, role__gt=settings.SITH_MAXIMUM_FREE_ROLE).count() }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
{% trans %}There is no club in this website.{% endtrans %}
{% endif %}
{% endblock %}

View File

@ -14,20 +14,21 @@
#
from datetime import timedelta
import pytest
from django.conf import settings
from django.core.cache import cache
from django.test import TestCase
from django.test import Client, TestCase
from django.urls import reverse
from django.utils import timezone
from django.utils.timezone import localdate, localtime, now
from django.utils.translation import gettext as _
from model_bakery import baker
from pytest_django.asserts import assertRedirects
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 +65,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 +576,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 +889,32 @@ 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
@pytest.mark.django_db
def test_club_board_member_cannot_edit_club_properties(client: Client):
user = subscriber_user.make()
club = baker.make(Club, name="old name", is_active=True, address="old address")
baker.make(Membership, club=club, user=user, role=7)
client.force_login(user)
res = client.post(
reverse("club:club_edit", kwargs={"club_id": club.id}),
{"name": "new name", "is_active": False, "address": "new address"},
)
# The request should success,
# but admin-only fields shouldn't be taken into account
assertRedirects(res, club.get_absolute_url())
club.refresh_from_db()
assert club.name == "old name"
assert club.is_active
assert club.address == "new address"

View File

@ -26,7 +26,6 @@ from django.urls import path
from club.views import (
ClubCreateView,
ClubEditPropView,
ClubEditView,
ClubListView,
ClubMailingView,
@ -37,7 +36,6 @@ from club.views import (
ClubRevView,
ClubSellingCSVView,
ClubSellingView,
ClubStatView,
ClubToolsView,
ClubView,
MailingAutoGenerationView,
@ -54,7 +52,6 @@ from club.views import (
urlpatterns = [
path("", ClubListView.as_view(), name="club_list"),
path("new/", ClubCreateView.as_view(), name="club_new"),
path("stats/", ClubStatView.as_view(), name="club_stats"),
path("<int:club_id>/", ClubView.as_view(), name="club_view"),
path(
"<int:club_id>/rev/<int:rev_id>/", ClubRevView.as_view(), name="club_view_rev"
@ -72,7 +69,6 @@ urlpatterns = [
path(
"<int:club_id>/sellings/csv/", ClubSellingCSVView.as_view(), name="sellings_csv"
),
path("<int:club_id>/prop/", ClubEditPropView.as_view(), name="club_prop"),
path("<int:club_id>/tools/", ClubToolsView.as_view(), name="tools"),
path("<int:club_id>/mailing/", ClubMailingView.as_view(), name="mailing"),
path(

View File

@ -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,
@ -50,12 +56,7 @@ from com.views import (
PosterEditBaseView,
PosterListBaseView,
)
from core.auth.mixins import (
CanCreateMixin,
CanEditMixin,
CanEditPropMixin,
CanViewMixin,
)
from core.auth.mixins import CanCreateMixin, CanEditMixin, CanViewMixin
from core.models import PageRev
from core.views import DetailFormView, PageEditViewBase
from core.views.mixins import TabedViewMixin
@ -78,23 +79,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(
@ -107,21 +108,23 @@ class ClubTabsMixin(TabedViewMixin):
}
)
if self.request.user.can_edit(self.object):
tab_list.append(
{
"url": reverse("club:tools", kwargs={"club_id": self.object.id}),
"slug": "tools",
"name": _("Tools"),
}
)
tab_list.append(
{
"url": reverse(
"club:club_edit", kwargs={"club_id": self.object.id}
),
"slug": "edit",
"name": _("Edit"),
}
tab_list.extend(
[
{
"url": reverse(
"club:tools", kwargs={"club_id": self.object.id}
),
"slug": "tools",
"name": _("Tools"),
},
{
"url": reverse(
"club:club_edit", kwargs={"club_id": self.object.id}
),
"slug": "edit",
"name": _("Edit"),
},
]
)
if self.object.page and self.request.user.can_edit(self.object.page):
tab_list.append(
@ -134,40 +137,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"),
}
)
if self.request.user.is_owner(self.object):
tab_list.append(
{
"url": reverse(
"club:club_prop", kwargs={"club_id": self.object.id}
),
"slug": "props",
"name": _("Props"),
}
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"),
},
]
)
return tab_list
@ -189,8 +182,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
@ -452,23 +448,23 @@ class ClubSellingCSVView(ClubSellingView):
class ClubEditView(ClubTabsMixin, CanEditMixin, UpdateView):
"""Edit a Club's main informations (for the club's members)."""
"""Edit a Club.
Regular club board members will be able to edit the main infos
(like the logo and the description).
Admins will also be able to edit the club properties
(like the name and the parent club).
"""
model = Club
pk_url_kwarg = "club_id"
form_class = ClubEditForm
template_name = "core/edit.jinja"
template_name = "club/edit_club.jinja"
current_tab = "edit"
class ClubEditPropView(ClubTabsMixin, CanEditPropMixin, UpdateView):
"""Edit the properties of a Club object (for the Sith admins)."""
model = Club
pk_url_kwarg = "club_id"
fields = ["name", "unix_name", "parent", "is_active"]
template_name = "core/edit.jinja"
current_tab = "props"
def get_form_class(self):
if self.object.is_owned_by(self.request.user):
return ClubAdminEditForm
return ClubEditForm
class ClubCreateView(PermissionRequiredMixin, CreateView):
@ -476,8 +472,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"
@ -522,15 +518,6 @@ class MembershipDeleteView(PermissionRequiredMixin, DeleteView):
return reverse_lazy("core:user_clubs", kwargs={"user_id": self.object.user.id})
class ClubStatView(TemplateView):
template_name = "club/stats.jinja"
def get_context_data(self, **kwargs):
kwargs = super().get_context_data(**kwargs)
kwargs["club_list"] = Club.objects.all()
return kwargs
class ClubMailingView(ClubTabsMixin, CanEditMixin, DetailFormView):
"""A list of mailing for a given club."""
@ -542,26 +529,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,
@ -572,7 +552,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,
@ -649,7 +629,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):

View File

@ -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)

View File

@ -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"])

View File

@ -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:

View File

@ -132,111 +132,104 @@
</div>
</div>
</main>
{% 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 #}
<hr>
{% if profile.is_subscribed %}
{% if user == profile or user.is_root or user.is_board_member %}
<div>
{{ user_subscription(profile) }}
</div>
{% endif %}
{% if user == profile or user.is_root or user.is_board_member or user.is_launderette_manager %}
<div>
{# Shows tokens bought by the user #}
{{ show_tokens(profile) }}
{# Shows slots took by the user #}
{{ show_slots(profile) }}
</div>
{% endif %}
{% else %}
<div>
{% trans %}Not subscribed{% endtrans %}
{% if user.is_board_member %}
<a href="{{ url('subscription:subscription') }}?member={{ profile.id }}">
{% trans %}New subscription{% endtrans %}
</a>
{% if user == profile or user.memberships.ongoing().exists() %}
{# if the user is member of a club, he can view the subscription state #}
<hr>
{% if profile.is_subscribed %}
{% if user == profile or user.is_root or user.is_board_member %}
<div>
{{ user_subscription(profile) }}
</div>
{% endif %}
{% if user == profile or user.is_root or user.is_board_member or user.is_launderette_manager %}
<div>
{{ show_tokens(profile) }}
{{ show_slots(profile) }}
</div>
{% endif %}
{% else %}
<div>
{% trans %}Not subscribed{% endtrans %}
{% if user.is_board_member %}
<a href="{{ url('subscription:subscription') }}?member={{ profile.id }}">
{% trans %}New subscription{% endtrans %}
</a>
{% endif %}
{% endif %}
</div>
{% endif %}
</div>
{% endif %}
<br>
{% if profile.was_subscribed and (user == profile or user.has_perm("subscription.view_subscription")) %}
<div class="collapse" :class="{'shadow': collapsed}" x-data="{collapsed: false}" x-cloak>
<div class="collapse-header clickable" @click="collapsed = !collapsed">
<span class="collapse-header-text">
{% trans %}Subscription history{% endtrans %}
</span>
<span class="collapse-header-icon" :class="{'reverse': collapsed}">
<i class="fa fa-caret-down"></i>
</span>
</div>
<div class="collapse-body" x-show="collapsed" x-transition.scale.origin.top>
<table>
<thead>
<tr>
<th>{% trans %}Subscription start{% endtrans %}</th>
<th>{% trans %}Subscription end{% endtrans %}</th>
<th>{% trans %}Subscription type{% endtrans %}</th>
<th>{% trans %}Payment method{% endtrans %}</th>
</tr>
</thead>
{% for sub in profile.subscriptions.all() %}
<tr>
<td>{{ sub.subscription_start }}</td>
<td>{{ sub.subscription_end }}</td>
<td>{{ sub.subscription_type }}</td>
<td>{{ sub.get_payment_method_display() }}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
<hr>
{% endif %}
<div>
{% if user.is_root or user.is_board_member %}
<form class="form-gifts" action="{{ url('core:user_gift_create', user_id=profile.id) }}" method="post">
{% csrf_token %}
{{ gift_form.label }}
{{ gift_form.user }}
<input type="submit" value="{% trans %}Give gift{% endtrans %}">
</form>
{% if profile.gifts.exists() %}
{% set gifts = profile.gifts.order_by("-date")|list %}
<br>
<br>
{% if profile.was_subscribed and (user == profile or user.has_perm("subscription.view_subscription")) %}
<div class="collapse" :class="{'shadow': collapsed}" x-data="{collapsed: false}" x-cloak>
<div class="collapse-header clickable" @click="collapsed = !collapsed">
<span class="collapse-header-text">
{% trans %}Last given gift :{% endtrans %} {{ gifts[0] }}
{% trans %}Subscription history{% endtrans %}
</span>
<span class="collapse-header-icon" :class="{'reverse': collapsed}">
<i class="fa fa-caret-down"></i>
</span>
</div>
<div class="collapse-body" x-show="collapsed" x-transition.scale.origin.top>
<ul>
{% for gift in gifts %}
<li>{{ gift }}
<a href="{{ url('core:user_gift_delete', user_id=profile.id, gift_id=gift.id) }}">
<i class="fa-solid fa-trash-can delete-action"></i>
</a>
</li>
<table>
<thead>
<tr>
<th>{% trans %}Subscription start{% endtrans %}</th>
<th>{% trans %}Subscription end{% endtrans %}</th>
<th>{% trans %}Subscription type{% endtrans %}</th>
<th>{% trans %}Payment method{% endtrans %}</th>
</tr>
</thead>
{% for sub in profile.subscriptions.all() %}
<tr>
<td>{{ sub.subscription_start }}</td>
<td>{{ sub.subscription_end }}</td>
<td>{{ sub.subscription_type }}</td>
<td>{{ sub.get_payment_method_display() }}</td>
</tr>
{% endfor %}
</ul>
</table>
</div>
{% else %}
<em>{% trans %}No gift given yet{% endtrans %}</em>
</div>
<hr>
{% endif %}
<div>
{% if user.is_root or user.is_board_member %}
<form class="form-gifts" action="{{ url('core:user_gift_create', user_id=profile.id) }}" method="post">
{% csrf_token %}
{{ gift_form.label }}
{{ gift_form.user }}
<input type="submit" value="{% trans %}Give gift{% endtrans %}">
</form>
{% if profile.gifts.exists() %}
{% set gifts = profile.gifts.order_by("-date")|list %}
<br>
<div class="collapse" :class="{'shadow': collapsed}" x-data="{collapsed: false}" x-cloak>
<div class="collapse-header clickable" @click="collapsed = !collapsed">
<span class="collapse-header-text">
{% trans %}Last given gift :{% endtrans %} {{ gifts[0] }}
</span>
<span class="collapse-header-icon" :class="{'reverse': collapsed}">
<i class="fa fa-caret-down"></i>
</span>
</div>
<div class="collapse-body" x-show="collapsed" x-transition.scale.origin.top>
<ul>
{% for gift in gifts %}
<li>{{ gift }}
<a href="{{ url('core:user_gift_delete', user_id=profile.id, gift_id=gift.id) }}">
<i class="fa-solid fa-trash-can delete-action"></i>
</a>
</li>
{% endfor %}
</ul>
</div>
{% else %}
<em>{% trans %}No gift given yet{% endtrans %}</em>
{% endif %}
</div>
{% endif %}
</div>
{% endif %}
</div>
{% endblock %}

View File

@ -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

View File

@ -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
@ -569,7 +568,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:

View File

@ -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,

View File

@ -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()
@ -127,15 +127,19 @@ class Command(BaseCommand):
# the galaxy doesn't care about the club groups,
# but it's necessary to add them nonetheless in order
# not to break the integrity constraints
pages = Page.objects.bulk_create(
[Page(name="page", _full_name="page") for _ in range(self.NB_CLUBS)]
)
self.clubs = Club.objects.bulk_create(
[
Club(
unix_name=f"galaxy-club-{i}",
name=f"club-{i}",
name=f"galaxy-club-{i}",
slug_name=f"galaxy-club-{i}",
board_group=Group.objects.create(name=f"board {i}"),
members_group=Group.objects.create(name=f"members {i}"),
page=page,
)
for i in range(self.NB_CLUBS)
for i, page in enumerate(pages)
]
)

View File

@ -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)

View File

@ -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

View File

@ -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 <thomas.girod@utbm.fr\n"
"Language-Team: AE info <ae.info@utbm.fr>\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"

View File

@ -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,

View File

@ -346,27 +346,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"
@ -419,10 +401,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")),