mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-07-22 16:56:48 +02:00
Compare commits
17 Commits
delete_act
...
16cfaa809a
Author | SHA1 | Date | |
---|---|---|---|
16cfaa809a | |||
f2cd0b6d36 | |||
a2e2ff5fa9 | |||
53d0480a12 | |||
ff812a028c | |||
136f636fda | |||
5a8acbde00 | |||
f60dc8cfa0 | |||
067dd6f9d1 | |||
7b1e32e514 | |||
e88dbfd597 | |||
3d34270959 | |||
3bb99671ec | |||
0d69383dfd | |||
7b9ff119e8 | |||
108a56745c | |||
9643d7652b |
@ -168,7 +168,8 @@ class BasicFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
|
||||
template_name = "food/food_update.html"
|
||||
|
||||
def get_sample_object(self):
|
||||
return BasicFood(
|
||||
# We choose a club which may work or BDE else
|
||||
food = BasicFood(
|
||||
name="",
|
||||
owner_id=1,
|
||||
expiry_date=timezone.now(),
|
||||
@ -177,6 +178,14 @@ class BasicFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
|
||||
date_type='DLC',
|
||||
)
|
||||
|
||||
for membership in self.request.user.memberships.all():
|
||||
club_id = membership.club.id
|
||||
food.owner_id = club_id
|
||||
if PermissionBackend.check_perm(self.request, "food.add_basicfood", food):
|
||||
return food
|
||||
|
||||
return food
|
||||
|
||||
@transaction.atomic
|
||||
def form_valid(self, form):
|
||||
if QRCode.objects.filter(qr_code_number=self.kwargs['slug']).count() > 0:
|
||||
@ -227,13 +236,22 @@ class TransformedFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
|
||||
template_name = "food/food_update.html"
|
||||
|
||||
def get_sample_object(self):
|
||||
return TransformedFood(
|
||||
# We choose a club which may work or BDE else
|
||||
food = TransformedFood(
|
||||
name="",
|
||||
owner_id=1,
|
||||
expiry_date=timezone.now(),
|
||||
is_ready=True,
|
||||
)
|
||||
|
||||
for membership in self.request.user.memberships.all():
|
||||
club_id = membership.club.id
|
||||
food.owner_id = club_id
|
||||
if PermissionBackend.check_perm(self.request, "food.add_transformedfood", food):
|
||||
return food
|
||||
|
||||
return food
|
||||
|
||||
@transaction.atomic
|
||||
def form_valid(self, form):
|
||||
form.instance.expiry_date = timezone.now() + timedelta(days=3)
|
||||
@ -245,10 +263,10 @@ class TransformedFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
|
||||
return reverse_lazy('food:transformedfood_view', kwargs={"pk": self.object.pk})
|
||||
|
||||
|
||||
MAX_FORMS = 10
|
||||
MAX_FORMS = 100
|
||||
|
||||
|
||||
class ManageIngredientsView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
||||
class ManageIngredientsView(LoginRequiredMixin, UpdateView):
|
||||
"""
|
||||
A view to manage ingredient for a transformed food
|
||||
"""
|
||||
@ -279,6 +297,14 @@ class ManageIngredientsView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView
|
||||
ingredient.end_of_life = _('Fully used in {meal}'.format(
|
||||
meal=self.object.name))
|
||||
ingredient.save()
|
||||
# We recalculate new expiry date and allergens
|
||||
self.object.expiry_date = self.object.creation_date + self.object.shelf_life
|
||||
self.object.allergens.clear()
|
||||
|
||||
for ingredient in self.object.ingredients.iterator():
|
||||
if not (ingredient.polymorphic_ctype.model == 'basicfood' and ingredient.date_type == 'DDM'):
|
||||
self.object.expiry_date = min(self.object.expiry_date, ingredient.expiry_date)
|
||||
self.object.allergens.set(self.object.allergens.union(ingredient.allergens.all()))
|
||||
|
||||
self.object.save(old_ingredients=old_ingredients, old_allergens=old_allergens)
|
||||
return HttpResponseRedirect(self.get_success_url())
|
||||
|
46
apps/member/migrations/0014_create_bda.py
Normal file
46
apps/member/migrations/0014_create_bda.py
Normal file
@ -0,0 +1,46 @@
|
||||
from django.db import migrations
|
||||
|
||||
def create_bda(apps, schema_editor):
|
||||
"""
|
||||
The club BDA is now pre-injected.
|
||||
"""
|
||||
Club = apps.get_model("member", "club")
|
||||
NoteClub = apps.get_model("note", "noteclub")
|
||||
Alias = apps.get_model("note", "alias")
|
||||
ContentType = apps.get_model('contenttypes', 'ContentType')
|
||||
polymorphic_ctype_id = ContentType.objects.get_for_model(NoteClub).id
|
||||
|
||||
Club.objects.get_or_create(
|
||||
id=10,
|
||||
name="BDA",
|
||||
email="bda.ensparissaclay@gmail.com",
|
||||
require_memberships=True,
|
||||
membership_fee_paid=750,
|
||||
membership_fee_unpaid=750,
|
||||
membership_duration=396,
|
||||
membership_start="2024-08-01",
|
||||
membership_end="2025-09-30",
|
||||
)
|
||||
NoteClub.objects.get_or_create(
|
||||
id=1937,
|
||||
club_id=10,
|
||||
polymorphic_ctype_id=polymorphic_ctype_id,
|
||||
)
|
||||
Alias.objects.get_or_create(
|
||||
id=1937,
|
||||
note_id=1937,
|
||||
name="BDA",
|
||||
normalized_name="bda",
|
||||
)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('member', '0013_auto_20240801_1436'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(create_bda),
|
||||
]
|
||||
|
@ -3998,6 +3998,54 @@
|
||||
"description": "Créer une transaction de ou vers la note d'un club tant que la source reste au dessus de -50 €"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "permission.permission",
|
||||
"pk": 271,
|
||||
"fields": {
|
||||
"model": [
|
||||
"wei",
|
||||
"bus"
|
||||
],
|
||||
"query": "{\"wei\": [\"club\"]}",
|
||||
"type": "change",
|
||||
"mask": 3,
|
||||
"field": "",
|
||||
"permanent": false,
|
||||
"description": "Modifier n'importe quel bus du wei"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "permission.permission",
|
||||
"pk": 272,
|
||||
"fields": {
|
||||
"model": [
|
||||
"wei",
|
||||
"bus"
|
||||
],
|
||||
"query": "{\"wei\": [\"club\"]}",
|
||||
"type": "view",
|
||||
"mask": 3,
|
||||
"field": "",
|
||||
"permanent": false,
|
||||
"description": "Voir tous les bus du wei"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "permission.permission",
|
||||
"pk": 273,
|
||||
"fields": {
|
||||
"model": [
|
||||
"wei",
|
||||
"busteam"
|
||||
],
|
||||
"query": "{\"bus__wei\": [\"club\"], \"bus__wei__membership_end__gte\": [\"today\"]}",
|
||||
"type": "view",
|
||||
"mask": 3,
|
||||
"field": "",
|
||||
"permanent": false,
|
||||
"description": "Voir toutes les équipes WEI"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "permission.role",
|
||||
"pk": 1,
|
||||
@ -4152,8 +4200,8 @@
|
||||
"name": "Pr\u00e9sident\u22c5e de club",
|
||||
"permissions": [
|
||||
62,
|
||||
142,
|
||||
135
|
||||
135,
|
||||
142
|
||||
]
|
||||
}
|
||||
},
|
||||
@ -4382,7 +4430,10 @@
|
||||
112,
|
||||
113,
|
||||
128,
|
||||
130
|
||||
130,
|
||||
271,
|
||||
272,
|
||||
273
|
||||
]
|
||||
}
|
||||
},
|
||||
@ -4562,6 +4613,133 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "permission.role",
|
||||
"pk": 23,
|
||||
"fields": {
|
||||
"for_club": 2,
|
||||
"name": "Darbonne",
|
||||
"permissions": [
|
||||
30,
|
||||
31,
|
||||
32
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "permission.role",
|
||||
"pk": 24,
|
||||
"fields": {
|
||||
"for_club": null,
|
||||
"name": "Staffeur⋅euse (S&L,Respo Tech,...)",
|
||||
"permissions": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "permission.role",
|
||||
"pk": 25,
|
||||
"fields": {
|
||||
"for_club": null,
|
||||
"name": "Référent⋅e Bus",
|
||||
"permissions": [
|
||||
22,
|
||||
84,
|
||||
115,
|
||||
117,
|
||||
118,
|
||||
119,
|
||||
120,
|
||||
121,
|
||||
122
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "permission.role",
|
||||
"pk": 28,
|
||||
"fields": {
|
||||
"for_club": 10,
|
||||
"name": "Trésorièr⸱e BDA",
|
||||
"permissions": [
|
||||
55,
|
||||
56,
|
||||
57,
|
||||
58,
|
||||
135,
|
||||
143,
|
||||
176,
|
||||
177,
|
||||
178,
|
||||
243,
|
||||
260,
|
||||
261,
|
||||
262,
|
||||
263,
|
||||
264,
|
||||
265,
|
||||
266,
|
||||
267,
|
||||
268,
|
||||
269
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "permission.role",
|
||||
"pk": 30,
|
||||
"fields": {
|
||||
"for_club": 10,
|
||||
"name": "Respo sorties",
|
||||
"permissions": [
|
||||
49,
|
||||
62,
|
||||
141,
|
||||
241,
|
||||
242,
|
||||
243
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "permission.role",
|
||||
"pk": 31,
|
||||
"fields": {
|
||||
"for_club": 1,
|
||||
"name": "Respo comm",
|
||||
"permissions": [
|
||||
135,
|
||||
244
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "permission.role",
|
||||
"pk": 32,
|
||||
"fields": {
|
||||
"for_club": 10,
|
||||
"name": "Respo comm Art",
|
||||
"permissions": [
|
||||
135,
|
||||
245
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "permission.role",
|
||||
"pk": 33,
|
||||
"fields": {
|
||||
"for_club": 10,
|
||||
"name": "Respo Jam",
|
||||
"permissions": [
|
||||
247,
|
||||
250,
|
||||
251,
|
||||
252,
|
||||
253,
|
||||
254
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "wei.weirole",
|
||||
"pk": 12,
|
||||
@ -4596,5 +4774,15 @@
|
||||
"model": "wei.weirole",
|
||||
"pk": 18,
|
||||
"fields": {}
|
||||
},
|
||||
{
|
||||
"model": "wei.weirole",
|
||||
"pk": 24,
|
||||
"fields": {}
|
||||
},
|
||||
{
|
||||
"model": "wei.weirole",
|
||||
"pk": 25,
|
||||
"fields": {}
|
||||
}
|
||||
]
|
||||
|
@ -39,7 +39,9 @@ class WEIRegistrationForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = WEIRegistration
|
||||
exclude = ('wei', 'clothing_cut')
|
||||
fields = ['user', 'soge_credit', 'birth_date', 'gender', 'clothing_size',
|
||||
'health_issues', 'emergency_contact_name', 'emergency_contact_phone', 'first_year',
|
||||
'information_json']
|
||||
widgets = {
|
||||
"user": Autocomplete(
|
||||
User,
|
||||
@ -81,11 +83,6 @@ class WEIChooseBusForm(forms.Form):
|
||||
|
||||
|
||||
class WEIMembershipForm(forms.ModelForm):
|
||||
caution_check = forms.BooleanField(
|
||||
required=False,
|
||||
label=_("Caution check given"),
|
||||
)
|
||||
|
||||
roles = forms.ModelMultipleChoiceField(
|
||||
queryset=WEIRole.objects,
|
||||
label=_("WEI Roles"),
|
||||
@ -194,3 +191,4 @@ class BusTeamForm(forms.ModelForm):
|
||||
),
|
||||
"color": ColorWidget(),
|
||||
}
|
||||
# "color": ColorWidget(),
|
||||
|
18
apps/wei/migrations/0011_alter_weiclub_year.py
Normal file
18
apps/wei/migrations/0011_alter_weiclub_year.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.21 on 2025-05-25 12:23
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('wei', '0010_remove_weiregistration_specific_diet'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='weiclub',
|
||||
name='year',
|
||||
field=models.PositiveIntegerField(default=2025, unique=True, verbose_name='year'),
|
||||
),
|
||||
]
|
@ -98,7 +98,7 @@ class WEIRegistrationTable(tables.Table):
|
||||
if not hasperm:
|
||||
return format_html("<span class='no-perm'></span>")
|
||||
|
||||
url = reverse_lazy('wei:validate_registration', args=(record.pk,))
|
||||
url = reverse_lazy('wei:wei_update_registration', args=(record.pk,)) + '?validate=true'
|
||||
text = _('Validate')
|
||||
if record.fee > record.user.note.balance and not record.soge_credit:
|
||||
btn_class = 'btn-secondary'
|
||||
|
@ -18,6 +18,8 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
<div class="card-footer text-center">
|
||||
<a class="btn btn-primary btn-sm my-1" href="{% url 'wei:update_bus' pk=bus.pk %}"
|
||||
data-turbolinks="false">{% trans "Edit" %}</a>
|
||||
<a class="btn btn-primary btn-sm my-1" href="{% url 'wei:manage_bus' pk=bus.pk %}"
|
||||
data-turbolinks="false">{% trans "View" %}</a>
|
||||
<a class="btn btn-primary btn-sm my-1" href="{% url 'wei:add_team' pk=bus.pk %}"
|
||||
data-turbolinks="false">{% trans "Add team" %}</a>
|
||||
</div>
|
||||
|
@ -13,9 +13,17 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
<div class="card-body">
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{{ form.media }}
|
||||
{{ form|crispy }}
|
||||
<button class="btn btn-primary" type="submit">{% trans "Submit" %}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
if (window.jscolor && jscolor.install) {
|
||||
jscolor.install();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
@ -8,18 +8,20 @@ from datetime import date, timedelta
|
||||
from tempfile import mkdtemp
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.db import transaction
|
||||
from django.db.models import Q, Count
|
||||
from django.db.models.functions.text import Lower
|
||||
from django import forms
|
||||
from django.http import HttpResponse, Http404
|
||||
from django.shortcuts import redirect
|
||||
from django.template.loader import render_to_string
|
||||
from django.urls import reverse_lazy
|
||||
from django.views import View
|
||||
from django.views.generic import DetailView, UpdateView, RedirectView, TemplateView
|
||||
from django.views.generic import DetailView, UpdateView, RedirectView, TemplateView, CreateView
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic.edit import BaseFormView, DeleteView
|
||||
from django_tables2 import SingleTableView, MultiTableMixin
|
||||
@ -37,6 +39,7 @@ from .forms import WEIForm, WEIRegistrationForm, BusForm, BusTeamForm, WEIMember
|
||||
WEIMembershipForm, CurrentSurvey
|
||||
from .tables import BusRepartitionTable, BusTable, BusTeamTable, WEITable, WEIRegistrationTable, \
|
||||
WEIRegistration1ATable, WEIMembershipTable
|
||||
from .forms.surveys import CurrentSurvey
|
||||
|
||||
|
||||
class CurrentWEIDetailView(LoginRequiredMixin, RedirectView):
|
||||
@ -441,6 +444,13 @@ class BusTeamCreateView(ProtectQuerysetMixin, ProtectedCreateView):
|
||||
self.object.refresh_from_db()
|
||||
return reverse_lazy("wei:manage_bus_team", kwargs={"pk": self.object.pk})
|
||||
|
||||
def get_template_names(self):
|
||||
names = super().get_template_names()
|
||||
return names
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class BusTeamUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
||||
"""
|
||||
@ -473,6 +483,13 @@ class BusTeamUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
||||
self.object.refresh_from_db()
|
||||
return reverse_lazy("wei:manage_bus_team", kwargs={"pk": self.object.pk})
|
||||
|
||||
def get_template_names(self):
|
||||
names = super().get_template_names()
|
||||
return names
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class BusTeamManageView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
|
||||
"""
|
||||
@ -546,9 +563,15 @@ class WEIRegister1AView(ProtectQuerysetMixin, ProtectedCreateView):
|
||||
def get_form(self, form_class=None):
|
||||
form = super().get_form(form_class)
|
||||
form.fields["user"].initial = self.request.user
|
||||
|
||||
# Cacher les champs pendant l'inscription initiale
|
||||
if "first_year" in form.fields:
|
||||
del form.fields["first_year"]
|
||||
if "caution_check" in form.fields:
|
||||
del form.fields["caution_check"]
|
||||
if "information_json" in form.fields:
|
||||
del form.fields["information_json"]
|
||||
|
||||
return form
|
||||
|
||||
@transaction.atomic
|
||||
@ -644,8 +667,12 @@ class WEIRegister2AView(ProtectQuerysetMixin, ProtectedCreateView):
|
||||
form.fields["soge_credit"].disabled = True
|
||||
form.fields["soge_credit"].help_text = _("You already opened an account in the Société générale.")
|
||||
|
||||
del form.fields["caution_check"]
|
||||
# Cacher les champs pendant l'inscription initiale
|
||||
if "first_year" in form.fields:
|
||||
del form.fields["first_year"]
|
||||
if "caution_check" in form.fields:
|
||||
del form.fields["caution_check"]
|
||||
if "information_json" in form.fields:
|
||||
del form.fields["information_json"]
|
||||
|
||||
return form
|
||||
@ -702,11 +729,15 @@ class WEIUpdateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Update
|
||||
# We can't update a registration once the WEI is started and before the membership start date
|
||||
if today >= wei.date_start or today < wei.membership_start:
|
||||
return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,)))
|
||||
# Store the validate parameter in the view's state
|
||||
self.should_validate = request.GET.get('validate', False)
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["club"] = self.object.wei
|
||||
# Pass the validate parameter to the template
|
||||
context["should_validate"] = self.should_validate
|
||||
|
||||
if self.object.is_validated:
|
||||
membership_form = self.get_membership_form(instance=self.object.membership,
|
||||
@ -740,6 +771,9 @@ class WEIUpdateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Update
|
||||
# The auto-json-format may cause issues with the default field remove
|
||||
if not PermissionBackend.check_perm(self.request, 'wei.change_weiregistration_information_json', self.object):
|
||||
del form.fields["information_json"]
|
||||
# Masquer le champ caution_check pour tout le monde dans le formulaire de modification
|
||||
if "caution_check" in form.fields:
|
||||
del form.fields["caution_check"]
|
||||
return form
|
||||
|
||||
def get_membership_form(self, data=None, instance=None):
|
||||
@ -759,10 +793,30 @@ class WEIUpdateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Update
|
||||
def form_valid(self, form):
|
||||
# If the membership is already validated, then we update the bus and the team (and the roles)
|
||||
if form.instance.is_validated:
|
||||
membership_form = self.get_membership_form(self.request.POST, form.instance.membership)
|
||||
try:
|
||||
membership = form.instance.membership
|
||||
if membership is None:
|
||||
raise ValueError(_("No membership found for this registration"))
|
||||
|
||||
membership_form = self.get_membership_form(self.request.POST, instance=membership)
|
||||
if not membership_form.is_valid():
|
||||
return self.form_invalid(form)
|
||||
|
||||
# Vérifier que l'utilisateur a la permission de modifier le membership
|
||||
# On vérifie d'abord si l'utilisateur a la permission générale de modification
|
||||
if not self.request.user.has_perm("wei.change_weimembership"):
|
||||
raise PermissionDenied(_("You don't have the permission to update memberships"))
|
||||
|
||||
# On vérifie ensuite les permissions spécifiques pour chaque champ modifié
|
||||
for field_name in membership_form.changed_data:
|
||||
perm = f"wei.change_weimembership_{field_name}"
|
||||
if not self.request.user.has_perm(perm):
|
||||
raise PermissionDenied(_("You don't have the permission to update the field %(field)s") % {'field': field_name})
|
||||
|
||||
membership_form.save()
|
||||
except (WEIMembership.DoesNotExist, ValueError, PermissionDenied) as e:
|
||||
form.add_error(None, str(e))
|
||||
return self.form_invalid(form)
|
||||
# If it is not validated and if this is an old member, then we update the choices
|
||||
elif not form.instance.first_year and PermissionBackend.check_perm(
|
||||
self.request, "wei.change_weiregistration_information_json", self.object):
|
||||
@ -787,14 +841,8 @@ class WEIUpdateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Update
|
||||
survey = CurrentSurvey(self.object)
|
||||
if not survey.is_complete():
|
||||
return reverse_lazy("wei:wei_survey", kwargs={"pk": self.object.pk})
|
||||
if PermissionBackend.check_perm(self.request, "wei.add_weimembership", WEIMembership(
|
||||
club=self.object.wei,
|
||||
user=self.object.user,
|
||||
date_start=date.today(),
|
||||
date_end=date.today(),
|
||||
fee=0,
|
||||
registration=self.object,
|
||||
)):
|
||||
# On redirige vers la validation uniquement si c'est explicitement demandé (et stocké dans la vue)
|
||||
if self.should_validate and self.request.user.has_perm("wei.add_weimembership"):
|
||||
return reverse_lazy("wei:validate_registration", kwargs={"pk": self.object.pk})
|
||||
return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.wei.pk})
|
||||
|
||||
@ -828,26 +876,21 @@ class WEIDeleteRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Delete
|
||||
return reverse_lazy('wei:wei_detail', args=(self.object.wei.pk,))
|
||||
|
||||
|
||||
class WEIValidateRegistrationView(ProtectQuerysetMixin, ProtectedCreateView):
|
||||
class WEIValidateRegistrationView(LoginRequiredMixin, CreateView):
|
||||
"""
|
||||
Validate WEI Registration
|
||||
"""
|
||||
model = WEIMembership
|
||||
extra_context = {"title": _("Validate WEI registration")}
|
||||
|
||||
def get_sample_object(self):
|
||||
registration = WEIRegistration.objects.get(pk=self.kwargs["pk"])
|
||||
return WEIMembership(
|
||||
club=registration.wei,
|
||||
user=registration.user,
|
||||
date_start=date.today(),
|
||||
date_end=date.today() + timedelta(days=1),
|
||||
fee=0,
|
||||
registration=registration,
|
||||
)
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
wei = WEIRegistration.objects.get(pk=self.kwargs["pk"]).wei
|
||||
# Vérifier d'abord si l'utilisateur a la permission générale
|
||||
if not request.user.has_perm("wei.add_weimembership"):
|
||||
raise PermissionDenied(_("You don't have the permission to validate registrations"))
|
||||
|
||||
registration = WEIRegistration.objects.get(pk=self.kwargs["pk"])
|
||||
|
||||
wei = registration.wei
|
||||
today = date.today()
|
||||
# We can't validate anyone once the WEI is started and before the membership start date
|
||||
if today >= wei.date_start or today < wei.membership_start:
|
||||
@ -900,8 +943,14 @@ class WEIValidateRegistrationView(ProtectQuerysetMixin, ProtectedCreateView):
|
||||
form.fields["last_name"].initial = registration.user.last_name
|
||||
form.fields["first_name"].initial = registration.user.first_name
|
||||
|
||||
if "caution_check" in form.fields:
|
||||
form.fields["caution_check"].initial = registration.caution_check
|
||||
# Ajouter le champ caution_check uniquement pour les non-première année et le rendre obligatoire
|
||||
if not registration.first_year:
|
||||
form.fields["caution_check"] = forms.BooleanField(
|
||||
required=True,
|
||||
initial=registration.caution_check,
|
||||
label=_("Caution check given"),
|
||||
help_text=_("Please make sure the check is given before validating the registration")
|
||||
)
|
||||
|
||||
if registration.soge_credit:
|
||||
form.fields["credit_type"].disabled = True
|
||||
@ -1289,8 +1338,22 @@ class WEIAttributeBus1ANextView(LoginRequiredMixin, RedirectView):
|
||||
if not wei.exists():
|
||||
raise Http404
|
||||
wei = wei.get()
|
||||
qs = WEIRegistration.objects.filter(wei=wei, membership__isnull=False, membership__bus__isnull=True)
|
||||
qs = qs.filter(information_json__contains='selected_bus_pk') # not perfect, but works...
|
||||
if qs.exists():
|
||||
return reverse_lazy('wei:wei_bus_1A', args=(qs.first().pk, ))
|
||||
return reverse_lazy('wei:wei_1A_list', args=(wei.pk, ))
|
||||
|
||||
# On cherche d'abord les 1A qui ont une inscription validée (membership) mais pas de bus
|
||||
qs = WEIRegistration.objects.filter(
|
||||
wei=wei,
|
||||
first_year=True,
|
||||
membership__isnull=False,
|
||||
membership__bus__isnull=True
|
||||
)
|
||||
|
||||
# Parmi eux, on prend ceux qui ont répondu au questionnaire (ont un bus préféré)
|
||||
qs = qs.filter(information_json__contains='selected_bus_pk')
|
||||
|
||||
if not qs.exists():
|
||||
# Si on ne trouve personne, on affiche un message et on retourne à la liste
|
||||
messages.info(self.request, _("No first year student without a bus found. Either all of them have a bus, or none has filled the survey yet."))
|
||||
return reverse_lazy('wei:wei_1A_list', args=(wei.pk,))
|
||||
|
||||
# On redirige vers la page d'attribution pour le premier étudiant trouvé
|
||||
return reverse_lazy('wei:wei_bus_1A', args=(qs.first().pk,))
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -63,8 +63,16 @@ class ColorWidget(Widget):
|
||||
def format_value(self, value):
|
||||
if value is None:
|
||||
value = 0xFFFFFF
|
||||
if isinstance(value, str):
|
||||
return value # Assume it's already a hex string like "#FFAA33"
|
||||
try:
|
||||
return "#{:06X}".format(value)
|
||||
except Exception:
|
||||
return "#FFFFFF"
|
||||
|
||||
|
||||
def value_from_datadict(self, data, files, name):
|
||||
val = super().value_from_datadict(data, files, name)
|
||||
if val:
|
||||
return int(val[1:], 16)
|
||||
return None
|
5
note_kfet/templates/colorfield/color.html
Normal file
5
note_kfet/templates/colorfield/color.html
Normal file
@ -0,0 +1,5 @@
|
||||
<input type="text"
|
||||
name="{{ widget.name }}"
|
||||
value="{{ widget.value }}"
|
||||
class="jscolor"
|
||||
{% include "django/forms/widgets/attrs.html" %}>
|
Reference in New Issue
Block a user