Author SHA1 Message Date
imperosol 0c6594b3cd remove CounterAdminMixin 2026-10-09 21:59:37 +02:00
9 changed files with 130 additions and 124 deletions

No files matched your search

+19 -7
View File
@@ -83,8 +83,17 @@
{% endmacro %} {% endmacro %}
{% block content %} {% block content %}
<div class="alert alert-yellow">
<div class="alert-main">
{%- trans trimmed -%}
You can see product details.
However, you cannot edit it, thus you won't be able
to submit this form.
{%- endtrans -%}
</div>
</div>
{% if object %} {% if object %}
<h2>{% trans name=object %}Edit product {{ name }}{% endtrans %}</h2> <h2>{{ object }}</h2>
<p><i>{% trans %}Creation date{% endtrans %} : {{ object.created_at|date }}</i></p> <p><i>{% trans %}Creation date{% endtrans %} : {{ object.created_at|date }}</i></p>
<p><i>{% trans %}Last update{% endtrans %} : {{ object.updated_at|date }}</i></p> <p><i>{% trans %}Last update{% endtrans %} : {{ object.updated_at|date }}</i></p>
{% else %} {% else %}
@@ -127,19 +136,17 @@
{{ form.price_formset.management_form }} {{ form.price_formset.management_form }}
<div x-ref="formContainer"> <div x-ref="formContainer">
{%- for form in form.price_formset.forms -%} {%- for form in form.price_formset.forms -%}
<div> <div>{{ price_form(form) }}</div>
{{ price_form(form) }}
</div>
{%- endfor -%} {%- endfor -%}
</div> </div>
<template x-ref="formTemplate"> <template x-ref="formTemplate">
<div> <div>{{ price_form(form.price_formset.empty_form) }}</div>
{{ price_form(form.price_formset.empty_form) }}
</div>
</template> </template>
{% if user.has_perm("counter.change_product") %}
<button class="btn btn-grey" @click.prevent="addForm()"> <button class="btn btn-grey" @click.prevent="addForm()">
<i class="fa fa-plus"></i> {% trans %}Add a price{% endtrans %} <i class="fa fa-plus"></i> {% trans %}Add a price{% endtrans %}
</button> </button>
{% endif %}
</div> </div>
<br /> <br />
@@ -165,11 +172,16 @@
<template x-ref="formTemplate"> <template x-ref="formTemplate">
{{ action_form(form.action_formset.empty_form) }} {{ action_form(form.action_formset.empty_form) }}
</template> </template>
{% if user.has_perm("counter.change_product") %}
<button @click.prevent="addForm()" class="btn btn-grey"> <button @click.prevent="addForm()" class="btn btn-grey">
<i class="fa fa-plus"></i>{% trans %}Add action{% endtrans %} <i class="fa fa-plus"></i>{% trans %}Add action{% endtrans %}
</button> </button>
{% endif %}
</div> </div>
<div class="row gap margin-bottom">{{ form.archived.as_field_group() }}</div> <div class="row gap margin-bottom">{{ form.archived.as_field_group() }}</div>
{% if user.has_perm("counter.change_product") %}
<p><input class="btn btn-blue" type="submit" value="{% trans %}Save{% endtrans %}" /></p> <p><input class="btn btn-blue" type="submit" value="{% trans %}Save{% endtrans %}" /></p>
{% endif %}
</form> </form>
{% endblock %} {% endblock %}
@@ -80,9 +80,11 @@
<h3 class="margin-bottom">{% trans %}Product list{% endtrans %}</h3> <h3 class="margin-bottom">{% trans %}Product list{% endtrans %}</h3>
<div class="row margin-bottom"> <div class="row margin-bottom">
{% if user.has_perm("counter.add_product") %}
<a href="{{ url('counter:new_product') }}" class="btn btn-blue"> <a href="{{ url('counter:new_product') }}" class="btn btn-blue">
{% trans %}New product{% endtrans %} <i class="fa fa-plus"></i> {% trans %}New product{% endtrans %} <i class="fa fa-plus"></i>
</a> </a>
{% endif %}
<button <button
class="btn btn-blue" class="btn btn-blue"
@click="downloadCsv()" @click="downloadCsv()"
@@ -13,12 +13,12 @@
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<p> {% if user.has_perm("counter.add_producttype") %}
<a href="{{ url('counter:new_product_type') }}" class="btn btn-blue"> <a href="{{ url('counter:new_product_type') }}" class="btn btn-blue margin-bottom">
{% trans %}New product type{% endtrans %} {% trans %}New product type{% endtrans %}
<i class="fa fa-plus"></i> <i class="fa fa-plus"></i>
</a> </a>
</p> {% endif %}
{% if product_types %} {% if product_types %}
<aside> <aside>
<p> <p>
+34 -21
View File
@@ -48,7 +48,7 @@ from counter.models import (
Selling, Selling,
) )
from counter.utils import is_logged_in_counter from counter.utils import is_logged_in_counter
from counter.views.mixins import CounterAdminMixin, CounterAdminTabsMixin from counter.views.mixins import CounterAdminTabsMixin
class CounterListView(CounterAdminTabsMixin, CanViewMixin, ListView): class CounterListView(CounterAdminTabsMixin, CanViewMixin, ListView):
@@ -84,17 +84,18 @@ class CounterEditView(
return reverse_lazy("counter:admin", kwargs={"counter_id": self.object.id}) return reverse_lazy("counter:admin", kwargs={"counter_id": self.object.id})
class CounterEditPropView(CounterAdminTabsMixin, CounterAdminMixin, UpdateView): class CounterEditPropView(CounterAdminTabsMixin, PermissionRequiredMixin, UpdateView):
"""Edit a counter's main informations (for the counter's admin).""" """Edit a counter's main infos."""
model = Counter model = Counter
form_class = modelform_factory(Counter, fields=["name", "club", "type"]) form_class = modelform_factory(Counter, fields=["name", "club", "type"])
pk_url_kwarg = "counter_id" pk_url_kwarg = "counter_id"
template_name = "core/edit.jinja" template_name = "core/edit.jinja"
current_tab = "counters" current_tab = "counters"
permission_required = "counter.change_counter"
class CounterCreateView(CounterAdminTabsMixin, CounterAdminMixin, CreateView): class CounterCreateView(CounterAdminTabsMixin, PermissionRequiredMixin, CreateView):
"""Create a counter (for the admins).""" """Create a counter (for the admins)."""
model = Counter model = Counter
@@ -105,9 +106,10 @@ class CounterCreateView(CounterAdminTabsMixin, CounterAdminMixin, CreateView):
) )
template_name = "core/create.jinja" template_name = "core/create.jinja"
current_tab = "counters" current_tab = "counters"
permission_required = "counter.add_counter"
class CounterDeleteView(CounterAdminTabsMixin, CounterAdminMixin, DeleteView): class CounterDeleteView(CounterAdminTabsMixin, PermissionRequiredMixin, DeleteView):
"""Delete a counter (for the admins).""" """Delete a counter (for the admins)."""
model = Counter model = Counter
@@ -115,30 +117,33 @@ class CounterDeleteView(CounterAdminTabsMixin, CounterAdminMixin, DeleteView):
template_name = "core/delete_confirm.jinja" template_name = "core/delete_confirm.jinja"
success_url = reverse_lazy("counter:admin_list") success_url = reverse_lazy("counter:admin_list")
current_tab = "counters" current_tab = "counters"
permission_required = "counter.delete_counter"
# Product management # Product management
class ProductTypeListView(CounterAdminTabsMixin, CounterAdminMixin, ListView): class ProductTypeListView(CounterAdminTabsMixin, PermissionRequiredMixin, ListView):
"""A list view for the admins.""" """A list view for the admins."""
model = ProductType model = ProductType
template_name = "counter/product_type_list.jinja" template_name = "counter/product_type_list.jinja"
current_tab = "product_types" current_tab = "product_types"
context_object_name = "product_types" context_object_name = "product_types"
permission_required = "counter.view_producttype"
class ProductTypeCreateView(CounterAdminTabsMixin, CounterAdminMixin, CreateView): class ProductTypeCreateView(CounterAdminTabsMixin, PermissionRequiredMixin, CreateView):
"""A create view for the admins.""" """A create view for the admins."""
model = ProductType model = ProductType
fields = ["name", "description", "comment", "icon"] fields = ["name", "description", "comment", "icon"]
template_name = "core/create.jinja" template_name = "core/create.jinja"
current_tab = "products" current_tab = "products"
permission_required = "counter.add_producttype"
class ProductTypeEditView(CounterAdminTabsMixin, CounterAdminMixin, UpdateView): class ProductTypeEditView(CounterAdminTabsMixin, PermissionRequiredMixin, UpdateView):
"""An edit view for the admins.""" """An edit view for the admins."""
model = ProductType model = ProductType
@@ -146,23 +151,26 @@ class ProductTypeEditView(CounterAdminTabsMixin, CounterAdminMixin, UpdateView):
fields = ["name", "description", "comment", "icon"] fields = ["name", "description", "comment", "icon"]
pk_url_kwarg = "type_id" pk_url_kwarg = "type_id"
current_tab = "products" current_tab = "products"
permission_required = "counter.change_producttype"
class ProductListView(CounterAdminTabsMixin, CounterAdminMixin, TemplateView): class ProductListView(CounterAdminTabsMixin, PermissionRequiredMixin, TemplateView):
current_tab = "products" current_tab = "products"
template_name = "counter/product_list.jinja" template_name = "counter/product_list.jinja"
permission_required = "counter.view_product"
class ProductCreateView(CounterAdminTabsMixin, CounterAdminMixin, CreateView): class ProductCreateView(CounterAdminTabsMixin, PermissionRequiredMixin, CreateView):
"""A create view for the admins.""" """A create view for the admins."""
model = Product model = Product
form_class = ProductForm form_class = ProductForm
template_name = "counter/product_form.jinja" template_name = "counter/product_form.jinja"
current_tab = "products" current_tab = "products"
permission_required = "counter.add_product"
class ProductEditView(CounterAdminTabsMixin, CounterAdminMixin, UpdateView): class ProductEditView(CounterAdminTabsMixin, PermissionRequiredMixin, UpdateView):
"""An edit view for the admins.""" """An edit view for the admins."""
model = Product model = Product
@@ -170,6 +178,13 @@ class ProductEditView(CounterAdminTabsMixin, CounterAdminMixin, UpdateView):
pk_url_kwarg = "product_id" pk_url_kwarg = "product_id"
template_name = "counter/product_form.jinja" template_name = "counter/product_form.jinja"
current_tab = "products" current_tab = "products"
permission_required = "counter.change_product"
def has_permission(self):
return self.request.user.has_perm("counter.change_product") or (
self.request.method == "GET"
and self.request.user.has_perm("counter.view_product")
)
class ProductFormulaListView(CounterAdminTabsMixin, PermissionRequiredMixin, ListView): class ProductFormulaListView(CounterAdminTabsMixin, PermissionRequiredMixin, ListView):
@@ -299,7 +314,6 @@ class RefillingDeleteView(DeleteView):
template_name = "core/delete_confirm.jinja" template_name = "core/delete_confirm.jinja"
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
"""We have here a very particular right handling, we can't inherit from CanEditPropMixin."""
self.object = self.get_object() self.object = self.get_object()
if timezone.now() - self.object.date <= timedelta( if timezone.now() - self.object.date <= timedelta(
minutes=settings.SITH_LAST_OPERATIONS_LIMIT minutes=settings.SITH_LAST_OPERATIONS_LIMIT
@@ -324,7 +338,6 @@ class SellingDeleteView(DeleteView):
template_name = "core/delete_confirm.jinja" template_name = "core/delete_confirm.jinja"
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
"""We have here a very particular right handling, we can't inherit from CanEditPropMixin."""
self.object = self.get_object() self.object = self.get_object()
if timezone.now() - self.object.date <= timedelta( if timezone.now() - self.object.date <= timedelta(
minutes=settings.SITH_LAST_OPERATIONS_LIMIT minutes=settings.SITH_LAST_OPERATIONS_LIMIT
@@ -376,23 +389,23 @@ class CounterStatView(PermissionRequiredMixin, DetailView):
return kwargs return kwargs
class CounterRefillingListView(CounterAdminTabsMixin, CounterAdminMixin, ListView): class CounterRefillingListView(
CounterAdminTabsMixin, PermissionRequiredMixin, ListView
):
"""List of refillings on a counter.""" """List of refillings on a counter."""
model = Refilling model = Refilling
template_name = "counter/refilling_list.jinja" template_name = "counter/refilling_list.jinja"
current_tab = "counters" current_tab = "counters"
paginate_by = 30 paginate_by = 30
permission_required = "counter.view_refilling"
def dispatch(self, request, *args, **kwargs): def get_queryset(self):
self.counter = get_object_or_404(Counter, pk=kwargs["counter_id"]) self.counter = get_object_or_404(Counter, pk=self.kwargs["counter_id"])
self.queryset = Refilling.objects.filter(counter__id=self.counter.id) return Refilling.objects.filter(counter=self.counter).order_by("-date")
return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super().get_context_data(**kwargs) return super().get_context_data(**kwargs) | {"counter": self.counter}
kwargs["counter"] = self.counter
return kwargs
class RefoundAccountView(UserPassesTestMixin, FormView): class RefoundAccountView(UserPassesTestMixin, FormView):
+8 -5
View File
@@ -12,7 +12,7 @@
# OR WITHIN THE LOCAL FILE "LICENSE" # OR WITHIN THE LOCAL FILE "LICENSE"
# #
# #
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.http import Http404, HttpResponse from django.http import Http404, HttpResponse
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.views.generic import DetailView, ListView from django.views.generic import DetailView, ListView
@@ -21,28 +21,30 @@ from django.views.generic.edit import CreateView, UpdateView
from core.auth.mixins import CanViewMixin from core.auth.mixins import CanViewMixin
from counter.forms import EticketForm from counter.forms import EticketForm
from counter.models import Eticket, Selling from counter.models import Eticket, Selling
from counter.views.mixins import CounterAdminMixin, CounterAdminTabsMixin from counter.views.mixins import CounterAdminTabsMixin
class EticketListView(CounterAdminTabsMixin, CounterAdminMixin, ListView): class EticketListView(CounterAdminTabsMixin, PermissionRequiredMixin, ListView):
"""A list view for the admins.""" """A list view for the admins."""
model = Eticket model = Eticket
template_name = "counter/eticket_list.jinja" template_name = "counter/eticket_list.jinja"
ordering = ["id"] ordering = ["id"]
current_tab = "etickets" current_tab = "etickets"
permission_required = "counter.view_eticket"
class EticketCreateView(CounterAdminTabsMixin, CounterAdminMixin, CreateView): class EticketCreateView(CounterAdminTabsMixin, PermissionRequiredMixin, CreateView):
"""Create an eticket.""" """Create an eticket."""
model = Eticket model = Eticket
template_name = "core/create.jinja" template_name = "core/create.jinja"
form_class = EticketForm form_class = EticketForm
current_tab = "etickets" current_tab = "etickets"
permission_required = "counter.add_eticket"
class EticketEditView(CounterAdminTabsMixin, CounterAdminMixin, UpdateView): class EticketEditView(CounterAdminTabsMixin, PermissionRequiredMixin, UpdateView):
"""Edit an eticket.""" """Edit an eticket."""
model = Eticket model = Eticket
@@ -50,6 +52,7 @@ class EticketEditView(CounterAdminTabsMixin, CounterAdminMixin, UpdateView):
form_class = EticketForm form_class = EticketForm
pk_url_kwarg = "eticket_id" pk_url_kwarg = "eticket_id"
current_tab = "etickets" current_tab = "etickets"
permission_required = "counter.change_eticket"
class EticketPDFView(CanViewMixin, DetailView): class EticketPDFView(CanViewMixin, DetailView):
+35 -35
View File
@@ -13,38 +13,13 @@
# #
# #
from django.conf import settings
from django.core.exceptions import PermissionDenied
from django.urls import reverse, reverse_lazy from django.urls import reverse, reverse_lazy
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.views.generic.base import View
from core.views.mixins import TabedViewMixin from core.views.mixins import TabedViewMixin
from counter.utils import is_logged_in_counter from counter.utils import is_logged_in_counter
class CounterAdminMixin(View):
"""Protect counter admin section."""
edit_group = [settings.SITH_GROUP_COUNTER_ADMIN_ID]
edit_club = []
def _test_group(self, user):
return any(user.is_in_group(pk=grp_id) for grp_id in self.edit_group)
def _test_club(self, user):
return any(c.can_be_edited_by(user) for c in self.edit_club)
def dispatch(self, request, *args, **kwargs):
if not (
request.user.is_root
or self._test_group(request.user)
or self._test_club(request.user)
):
raise PermissionDenied
return super().dispatch(request, *args, **kwargs)
class CounterTabsMixin(TabedViewMixin): class CounterTabsMixin(TabedViewMixin):
def get_tabs_title(self): def get_tabs_title(self):
return self.object return self.object
@@ -89,45 +64,70 @@ class CounterTabsMixin(TabedViewMixin):
class CounterAdminTabsMixin(TabedViewMixin): class CounterAdminTabsMixin(TabedViewMixin):
tabs_title = _("Counter administration") tabs_title = _("Counter administration")
list_of_tabs = [
def get_list_of_tabs(self):
user = self.request.user
res = [
{ {
"url": reverse_lazy("counter:admin_list"), "url": reverse_lazy("counter:admin_list"),
"slug": "counters", "slug": "counters",
"name": _("Counters"), "name": _("Counters"),
}, }
]
if user.has_perm("counter.view_product"):
res.append(
{ {
"url": reverse_lazy("counter:product_list"), "url": reverse_lazy("counter:product_list"),
"slug": "products", "slug": "products",
"name": _("Products"), "name": _("Products"),
}, }
)
if user.has_perm("counter.view_productformula"):
res.append(
{ {
"url": reverse_lazy("counter:product_formula_list"), "url": reverse_lazy("counter:product_formula_list"),
"slug": "formulas", "slug": "formulas",
"name": _("Formulas"), "name": _("Formulas"),
}, }
)
if user.has_perm("counter.view_producttype"):
res.append(
{ {
"url": reverse_lazy("counter:product_type_list"), "url": reverse_lazy("counter:product_type_list"),
"slug": "product_types", "slug": "product_types",
"name": _("Product types"), "name": _("Product types"),
}, }
)
if user.has_perm("counter.view_returnableproduct"):
res.append(
{ {
"url": reverse_lazy("counter:returnable_list"), "url": reverse_lazy("counter:returnable_list"),
"slug": "returnable_products", "slug": "returnable_products",
"name": _("Returnable products"), "name": _("Returnable products"),
}, }
)
if user.has_perm("counter.view_cashregistersummary"):
res.append(
{ {
"url": reverse_lazy("counter:cash_summary_list"), "url": reverse_lazy("counter:cash_summary_list"),
"slug": "cash_summary", "slug": "cash_summary",
"name": _("Cash register summaries"), "name": _("Cash register summaries"),
}, }
)
if user.has_perm("counter.view_invoicecall"):
res.append(
{ {
"url": reverse_lazy("counter:invoices_call"), "url": reverse_lazy("counter:invoices_call"),
"slug": "invoices_call", "slug": "invoices_call",
"name": _("Invoices call"), "name": _("Invoices call"),
}, }
)
if user.has_perm("counter.view_eticket"):
res.append(
{ {
"url": reverse_lazy("counter:eticket_list"), "url": reverse_lazy("counter:eticket_list"),
"slug": "etickets", "slug": "etickets",
"name": _("Etickets"), "name": _("Etickets"),
}, }
] )
return res
+7 -5
View File
@@ -48,7 +48,7 @@ des scripts complets mais qui restent lisibles,
``` ```
Ok, c'est de la triche, on installe un package externe. Ok, c'est de la triche, on installe un package externe.
Mais bon, ça marche, et l'équivalent pur bash Mais bon, ça marche, et l'équivalent pur bash
serait un pur enfer. serait carrément plus moche.
=== "nu" === "nu"
@@ -59,18 +59,20 @@ des scripts complets mais qui restent lisibles,
Nombre de lignes total : Nombre de lignes total :
```nu ```nu
ls **/*.py | par-each { open $in.name | lines | length } | math sum ls **/*.py | insert linecount { get name | open | lines | length } | math sum
``` ```
Vous pouvez aussi exlure les lignes vides Vous pouvez aussi exlure les lignes vides
et les les lignes de commentaire : et les les lignes de commentaire :
```nu ```nu
ls **/*.py | ls **/*.py |
par-each { insert linecount {
open $in.name | get name |
open |
lines | lines |
each { str trim } | each { str trim } |
where { |l| ($l | str length) > 0 and not ($l | str starts-with "#") } | filter { |l| not ($l | str starts-with "#") } | # commentaires
filter { |l| ($l | str length) > 0 } | # lignes vides
length length
} | } |
math sum math sum
+11 -35
View File
@@ -18,8 +18,7 @@ il n'est pas possible de développer le site sur ce système d'exploitation.
Heureusement, il existe une alternative qui ne requiert pas de désinstaller votre Heureusement, il existe une alternative qui ne requiert pas de désinstaller votre
OS ni de mettre un dual boot sur votre ordinateur : `WSL`. OS ni de mettre un dual boot sur votre ordinateur : `WSL`.
- **Prérequis:** vous devez être sur Windows 10 version 2004 ou ultérieure (build 19041 & versions ultérieures) ou - **Prérequis:** vous devez être sur Windows 10 version 2004 ou ultérieure (build 19041 & versions ultérieures) ou Windows 11.
Windows 11.
- **Plus d'info:** [docs.microsoft.com](https://docs.microsoft.com/fr-fr/windows/wsl/install) - **Plus d'info:** [docs.microsoft.com](https://docs.microsoft.com/fr-fr/windows/wsl/install)
```shell ```shell
@@ -44,7 +43,7 @@ il suffit d'utiliser la commande suivante :
cd /mnt/<la_lettre_du_disque>/vos/fichiers/comme/dhab cd /mnt/<la_lettre_du_disque>/vos/fichiers/comme/dhab
``` ```
!!!success !!!note
À ce stade, si vous avez réussi votre installation de `WSL` ou bien qu'il À ce stade, si vous avez réussi votre installation de `WSL` ou bien qu'il
était déjà installé, vous pouvez effectuer la mise en place du projet en suivant était déjà installé, vous pouvez effectuer la mise en place du projet en suivant
@@ -102,10 +101,10 @@ cd /mnt/<la_lettre_du_disque>/vos/fichiers/comme/dhab
ln -s /usr/bin/valkey-server /usr/bin/redis-server ln -s /usr/bin/valkey-server /usr/bin/redis-server
``` ```
=== "macOS" === "macOS"
Pour installer les dépendances, il est fortement recommandé Pour installer les dépendances, il est fortement recommandé d'installer le gestionnaire de paquets `homebrew <https://brew.sh/index_fr>`_.
d'installer le gestionnaire de paquets `homebrew <https://brew.sh/index_fr>`_.
Il est également nécessaire d'avoir installé xcode Il est également nécessaire d'avoir installé xcode
```bash ```bash
@@ -117,15 +116,12 @@ cd /mnt/<la_lettre_du_disque>/vos/fichiers/comme/dhab
!!!note !!!note
Si vous rencontrez des erreurs lors de votre configuration, Si vous rencontrez des erreurs lors de votre configuration, n'hésitez pas à vérifier l'état de votre installation homebrew avec :code:`brew doctor`
n'hésitez pas à vérifier l'état de votre installation homebrew
avec :code:`brew doctor`
!!!note !!!note
Python ne fait pas parti des dépendances puisqu'il est automatiquement Python ne fait pas parti des dépendances puisqu'il est automatiquement
installé par uv. Il est cependant parfois nécessaire d'installer installé par uv. Il est cependant parfois nécessaire d'installer les headers Python nécessaire à la compilation de certains paquets.
les headers Python nécessaire à la compilation de certains paquets.
## Finaliser l'installation ## Finaliser l'installation
@@ -149,6 +145,7 @@ uv run ./manage.py install_xapian
de texte à l'écran. de texte à l'écran.
C'est normal, il ne faut pas avoir peur. C'est normal, il ne faut pas avoir peur.
La modification de la configuration passe par la modification de variables La modification de la configuration passe par la modification de variables
d'environnement. d'environnement.
Ces variables sont stockées dans un fichier `.env`. Ces variables sont stockées dans un fichier `.env`.
@@ -186,32 +183,11 @@ Il suffit ensuite d'utiliser cette commande :
uv run ./manage.py runserver uv run ./manage.py runserver
``` ```
Le serveur est alors accessible à l'adresse !!!note
[http://localhost:8000](http://localhost:8000)
ou bien [http://127.0.0.1:8000/](http://127.0.0.1:8000/).
Pour vous connecter, vous pouvez utiliser un des comptes utilisateur Le serveur est alors accessible à l'adresse
créés durant l'installation : [http://localhost:8000](http://localhost:8000)
ou bien [http://127.0.0.1:8000/](http://127.0.0.1:8000/).
| username | description |
|------------------|----------------------------------------------------------------------------|
| `root` | super-utilisateur<br/>il peut tout faire et tout voir |
| `subscriber` | simple cotisant |
| `old_subscriber` | ancien cotisant |
| `public` | non-cotisant |
| `krophil` | cotisant<br/>barman Foyer<br/>président du Troll Penché |
| `sli` | cotisant<br/>VP Troll |
| `skia` | cotisant<br/>barman MDE<br/>membre du bureau AE<br/>ancien membre du Troll |
| `comunity` | cotisant<br/>membre du bureau PdF<br/>admin communication |
| `counter` | cotisant<br/>admin comptoirs |
| `comptable` | cotisant<br/>admin comptabilité |
| `rbatsbak` | cotisant<br/>membre du Troll |
En plus de ces dernier, quelques centaines d'utilisateurs
supplémentaires sont générés procéduralement,
afin de rajouter un peu de volume de données.
Tous les utilisateurs ont le mot de passe `plop`.
!!!note !!!note
+11 -13
View File
@@ -6,7 +6,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-10-02 12:56+0200\n" "POT-Creation-Date: 2026-10-09 21:44+0200\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"
@@ -236,7 +236,7 @@ msgstr "vous devez spécifier au moins un utilisateur ou une adresse email"
msgid "Begin date" msgid "Begin date"
msgstr "Date de début" msgstr "Date de début"
#: club/forms.py com/forms.py counter/forms.py subscription/forms.py #: club/forms.py com/forms.py counter/forms.py
msgid "End date" msgid "End date"
msgstr "Date de fin" msgstr "Date de fin"
@@ -1093,7 +1093,7 @@ msgstr "Prix d'achat"
msgid "Format: 16:9 | Resolution: 1920x1080" msgid "Format: 16:9 | Resolution: 1920x1080"
msgstr "Format : 16:9 | Résolution : 1920x1080" msgstr "Format : 16:9 | Résolution : 1920x1080"
#: com/forms.py subscription/forms.py #: com/forms.py
msgid "Start date" msgid "Start date"
msgstr "Date de début" msgstr "Date de début"
@@ -4102,7 +4102,6 @@ msgstr "Nouvelle formule"
#: counter/templates/counter/fragments/create_student_card.jinja #: counter/templates/counter/fragments/create_student_card.jinja
#: counter/templates/counter/invoices_call.jinja #: counter/templates/counter/invoices_call.jinja
#: sas/templates/sas/picture.jinja #: sas/templates/sas/picture.jinja
#: subscription/templates/subscription/stats.jinja
msgid "Go" msgid "Go"
msgstr "Valider" msgstr "Valider"
@@ -4237,9 +4236,12 @@ msgid "Remove price"
msgstr "Retirer le prix" msgstr "Retirer le prix"
#: counter/templates/counter/product_form.jinja #: counter/templates/counter/product_form.jinja
#, python-format msgid ""
msgid "Edit product %(name)s" "You can see product details. However, you cannot edit it, thus you won't be "
msgstr "Édition du produit %(name)s" "able to submit this form."
msgstr ""
"Vous pouvez voir ce produit. Cependant, vous ne pouvez pas l'éditer ; vous "
"ne serez donc pas en mesure de soumettre le formulaire."
#: counter/templates/counter/product_form.jinja #: counter/templates/counter/product_form.jinja
msgid "Creation date" msgid "Creation date"
@@ -5985,12 +5987,8 @@ msgid "Create another subscription"
msgstr "Créer une nouvelle cotisation" msgstr "Créer une nouvelle cotisation"
#: subscription/templates/subscription/stats.jinja #: subscription/templates/subscription/stats.jinja
msgid "Total subscriptions" msgid "All subscriptions"
msgstr "Cotisations totales" msgstr "Toutes les cotisations"
#: subscription/templates/subscription/stats.jinja
msgid "Subscriptions by type"
msgstr "Cotisations par type"
#: subscription/templates/subscription/subscription.jinja #: subscription/templates/subscription/subscription.jinja
msgid "Existing member" msgid "Existing member"