mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-06-21 18:08:21 +02:00
Compare commits
28 Commits
Author | SHA1 | Date | |
---|---|---|---|
3f76ca6472 | |||
5c5f579729 | |||
a6df0e7c69 | |||
6822500fdc | |||
63f6528adc | |||
40ac1daece | |||
e617048332 | |||
9eb6edb37d | |||
70a57bf02d | |||
02453e07ba | |||
4479e8f97a | |||
a351415494 | |||
16cfaa809a | |||
f2cd0b6d36 | |||
a2e2ff5fa9 | |||
53d0480a12 | |||
ff812a028c | |||
136f636fda | |||
5a8acbde00 | |||
f60dc8cfa0 | |||
067dd6f9d1 | |||
7b1e32e514 | |||
e88dbfd597 | |||
3d34270959 | |||
3bb99671ec | |||
0d69383dfd | |||
7b9ff119e8 | |||
9643d7652b |
@ -263,7 +263,7 @@ class TransformedFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
|
|||||||
return reverse_lazy('food:transformedfood_view', kwargs={"pk": self.object.pk})
|
return reverse_lazy('food:transformedfood_view', kwargs={"pk": self.object.pk})
|
||||||
|
|
||||||
|
|
||||||
MAX_FORMS = 10
|
MAX_FORMS = 100
|
||||||
|
|
||||||
|
|
||||||
class ManageIngredientsView(LoginRequiredMixin, UpdateView):
|
class ManageIngredientsView(LoginRequiredMixin, UpdateView):
|
||||||
|
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),
|
||||||
|
]
|
||||||
|
|
@ -1695,7 +1695,7 @@
|
|||||||
"wei",
|
"wei",
|
||||||
"weimembership"
|
"weimembership"
|
||||||
],
|
],
|
||||||
"query": "[\"AND\", {\"club\": [\"club\"], \"club__weiclub__membership_end__gte\": [\"today\"]}, [\"OR\", {\"registration__soge_credit\": true}, {\"user__note__balance__gte\": {\"F\": [\"F\", \"fee\"]}}]]",
|
"query": "{\"club\": [\"club\"]}",
|
||||||
"type": "add",
|
"type": "add",
|
||||||
"mask": 2,
|
"mask": 2,
|
||||||
"field": "",
|
"field": "",
|
||||||
@ -3998,6 +3998,358 @@
|
|||||||
"description": "Créer une transaction de ou vers la note d'un club tant que la source reste au dessus de -50 €"
|
"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.permission",
|
||||||
|
"pk": 274,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"member",
|
||||||
|
"club"
|
||||||
|
],
|
||||||
|
"query": "{\"bus__wei\": [\"club\"]}",
|
||||||
|
"type": "view",
|
||||||
|
"mask": 3,
|
||||||
|
"field": "",
|
||||||
|
"permanent": false,
|
||||||
|
"description": "Voir les informations de clubs des bus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 275,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"member",
|
||||||
|
"club"
|
||||||
|
],
|
||||||
|
"query": "{\"bus__wei\": [\"club\"]}",
|
||||||
|
"type": "change",
|
||||||
|
"mask": 3,
|
||||||
|
"field": "",
|
||||||
|
"permanent": false,
|
||||||
|
"description": "Modifier les clubs des bus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 276,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"member",
|
||||||
|
"membership"
|
||||||
|
],
|
||||||
|
"query": "{\"club__bus__wei\": [\"club\"]}",
|
||||||
|
"type": "add",
|
||||||
|
"mask": 3,
|
||||||
|
"field": "",
|
||||||
|
"permanent": false,
|
||||||
|
"description": "Ajouter un⋅e membre à un club de bus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 277,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"member",
|
||||||
|
"membership"
|
||||||
|
],
|
||||||
|
"query": "{\"club__bus__wei\": [\"club\"]}",
|
||||||
|
"type": "view",
|
||||||
|
"mask": 3,
|
||||||
|
"field": "",
|
||||||
|
"permanent": false,
|
||||||
|
"description": "Voir les adhérents d'un club de bus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 278,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"member",
|
||||||
|
"membership"
|
||||||
|
],
|
||||||
|
"query": "{\"club__bus__wei\": [\"club\"]}",
|
||||||
|
"type": "change",
|
||||||
|
"mask": 3,
|
||||||
|
"field": "",
|
||||||
|
"permanent": false,
|
||||||
|
"description": "Modifier l'adhésion d'un club de bus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 279,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"note",
|
||||||
|
"note"
|
||||||
|
],
|
||||||
|
"query": "{\"noteclub__club__bus__wei\": [\"club\"]}",
|
||||||
|
"type": "view",
|
||||||
|
"mask": 3,
|
||||||
|
"field": "",
|
||||||
|
"permanent": false,
|
||||||
|
"description": "Voir la note d'un club de bus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 280,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"note",
|
||||||
|
"transaction"
|
||||||
|
],
|
||||||
|
"query": "[\"OR\", {\"source__noteclub__club__bus__wei\": [\"club\"]}, {\"destination__noteclub__club__bus__wei\": [\"club\"]}]",
|
||||||
|
"type": "view",
|
||||||
|
"mask": 3,
|
||||||
|
"field": "",
|
||||||
|
"permanent": false,
|
||||||
|
"description": "Voir les transactions d'un club de bus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 281,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"note",
|
||||||
|
"transaction"
|
||||||
|
],
|
||||||
|
"query": "[\"AND\", [\"OR\", {\"source__noteclub__club__bus__wei\": [\"club\"]}, {\"destination__noteclub__club__bus__wei\": [\"club\"]}], [\"OR\", {\"source__balance__gte\": {\"F\": [\"SUB\", [\"MUL\", [\"F\", \"amount\"], [\"F\", \"quantity\"]], 2000]}}, {\"valid\": false}]]",
|
||||||
|
"type": "add",
|
||||||
|
"mask": 3,
|
||||||
|
"field": "",
|
||||||
|
"permanent": false,
|
||||||
|
"description": "Créer une transaction d'un club de bus tant que la source reste au dessus de -20 €"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 282,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"note",
|
||||||
|
"transaction"
|
||||||
|
],
|
||||||
|
"query": "[\"AND\", [\"OR\", {\"source__noteclub__club\": [\"club\"]}, {\"destination__noteclub__club\": [\"club\"]}], [\"OR\", {\"source__balance__gte\": {\"F\": [\"SUB\", [\"MUL\", [\"F\", \"amount\"], [\"F\", \"quantity\"]], 2000]}}, {\"valid\": false}]]",
|
||||||
|
"type": "add",
|
||||||
|
"mask": 3,
|
||||||
|
"field": "",
|
||||||
|
"permanent": false,
|
||||||
|
"description": "Créer une transaction d'un WEI tant que la source reste au dessus de -20 €"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 283,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"auth",
|
||||||
|
"user"
|
||||||
|
],
|
||||||
|
"query": "{\"memberships__club__name\": \"Kfet\", \"memberships__roles__name\": \"Adh\u00e9rent\u22c5e Kfet\", \"memberships__date_start__lte\": [\"today\"], \"memberships__date_end__gte\": [\"today\"]}",
|
||||||
|
"type": "view",
|
||||||
|
"mask": 3,
|
||||||
|
"field": "",
|
||||||
|
"permanent": false,
|
||||||
|
"description": "Voir n'importe quel⋅le utilisateur⋅rice qui est adhérent⋅e Kfet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 284,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"member",
|
||||||
|
"club"
|
||||||
|
],
|
||||||
|
"query": "{\"bus\": [\"membership\", \"weimembership\", \"bus\"]}",
|
||||||
|
"type": "view",
|
||||||
|
"mask": 3,
|
||||||
|
"field": "",
|
||||||
|
"permanent": false,
|
||||||
|
"description": "Voir les informations de club de son bus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 285,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"member",
|
||||||
|
"club"
|
||||||
|
],
|
||||||
|
"query": "{\"bus\": [\"membership\", \"weimembership\", \"bus\"]}",
|
||||||
|
"type": "change",
|
||||||
|
"mask": 3,
|
||||||
|
"field": "",
|
||||||
|
"permanent": false,
|
||||||
|
"description": "Modifier le club de son bus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 286,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"member",
|
||||||
|
"membership"
|
||||||
|
],
|
||||||
|
"query": "{\"club__bus\": [\"membership\", \"weimembership\", \"bus\"]}",
|
||||||
|
"type": "add",
|
||||||
|
"mask": 3,
|
||||||
|
"field": "",
|
||||||
|
"permanent": false,
|
||||||
|
"description": "Ajouter un⋅e membre au club de son bus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 287,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"member",
|
||||||
|
"membership"
|
||||||
|
],
|
||||||
|
"query": "{\"club__bus\": [\"membership\", \"weimembership\", \"bus\"]}",
|
||||||
|
"type": "view",
|
||||||
|
"mask": 3,
|
||||||
|
"field": "",
|
||||||
|
"permanent": false,
|
||||||
|
"description": "Voir les adhérents du club de son bus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 288,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"member",
|
||||||
|
"membership"
|
||||||
|
],
|
||||||
|
"query": "{\"club__bus\": [\"membership\", \"weimembership\", \"bus\"]}",
|
||||||
|
"type": "change",
|
||||||
|
"mask": 3,
|
||||||
|
"field": "",
|
||||||
|
"permanent": false,
|
||||||
|
"description": "Modifier l'adhésion au club de son bus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 289,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"note",
|
||||||
|
"note"
|
||||||
|
],
|
||||||
|
"query": "{\"noteclub__club__bus\": [\"membership\", \"weimembership\", \"bus\"]}",
|
||||||
|
"type": "view",
|
||||||
|
"mask": 3,
|
||||||
|
"field": "",
|
||||||
|
"permanent": false,
|
||||||
|
"description": "Voir la note du club de son bus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 290,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"note",
|
||||||
|
"transaction"
|
||||||
|
],
|
||||||
|
"query": "[\"OR\", {\"source__noteclub__club__bus\": [\"membership\", \"weimembership\", \"bus\"]}, {\"destination__noteclub__club__bus\": [\"membership\", \"weimembership\", \"bus\"]}]",
|
||||||
|
"type": "view",
|
||||||
|
"mask": 3,
|
||||||
|
"field": "",
|
||||||
|
"permanent": false,
|
||||||
|
"description": "Voir les transactions du club de son bus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 291,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"wei",
|
||||||
|
"bus"
|
||||||
|
],
|
||||||
|
"query": "{\"pk\": [\"membership\", \"weimembership\", \"bus\", \"pk\"], \"wei__date_end__gte\": [\"today\"]}",
|
||||||
|
"type": "view",
|
||||||
|
"mask": 3,
|
||||||
|
"field": "",
|
||||||
|
"permanent": false,
|
||||||
|
"description": "Voir mon bus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 292,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"member",
|
||||||
|
"membership"
|
||||||
|
],
|
||||||
|
"query": "{\"club__pk__lte\": 2}",
|
||||||
|
"type": "add",
|
||||||
|
"mask": 3,
|
||||||
|
"field": "",
|
||||||
|
"permanent": false,
|
||||||
|
"description": "Ajouter un membre au BDE ou à la Kfet"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"model": "permission.role",
|
"model": "permission.role",
|
||||||
"pk": 1,
|
"pk": 1,
|
||||||
@ -4091,8 +4443,8 @@
|
|||||||
158,
|
158,
|
||||||
159,
|
159,
|
||||||
160,
|
160,
|
||||||
212,
|
212,
|
||||||
222
|
222
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -4133,14 +4485,14 @@
|
|||||||
50,
|
50,
|
||||||
141,
|
141,
|
||||||
169,
|
169,
|
||||||
217,
|
217,
|
||||||
218,
|
218,
|
||||||
219,
|
219,
|
||||||
220,
|
220,
|
||||||
221,
|
221,
|
||||||
247,
|
247,
|
||||||
258,
|
258,
|
||||||
259
|
259
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -4152,8 +4504,8 @@
|
|||||||
"name": "Pr\u00e9sident\u22c5e de club",
|
"name": "Pr\u00e9sident\u22c5e de club",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
62,
|
62,
|
||||||
142,
|
135,
|
||||||
135
|
142
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -4358,6 +4710,8 @@
|
|||||||
"name": "GC WEI",
|
"name": "GC WEI",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
22,
|
22,
|
||||||
|
49,
|
||||||
|
62,
|
||||||
70,
|
70,
|
||||||
72,
|
72,
|
||||||
76,
|
76,
|
||||||
@ -4382,7 +4736,23 @@
|
|||||||
112,
|
112,
|
||||||
113,
|
113,
|
||||||
128,
|
128,
|
||||||
130
|
130,
|
||||||
|
142,
|
||||||
|
269,
|
||||||
|
271,
|
||||||
|
272,
|
||||||
|
273,
|
||||||
|
274,
|
||||||
|
275,
|
||||||
|
276,
|
||||||
|
277,
|
||||||
|
278,
|
||||||
|
279,
|
||||||
|
280,
|
||||||
|
281,
|
||||||
|
282,
|
||||||
|
283,
|
||||||
|
292
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -4401,7 +4771,14 @@
|
|||||||
119,
|
119,
|
||||||
120,
|
120,
|
||||||
121,
|
121,
|
||||||
122
|
122,
|
||||||
|
284,
|
||||||
|
285,
|
||||||
|
286,
|
||||||
|
287,
|
||||||
|
289,
|
||||||
|
290,
|
||||||
|
291
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -4538,8 +4915,8 @@
|
|||||||
"name": "GC anti-VSS",
|
"name": "GC anti-VSS",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
42,
|
42,
|
||||||
135,
|
135,
|
||||||
150,
|
150,
|
||||||
163,
|
163,
|
||||||
164
|
164
|
||||||
]
|
]
|
||||||
@ -4555,13 +4932,147 @@
|
|||||||
137,
|
137,
|
||||||
211,
|
211,
|
||||||
212,
|
212,
|
||||||
213,
|
213,
|
||||||
214,
|
214,
|
||||||
215,
|
215,
|
||||||
216
|
216
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"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,
|
||||||
|
284,
|
||||||
|
285,
|
||||||
|
286,
|
||||||
|
287,
|
||||||
|
289,
|
||||||
|
290,
|
||||||
|
291
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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",
|
"model": "wei.weirole",
|
||||||
"pk": 12,
|
"pk": 12,
|
||||||
@ -4596,5 +5107,15 @@
|
|||||||
"model": "wei.weirole",
|
"model": "wei.weirole",
|
||||||
"pk": 18,
|
"pk": 18,
|
||||||
"fields": {}
|
"fields": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "wei.weirole",
|
||||||
|
"pk": 24,
|
||||||
|
"fields": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "wei.weirole",
|
||||||
|
"pk": 25,
|
||||||
|
"fields": {}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -10,7 +10,7 @@ from django.utils import timezone
|
|||||||
from django.utils.crypto import get_random_string
|
from django.utils.crypto import get_random_string
|
||||||
from activity.models import Activity
|
from activity.models import Activity
|
||||||
from member.models import Club, Membership
|
from member.models import Club, Membership
|
||||||
from note.models import NoteUser
|
from note.models import NoteUser, NoteClub
|
||||||
from wei.models import WEIClub, Bus, WEIRegistration
|
from wei.models import WEIClub, Bus, WEIRegistration
|
||||||
|
|
||||||
|
|
||||||
@ -122,10 +122,13 @@ class TestPermissionDenied(TestCase):
|
|||||||
|
|
||||||
def test_validate_weiregistration(self):
|
def test_validate_weiregistration(self):
|
||||||
wei = WEIClub.objects.create(
|
wei = WEIClub.objects.create(
|
||||||
|
name="WEI Test",
|
||||||
membership_start=date.today(),
|
membership_start=date.today(),
|
||||||
date_start=date.today() + timedelta(days=1),
|
date_start=date.today() + timedelta(days=1),
|
||||||
date_end=date.today() + timedelta(days=1),
|
date_end=date.today() + timedelta(days=1),
|
||||||
|
parent_club=Club.objects.get(name="Kfet"),
|
||||||
)
|
)
|
||||||
|
NoteClub.objects.create(club=wei)
|
||||||
registration = WEIRegistration.objects.create(wei=wei, user=self.user, birth_date="2000-01-01")
|
registration = WEIRegistration.objects.create(wei=wei, user=self.user, birth_date="2000-01-01")
|
||||||
response = self.client.get(reverse("wei:validate_registration", kwargs=dict(pk=registration.pk)))
|
response = self.client.get(reverse("wei:validate_registration", kwargs=dict(pk=registration.pk)))
|
||||||
self.assertEqual(response.status_code, 403)
|
self.assertEqual(response.status_code, 403)
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
# Copyright (C) 2018-2025 by BDE ENS Paris-Saclay
|
# Copyright (C) 2018-2025 by BDE ENS Paris-Saclay
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
from .registration import WEIForm, WEIRegistrationForm, WEIMembership1AForm, WEIMembershipForm, BusForm, BusTeamForm
|
from .registration import WEIForm, WEIRegistrationForm, WEIRegistration1AForm, WEIRegistration2AForm, WEIMembership1AForm, \
|
||||||
|
WEIMembershipForm, BusForm, BusTeamForm
|
||||||
from .surveys import WEISurvey, WEISurveyInformation, WEISurveyAlgorithm, CurrentSurvey
|
from .surveys import WEISurvey, WEISurveyInformation, WEISurveyAlgorithm, CurrentSurvey
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'WEIForm', 'WEIRegistrationForm', 'WEIMembership1AForm', 'WEIMembershipForm', 'BusForm', 'BusTeamForm',
|
'WEIForm', 'WEIRegistrationForm', 'WEIRegistration1AForm', 'WEIRegistration2AForm', 'WEIMembership1AForm', 'WEIMembershipForm', 'BusForm', 'BusTeamForm',
|
||||||
'WEISurvey', 'WEISurveyInformation', 'WEISurveyAlgorithm', 'CurrentSurvey',
|
'WEISurvey', 'WEISurveyInformation', 'WEISurveyAlgorithm', 'CurrentSurvey',
|
||||||
]
|
]
|
||||||
|
@ -24,6 +24,7 @@ class WEIForm(forms.ModelForm):
|
|||||||
"membership_end": DatePickerInput(),
|
"membership_end": DatePickerInput(),
|
||||||
"date_start": DatePickerInput(),
|
"date_start": DatePickerInput(),
|
||||||
"date_end": DatePickerInput(),
|
"date_end": DatePickerInput(),
|
||||||
|
"caution_amount": AmountInput(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -39,7 +40,11 @@ class WEIRegistrationForm(forms.ModelForm):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = WEIRegistration
|
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', 'caution_check'
|
||||||
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
"user": Autocomplete(
|
"user": Autocomplete(
|
||||||
User,
|
User,
|
||||||
@ -49,11 +54,30 @@ class WEIRegistrationForm(forms.ModelForm):
|
|||||||
'placeholder': 'Nom ...',
|
'placeholder': 'Nom ...',
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
"birth_date": DatePickerInput(options={'minDate': '1900-01-01',
|
"birth_date": DatePickerInput(options={
|
||||||
'maxDate': '2100-01-01'}),
|
'minDate': '1900-01-01',
|
||||||
|
'maxDate': '2100-01-01'
|
||||||
|
}),
|
||||||
|
"caution_check": forms.BooleanField(
|
||||||
|
required=False,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class WEIRegistration2AForm(WEIRegistrationForm):
|
||||||
|
class Meta(WEIRegistrationForm.Meta):
|
||||||
|
fields = WEIRegistrationForm.Meta.fields + ['caution_type']
|
||||||
|
widgets = WEIRegistrationForm.Meta.widgets.copy()
|
||||||
|
widgets.update({
|
||||||
|
"caution_type": forms.RadioSelect(),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
class WEIRegistration1AForm(WEIRegistrationForm):
|
||||||
|
class Meta(WEIRegistrationForm.Meta):
|
||||||
|
fields = WEIRegistrationForm.Meta.fields
|
||||||
|
|
||||||
|
|
||||||
class WEIChooseBusForm(forms.Form):
|
class WEIChooseBusForm(forms.Form):
|
||||||
bus = forms.ModelMultipleChoiceField(
|
bus = forms.ModelMultipleChoiceField(
|
||||||
queryset=Bus.objects,
|
queryset=Bus.objects,
|
||||||
@ -72,7 +96,7 @@ class WEIChooseBusForm(forms.Form):
|
|||||||
)
|
)
|
||||||
|
|
||||||
roles = forms.ModelMultipleChoiceField(
|
roles = forms.ModelMultipleChoiceField(
|
||||||
queryset=WEIRole.objects.filter(~Q(name="1A")),
|
queryset=WEIRole.objects.filter(~Q(name="1A") & ~Q(name="GC WEI")),
|
||||||
label=_("WEI Roles"),
|
label=_("WEI Roles"),
|
||||||
help_text=_("Select the roles that you are interested in."),
|
help_text=_("Select the roles that you are interested in."),
|
||||||
initial=WEIRole.objects.filter(name="Adhérent⋅e WEI").all(),
|
initial=WEIRole.objects.filter(name="Adhérent⋅e WEI").all(),
|
||||||
@ -81,13 +105,8 @@ class WEIChooseBusForm(forms.Form):
|
|||||||
|
|
||||||
|
|
||||||
class WEIMembershipForm(forms.ModelForm):
|
class WEIMembershipForm(forms.ModelForm):
|
||||||
caution_check = forms.BooleanField(
|
|
||||||
required=False,
|
|
||||||
label=_("Caution check given"),
|
|
||||||
)
|
|
||||||
|
|
||||||
roles = forms.ModelMultipleChoiceField(
|
roles = forms.ModelMultipleChoiceField(
|
||||||
queryset=WEIRole.objects,
|
queryset=WEIRole.objects.filter(~Q(name="GC WEI")),
|
||||||
label=_("WEI Roles"),
|
label=_("WEI Roles"),
|
||||||
widget=CheckboxSelectMultiple(),
|
widget=CheckboxSelectMultiple(),
|
||||||
)
|
)
|
||||||
@ -194,3 +213,4 @@ class BusTeamForm(forms.ModelForm):
|
|||||||
),
|
),
|
||||||
"color": ColorWidget(),
|
"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'),
|
||||||
|
),
|
||||||
|
]
|
20
apps/wei/migrations/0012_bus_club.py
Normal file
20
apps/wei/migrations/0012_bus_club.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Generated by Django 4.2.21 on 2025-05-29 16:16
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('member', '0014_create_bda'),
|
||||||
|
('wei', '0011_alter_weiclub_year'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='bus',
|
||||||
|
name='club',
|
||||||
|
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bus', to='member.club', verbose_name='club'),
|
||||||
|
),
|
||||||
|
]
|
@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 4.2.21 on 2025-06-01 21:43
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('wei', '0012_bus_club'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='weiclub',
|
||||||
|
name='caution_amount',
|
||||||
|
field=models.PositiveIntegerField(default=0, verbose_name='caution amount'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='weiregistration',
|
||||||
|
name='caution_type',
|
||||||
|
field=models.CharField(choices=[('check', 'Check'), ('note', 'Note transaction')], default='check', max_length=16, verbose_name='caution type'),
|
||||||
|
),
|
||||||
|
]
|
@ -33,6 +33,11 @@ class WEIClub(Club):
|
|||||||
verbose_name=_("date end"),
|
verbose_name=_("date end"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
caution_amount = models.PositiveIntegerField(
|
||||||
|
verbose_name=_("caution amount"),
|
||||||
|
default=0,
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("WEI")
|
verbose_name = _("WEI")
|
||||||
verbose_name_plural = _("WEI")
|
verbose_name_plural = _("WEI")
|
||||||
@ -72,6 +77,15 @@ class Bus(models.Model):
|
|||||||
default=50,
|
default=50,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
club = models.OneToOneField(
|
||||||
|
Club,
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
related_name="bus",
|
||||||
|
verbose_name=_("club"),
|
||||||
|
)
|
||||||
|
|
||||||
description = models.TextField(
|
description = models.TextField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default="",
|
default="",
|
||||||
@ -188,6 +202,16 @@ class WEIRegistration(models.Model):
|
|||||||
verbose_name=_("Caution check given")
|
verbose_name=_("Caution check given")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
caution_type = models.CharField(
|
||||||
|
max_length=16,
|
||||||
|
choices=(
|
||||||
|
('check', _("Check")),
|
||||||
|
('note', _("Note transaction")),
|
||||||
|
),
|
||||||
|
default='check',
|
||||||
|
verbose_name=_("caution type"),
|
||||||
|
)
|
||||||
|
|
||||||
birth_date = models.DateField(
|
birth_date = models.DateField(
|
||||||
verbose_name=_("birth date"),
|
verbose_name=_("birth date"),
|
||||||
)
|
)
|
||||||
|
@ -98,7 +98,7 @@ class WEIRegistrationTable(tables.Table):
|
|||||||
if not hasperm:
|
if not hasperm:
|
||||||
return format_html("<span class='no-perm'></span>")
|
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')
|
text = _('Validate')
|
||||||
if record.fee > record.user.note.balance and not record.soge_credit:
|
if record.fee > record.user.note.balance and not record.soge_credit:
|
||||||
btn_class = 'btn-secondary'
|
btn_class = 'btn-secondary'
|
||||||
|
@ -40,22 +40,20 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
<dt class="col-xl-6">{% trans 'membership fee'|capfirst %}</dt>
|
<dt class="col-xl-6">{% trans 'membership fee'|capfirst %}</dt>
|
||||||
<dd class="col-xl-6">{{ club.membership_fee_paid|pretty_money }}</dd>
|
<dd class="col-xl-6">{{ club.membership_fee_paid|pretty_money }}</dd>
|
||||||
{% else %}
|
{% else %}
|
||||||
{% with bde_kfet_fee=club.parent_club.membership_fee_paid|add:club.parent_club.parent_club.membership_fee_paid %}
|
|
||||||
<dt class="col-xl-6">{% trans 'WEI fee (paid students)'|capfirst %}</dt>
|
|
||||||
<dd class="col-xl-6">{{ club.membership_fee_paid|add:bde_kfet_fee|pretty_money }}
|
|
||||||
<i class="fa fa-question-circle"
|
|
||||||
title="{% trans "The BDE membership is included in the WEI registration." %}"></i></dd>
|
|
||||||
{% endwith %}
|
|
||||||
|
|
||||||
{% with bde_kfet_fee=club.parent_club.membership_fee_unpaid|add:club.parent_club.parent_club.membership_fee_unpaid %}
|
<dt class="col-xl-6">{% trans 'WEI fee (paid students)'|capfirst %}</dt>
|
||||||
|
<dd class="col-xl-6">{{ club.membership_fee_paid|pretty_money }}
|
||||||
|
|
||||||
<dt class="col-xl-6">{% trans 'WEI fee (unpaid students)'|capfirst %}</dt>
|
<dt class="col-xl-6">{% trans 'WEI fee (unpaid students)'|capfirst %}</dt>
|
||||||
<dd class="col-xl-6">{{ club.membership_fee_unpaid|add:bde_kfet_fee|pretty_money }}
|
<dd class="col-xl-6">{{ club.membership_fee_unpaid|pretty_money }}
|
||||||
<i class="fa fa-question-circle"
|
|
||||||
title="{% trans "The BDE membership is included in the WEI registration." %}"></i></dd>
|
|
||||||
{% endwith %}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if club.caution_amount > 0 %}
|
||||||
|
<dt class="col-xl-6">{% trans 'Caution amount'|capfirst %}</dt>
|
||||||
|
<dd class="col-xl-6">{{ club.caution_amount|pretty_money }}</dd>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if "note.view_note"|has_perm:club.note %}
|
{% if "note.view_note"|has_perm:club.note %}
|
||||||
<dt class="col-xl-6">{% trans 'balance'|capfirst %}</dt>
|
<dt class="col-xl-6">{% trans 'balance'|capfirst %}</dt>
|
||||||
<dd class="col-xl-6">{{ club.note.balance | pretty_money }}</dd>
|
<dd class="col-xl-6">{{ club.note.balance | pretty_money }}</dd>
|
||||||
|
@ -16,6 +16,10 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-footer text-center">
|
<div class="card-footer text-center">
|
||||||
|
{% if object.club %}
|
||||||
|
<a class="btn btn-primary btn-sm my-1" href="{% url 'member:club_detail' pk=object.club.pk %}"
|
||||||
|
data-turbolinks="false">{% trans "View club" %}</a>
|
||||||
|
{% endif %}
|
||||||
<a class="btn btn-primary btn-sm my-1" href="{% url 'wei:update_bus' pk=object.pk %}"
|
<a class="btn btn-primary btn-sm my-1" href="{% url 'wei:update_bus' pk=object.pk %}"
|
||||||
data-turbolinks="false">{% trans "Edit" %}</a>
|
data-turbolinks="false">{% trans "Edit" %}</a>
|
||||||
<a class="btn btn-primary btn-sm my-1" href="{% url 'wei:add_team' pk=object.pk %}"
|
<a class="btn btn-primary btn-sm my-1" href="{% url 'wei:add_team' pk=object.pk %}"
|
||||||
|
@ -18,6 +18,8 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
<div class="card-footer text-center">
|
<div class="card-footer text-center">
|
||||||
<a class="btn btn-primary btn-sm my-1" href="{% url 'wei:update_bus' pk=bus.pk %}"
|
<a class="btn btn-primary btn-sm my-1" href="{% url 'wei:update_bus' pk=bus.pk %}"
|
||||||
data-turbolinks="false">{% trans "Edit" %}</a>
|
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 %}"
|
<a class="btn btn-primary btn-sm my-1" href="{% url 'wei:add_team' pk=bus.pk %}"
|
||||||
data-turbolinks="false">{% trans "Add team" %}</a>
|
data-turbolinks="false">{% trans "Add team" %}</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,9 +13,17 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form method="post">
|
<form method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
{{ form.media }}
|
||||||
{{ form|crispy }}
|
{{ form|crispy }}
|
||||||
<button class="btn btn-primary" type="submit">{% trans "Submit" %}</button>
|
<button class="btn btn-primary" type="submit">{% trans "Submit" %}</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
if (window.jscolor && jscolor.install) {
|
||||||
|
jscolor.install();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -95,9 +95,11 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if can_validate_1a %}
|
{% if can_validate_1a %}
|
||||||
<a href="{% url 'wei:wei_1A_list' pk=object.pk %}" class="btn btn-block btn-info">{% trans "Attribute buses" %}</a>
|
<a href="{% url 'wei:wei_1A_list' pk=object.pk %}" class="btn btn-block btn-info">{% trans "Attribute buses" %}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block extrajavascript %}
|
{% block extrajavascript %}
|
||||||
|
@ -143,25 +143,35 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if registration.user.note.balance < fee %}
|
<div class="alert {% if registration.user.note.balance < fee %}alert-danger{% else %}alert-success{% endif %}">
|
||||||
<div class="alert alert-danger">
|
<h5>{% trans "Required payments:" %}</h5>
|
||||||
{% with pretty_fee=fee|pretty_money %}
|
<ul>
|
||||||
{% blocktrans trimmed with balance=registration.user.note.balance|pretty_money %}
|
<li>{% blocktrans trimmed with amount=fee|pretty_money %}
|
||||||
The note don't have enough money ({{ balance }}, {{ pretty_fee }} required).
|
Membership fees: {{ amount }}
|
||||||
The registration may fail if you don't credit the note now.
|
{% endblocktrans %}</li>
|
||||||
{% endblocktrans %}
|
{% if registration.caution_type == 'note' %}
|
||||||
{% endwith %}
|
<li>{% blocktrans trimmed with amount=club.caution_amount|pretty_money %}
|
||||||
</div>
|
Deposit (by Note transaction): {{ amount }}
|
||||||
{% else %}
|
{% endblocktrans %}</li>
|
||||||
<div class="alert alert-success">
|
<li><strong>{% blocktrans trimmed with total=total_needed|pretty_money %}
|
||||||
{% blocktrans trimmed with pretty_fee=fee|pretty_money %}
|
Total needed: {{ total }}
|
||||||
The note has enough money ({{ pretty_fee }} required), the registration is possible.
|
{% endblocktrans %}</strong></li>
|
||||||
{% endblocktrans %}
|
{% else %}
|
||||||
</div>
|
<li>{% blocktrans trimmed with amount=club.caution_amount|pretty_money %}
|
||||||
{% endif %}
|
Deposit (by check): {{ amount }}
|
||||||
|
{% endblocktrans %}</li>
|
||||||
|
<li><strong>{% blocktrans trimmed with total=fee|pretty_money %}
|
||||||
|
Total needed: {{ total }}
|
||||||
|
{% endblocktrans %}</strong></li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
<p>{% blocktrans trimmed with balance=registration.user.note.balance|pretty_money %}
|
||||||
|
Current balance: {{ balance }}
|
||||||
|
{% endblocktrans %}</p>
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if not registration.caution_check and not registration.first_year %}
|
{% if not registration.caution_check and not registration.first_year and registration.caution_type == 'check' %}
|
||||||
<div class="alert alert-danger">
|
<div class="alert alert-danger">
|
||||||
{% trans "The user didn't give her/his caution check." %}
|
{% trans "The user didn't give her/his caution check." %}
|
||||||
</div>
|
</div>
|
||||||
|
@ -126,6 +126,7 @@ class TestWEIRegistration(TestCase):
|
|||||||
year=self.year + 1,
|
year=self.year + 1,
|
||||||
date_start=str(self.year + 1) + "-09-01",
|
date_start=str(self.year + 1) + "-09-01",
|
||||||
date_end=str(self.year + 1) + "-09-03",
|
date_end=str(self.year + 1) + "-09-03",
|
||||||
|
caution_amount=12000,
|
||||||
))
|
))
|
||||||
qs = WEIClub.objects.filter(name="Create WEI Test", year=self.year + 1)
|
qs = WEIClub.objects.filter(name="Create WEI Test", year=self.year + 1)
|
||||||
self.assertTrue(qs.exists())
|
self.assertTrue(qs.exists())
|
||||||
@ -160,6 +161,7 @@ class TestWEIRegistration(TestCase):
|
|||||||
membership_end="2000-09-30",
|
membership_end="2000-09-30",
|
||||||
date_start="2000-09-01",
|
date_start="2000-09-01",
|
||||||
date_end="2000-09-03",
|
date_end="2000-09-03",
|
||||||
|
caution_amount=12000,
|
||||||
))
|
))
|
||||||
qs = WEIClub.objects.filter(name="Update WEI Test", id=self.wei.id)
|
qs = WEIClub.objects.filter(name="Update WEI Test", id=self.wei.id)
|
||||||
self.assertRedirects(response, reverse("wei:wei_detail", kwargs=dict(pk=self.wei.pk)), 302, 200)
|
self.assertRedirects(response, reverse("wei:wei_detail", kwargs=dict(pk=self.wei.pk)), 302, 200)
|
||||||
@ -318,6 +320,7 @@ class TestWEIRegistration(TestCase):
|
|||||||
bus=[],
|
bus=[],
|
||||||
team=[],
|
team=[],
|
||||||
roles=[],
|
roles=[],
|
||||||
|
caution_type='check'
|
||||||
))
|
))
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertFalse(response.context["membership_form"].is_valid())
|
self.assertFalse(response.context["membership_form"].is_valid())
|
||||||
@ -334,7 +337,8 @@ class TestWEIRegistration(TestCase):
|
|||||||
emergency_contact_phone='+33123456789',
|
emergency_contact_phone='+33123456789',
|
||||||
bus=[self.bus.id],
|
bus=[self.bus.id],
|
||||||
team=[self.team.id],
|
team=[self.team.id],
|
||||||
roles=[role.id for role in WEIRole.objects.filter(~Q(name="1A")).all()],
|
roles=[role.id for role in WEIRole.objects.filter(~Q(name="1A") & ~Q(name="GC WEI")).all()],
|
||||||
|
caution_type='check'
|
||||||
))
|
))
|
||||||
qs = WEIRegistration.objects.filter(user_id=user.id)
|
qs = WEIRegistration.objects.filter(user_id=user.id)
|
||||||
self.assertTrue(qs.exists())
|
self.assertTrue(qs.exists())
|
||||||
@ -354,6 +358,7 @@ class TestWEIRegistration(TestCase):
|
|||||||
bus=[self.bus.id],
|
bus=[self.bus.id],
|
||||||
team=[self.team.id],
|
team=[self.team.id],
|
||||||
roles=[role.id for role in WEIRole.objects.filter(~Q(name="1A")).all()],
|
roles=[role.id for role in WEIRole.objects.filter(~Q(name="1A")).all()],
|
||||||
|
caution_type='check'
|
||||||
))
|
))
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertTrue("This user is already registered to this WEI." in str(response.context["form"].errors))
|
self.assertTrue("This user is already registered to this WEI." in str(response.context["form"].errors))
|
||||||
@ -506,11 +511,12 @@ class TestWEIRegistration(TestCase):
|
|||||||
team=[self.team.id],
|
team=[self.team.id],
|
||||||
roles=[role.id for role in WEIRole.objects.filter(name="Adhérent⋅e WEI").all()],
|
roles=[role.id for role in WEIRole.objects.filter(name="Adhérent⋅e WEI").all()],
|
||||||
information_json=self.registration.information_json,
|
information_json=self.registration.information_json,
|
||||||
|
caution_type='check'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
qs = WEIRegistration.objects.filter(user_id=self.user.id, soge_credit=False, clothing_size="M")
|
qs = WEIRegistration.objects.filter(user_id=self.user.id, soge_credit=False, clothing_size="M")
|
||||||
self.assertTrue(qs.exists())
|
self.assertTrue(qs.exists())
|
||||||
self.assertRedirects(response, reverse("wei:validate_registration", kwargs=dict(pk=qs.get().pk)), 302, 200)
|
self.assertRedirects(response, reverse("wei:wei_detail", kwargs=dict(pk=qs.get().wei.pk)), 302, 200)
|
||||||
|
|
||||||
# Check the page when the registration is already validated
|
# Check the page when the registration is already validated
|
||||||
membership = WEIMembership(
|
membership = WEIMembership(
|
||||||
@ -560,11 +566,12 @@ class TestWEIRegistration(TestCase):
|
|||||||
team=[self.team.id],
|
team=[self.team.id],
|
||||||
roles=[role.id for role in WEIRole.objects.filter(name="Adhérent⋅e WEI").all()],
|
roles=[role.id for role in WEIRole.objects.filter(name="Adhérent⋅e WEI").all()],
|
||||||
information_json=self.registration.information_json,
|
information_json=self.registration.information_json,
|
||||||
|
caution_type='check'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
qs = WEIRegistration.objects.filter(user_id=self.user.id, clothing_size="L")
|
qs = WEIRegistration.objects.filter(user_id=self.user.id, clothing_size="L")
|
||||||
self.assertTrue(qs.exists())
|
self.assertTrue(qs.exists())
|
||||||
self.assertRedirects(response, reverse("wei:validate_registration", kwargs=dict(pk=qs.get().pk)), 302, 200)
|
self.assertRedirects(response, reverse("wei:wei_detail", kwargs=dict(pk=qs.get().wei.pk)), 302, 200)
|
||||||
|
|
||||||
# Test invalid form
|
# Test invalid form
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
@ -583,6 +590,7 @@ class TestWEIRegistration(TestCase):
|
|||||||
team=[],
|
team=[],
|
||||||
roles=[],
|
roles=[],
|
||||||
information_json=self.registration.information_json,
|
information_json=self.registration.information_json,
|
||||||
|
caution_type='check'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.assertFalse(response.context["membership_form"].is_valid())
|
self.assertFalse(response.context["membership_form"].is_valid())
|
||||||
@ -624,7 +632,7 @@ class TestWEIRegistration(TestCase):
|
|||||||
second_bus = Bus.objects.create(wei=self.wei, name="Second bus")
|
second_bus = Bus.objects.create(wei=self.wei, name="Second bus")
|
||||||
second_team = BusTeam.objects.create(bus=second_bus, name="Second team", color=42)
|
second_team = BusTeam.objects.create(bus=second_bus, name="Second team", color=42)
|
||||||
response = self.client.post(reverse("wei:validate_registration", kwargs=dict(pk=self.registration.pk)), dict(
|
response = self.client.post(reverse("wei:validate_registration", kwargs=dict(pk=self.registration.pk)), dict(
|
||||||
roles=[WEIRole.objects.get(name="GC WEI").id],
|
roles=[WEIRole.objects.get(name="Adhérent⋅e WEI").id],
|
||||||
bus=self.bus.pk,
|
bus=self.bus.pk,
|
||||||
team=second_team.pk,
|
team=second_team.pk,
|
||||||
credit_type=4, # Bank transfer
|
credit_type=4, # Bank transfer
|
||||||
@ -632,13 +640,14 @@ class TestWEIRegistration(TestCase):
|
|||||||
last_name="admin",
|
last_name="admin",
|
||||||
first_name="admin",
|
first_name="admin",
|
||||||
bank="Société générale",
|
bank="Société générale",
|
||||||
|
caution_check=True,
|
||||||
))
|
))
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertFalse(response.context["form"].is_valid())
|
self.assertFalse(response.context["form"].is_valid())
|
||||||
self.assertTrue("This team doesn't belong to the given bus." in str(response.context["form"].errors))
|
self.assertTrue("This team doesn't belong to the given bus." in str(response.context["form"].errors))
|
||||||
|
|
||||||
response = self.client.post(reverse("wei:validate_registration", kwargs=dict(pk=self.registration.pk)), dict(
|
response = self.client.post(reverse("wei:validate_registration", kwargs=dict(pk=self.registration.pk)), dict(
|
||||||
roles=[WEIRole.objects.get(name="GC WEI").id],
|
roles=[WEIRole.objects.get(name="Adhérent⋅e WEI").id],
|
||||||
bus=self.bus.pk,
|
bus=self.bus.pk,
|
||||||
team=self.team.pk,
|
team=self.team.pk,
|
||||||
credit_type=4, # Bank transfer
|
credit_type=4, # Bank transfer
|
||||||
@ -646,8 +655,10 @@ class TestWEIRegistration(TestCase):
|
|||||||
last_name="admin",
|
last_name="admin",
|
||||||
first_name="admin",
|
first_name="admin",
|
||||||
bank="Société générale",
|
bank="Société générale",
|
||||||
|
caution_check=True,
|
||||||
))
|
))
|
||||||
self.assertRedirects(response, reverse("wei:wei_registrations", kwargs=dict(pk=self.registration.wei.pk)), 302, 200)
|
self.assertRedirects(response, reverse("wei:wei_registrations", kwargs=dict(pk=self.registration.wei.pk)), 302, 200)
|
||||||
|
|
||||||
# Check if the membership is successfully created
|
# Check if the membership is successfully created
|
||||||
membership = WEIMembership.objects.filter(user_id=self.user.id, club=self.wei)
|
membership = WEIMembership.objects.filter(user_id=self.user.id, club=self.wei)
|
||||||
self.assertTrue(membership.exists())
|
self.assertTrue(membership.exists())
|
||||||
|
@ -4,16 +4,18 @@
|
|||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
from datetime import date, timedelta
|
from datetime import date
|
||||||
from tempfile import mkdtemp
|
from tempfile import mkdtemp
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.contrib import messages
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.db.models import Q, Count
|
from django.db.models import Q, Count
|
||||||
from django.db.models.functions.text import Lower
|
from django.db.models.functions.text import Lower
|
||||||
|
from django import forms
|
||||||
from django.http import HttpResponse, Http404
|
from django.http import HttpResponse, Http404
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
@ -33,7 +35,7 @@ from permission.views import ProtectQuerysetMixin, ProtectedCreateView
|
|||||||
|
|
||||||
from .forms.registration import WEIChooseBusForm
|
from .forms.registration import WEIChooseBusForm
|
||||||
from .models import WEIClub, WEIRegistration, WEIMembership, Bus, BusTeam, WEIRole
|
from .models import WEIClub, WEIRegistration, WEIMembership, Bus, BusTeam, WEIRole
|
||||||
from .forms import WEIForm, WEIRegistrationForm, BusForm, BusTeamForm, WEIMembership1AForm, \
|
from .forms import WEIForm, WEIRegistrationForm, WEIRegistration1AForm, WEIRegistration2AForm, BusForm, BusTeamForm, WEIMembership1AForm, \
|
||||||
WEIMembershipForm, CurrentSurvey
|
WEIMembershipForm, CurrentSurvey
|
||||||
from .tables import BusRepartitionTable, BusTable, BusTeamTable, WEITable, WEIRegistrationTable, \
|
from .tables import BusRepartitionTable, BusTable, BusTeamTable, WEITable, WEIRegistrationTable, \
|
||||||
WEIRegistration1ATable, WEIMembershipTable
|
WEIRegistration1ATable, WEIMembershipTable
|
||||||
@ -441,6 +443,10 @@ class BusTeamCreateView(ProtectQuerysetMixin, ProtectedCreateView):
|
|||||||
self.object.refresh_from_db()
|
self.object.refresh_from_db()
|
||||||
return reverse_lazy("wei:manage_bus_team", kwargs={"pk": self.object.pk})
|
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):
|
class BusTeamUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
||||||
"""
|
"""
|
||||||
@ -473,6 +479,10 @@ class BusTeamUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
|||||||
self.object.refresh_from_db()
|
self.object.refresh_from_db()
|
||||||
return reverse_lazy("wei:manage_bus_team", kwargs={"pk": self.object.pk})
|
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):
|
class BusTeamManageView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
|
||||||
"""
|
"""
|
||||||
@ -500,7 +510,7 @@ class WEIRegister1AView(ProtectQuerysetMixin, ProtectedCreateView):
|
|||||||
Register a new user to the WEI
|
Register a new user to the WEI
|
||||||
"""
|
"""
|
||||||
model = WEIRegistration
|
model = WEIRegistration
|
||||||
form_class = WEIRegistrationForm
|
form_class = WEIRegistration1AForm
|
||||||
extra_context = {"title": _("Register first year student to the WEI")}
|
extra_context = {"title": _("Register first year student to the WEI")}
|
||||||
|
|
||||||
def get_sample_object(self):
|
def get_sample_object(self):
|
||||||
@ -546,9 +556,17 @@ class WEIRegister1AView(ProtectQuerysetMixin, ProtectedCreateView):
|
|||||||
def get_form(self, form_class=None):
|
def get_form(self, form_class=None):
|
||||||
form = super().get_form(form_class)
|
form = super().get_form(form_class)
|
||||||
form.fields["user"].initial = self.request.user
|
form.fields["user"].initial = self.request.user
|
||||||
del form.fields["first_year"]
|
|
||||||
del form.fields["caution_check"]
|
# Cacher les champs pendant l'inscription initiale
|
||||||
del form.fields["information_json"]
|
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"]
|
||||||
|
if "caution_type" in form.fields:
|
||||||
|
del form.fields["caution_type"]
|
||||||
|
|
||||||
return form
|
return form
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
@ -586,7 +604,7 @@ class WEIRegister2AView(ProtectQuerysetMixin, ProtectedCreateView):
|
|||||||
Register an old user to the WEI
|
Register an old user to the WEI
|
||||||
"""
|
"""
|
||||||
model = WEIRegistration
|
model = WEIRegistration
|
||||||
form_class = WEIRegistrationForm
|
form_class = WEIRegistration2AForm
|
||||||
extra_context = {"title": _("Register old student to the WEI")}
|
extra_context = {"title": _("Register old student to the WEI")}
|
||||||
|
|
||||||
def get_sample_object(self):
|
def get_sample_object(self):
|
||||||
@ -644,9 +662,19 @@ class WEIRegister2AView(ProtectQuerysetMixin, ProtectedCreateView):
|
|||||||
form.fields["soge_credit"].disabled = True
|
form.fields["soge_credit"].disabled = True
|
||||||
form.fields["soge_credit"].help_text = _("You already opened an account in the Société générale.")
|
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
|
||||||
del form.fields["first_year"]
|
if "first_year" in form.fields:
|
||||||
del form.fields["information_json"]
|
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"]
|
||||||
|
|
||||||
|
# S'assurer que le champ caution_type est obligatoire
|
||||||
|
if "caution_type" in form.fields:
|
||||||
|
form.fields["caution_type"].required = True
|
||||||
|
form.fields["caution_type"].help_text = _("Choose how you want to pay the deposit")
|
||||||
|
form.fields["caution_type"].widget = forms.RadioSelect(choices=form.fields["caution_type"].choices)
|
||||||
|
|
||||||
return form
|
return form
|
||||||
|
|
||||||
@ -673,6 +701,9 @@ class WEIRegister2AView(ProtectQuerysetMixin, ProtectedCreateView):
|
|||||||
information["preferred_roles_pk"] = [role.pk for role in choose_bus_form.cleaned_data["roles"]]
|
information["preferred_roles_pk"] = [role.pk for role in choose_bus_form.cleaned_data["roles"]]
|
||||||
information["preferred_roles_name"] = [role.name for role in choose_bus_form.cleaned_data["roles"]]
|
information["preferred_roles_name"] = [role.name for role in choose_bus_form.cleaned_data["roles"]]
|
||||||
form.instance.information = information
|
form.instance.information = information
|
||||||
|
|
||||||
|
# Sauvegarder le type de caution
|
||||||
|
form.instance.caution_type = form.cleaned_data["caution_type"]
|
||||||
form.instance.save()
|
form.instance.save()
|
||||||
|
|
||||||
if 'treasury' in settings.INSTALLED_APPS:
|
if 'treasury' in settings.INSTALLED_APPS:
|
||||||
@ -702,11 +733,15 @@ class WEIUpdateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Update
|
|||||||
# We can't update a registration once the WEI is started and before the membership start date
|
# 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:
|
if today >= wei.date_start or today < wei.membership_start:
|
||||||
return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,)))
|
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)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
context["club"] = self.object.wei
|
context["club"] = self.object.wei
|
||||||
|
# Pass the validate parameter to the template
|
||||||
|
context["should_validate"] = self.should_validate
|
||||||
|
|
||||||
if self.object.is_validated:
|
if self.object.is_validated:
|
||||||
membership_form = self.get_membership_form(instance=self.object.membership,
|
membership_form = self.get_membership_form(instance=self.object.membership,
|
||||||
@ -740,6 +775,16 @@ class WEIUpdateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Update
|
|||||||
# The auto-json-format may cause issues with the default field remove
|
# 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):
|
if not PermissionBackend.check_perm(self.request, 'wei.change_weiregistration_information_json', self.object):
|
||||||
del form.fields["information_json"]
|
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"]
|
||||||
|
|
||||||
|
# S'assurer que le champ caution_type est obligatoire pour les 2A+
|
||||||
|
if not self.object.first_year and "caution_type" in form.fields:
|
||||||
|
form.fields["caution_type"].required = True
|
||||||
|
form.fields["caution_type"].help_text = _("Choose how you want to pay the deposit")
|
||||||
|
form.fields["caution_type"].widget = forms.RadioSelect(choices=form.fields["caution_type"].choices)
|
||||||
|
|
||||||
return form
|
return form
|
||||||
|
|
||||||
def get_membership_form(self, data=None, instance=None):
|
def get_membership_form(self, data=None, instance=None):
|
||||||
@ -759,10 +804,30 @@ class WEIUpdateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Update
|
|||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
# If the membership is already validated, then we update the bus and the team (and the roles)
|
# If the membership is already validated, then we update the bus and the team (and the roles)
|
||||||
if form.instance.is_validated:
|
if form.instance.is_validated:
|
||||||
membership_form = self.get_membership_form(self.request.POST, form.instance.membership)
|
try:
|
||||||
if not membership_form.is_valid():
|
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)
|
return self.form_invalid(form)
|
||||||
membership_form.save()
|
|
||||||
# If it is not validated and if this is an old member, then we update the choices
|
# 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(
|
elif not form.instance.first_year and PermissionBackend.check_perm(
|
||||||
self.request, "wei.change_weiregistration_information_json", self.object):
|
self.request, "wei.change_weiregistration_information_json", self.object):
|
||||||
@ -777,6 +842,10 @@ class WEIUpdateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Update
|
|||||||
information["preferred_roles_pk"] = [role.pk for role in choose_bus_form.cleaned_data["roles"]]
|
information["preferred_roles_pk"] = [role.pk for role in choose_bus_form.cleaned_data["roles"]]
|
||||||
information["preferred_roles_name"] = [role.name for role in choose_bus_form.cleaned_data["roles"]]
|
information["preferred_roles_name"] = [role.name for role in choose_bus_form.cleaned_data["roles"]]
|
||||||
form.instance.information = information
|
form.instance.information = information
|
||||||
|
|
||||||
|
# Sauvegarder le type de caution pour les 2A+
|
||||||
|
if "caution_type" in form.cleaned_data:
|
||||||
|
form.instance.caution_type = form.cleaned_data["caution_type"]
|
||||||
form.instance.save()
|
form.instance.save()
|
||||||
|
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
@ -787,14 +856,8 @@ class WEIUpdateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Update
|
|||||||
survey = CurrentSurvey(self.object)
|
survey = CurrentSurvey(self.object)
|
||||||
if not survey.is_complete():
|
if not survey.is_complete():
|
||||||
return reverse_lazy("wei:wei_survey", kwargs={"pk": self.object.pk})
|
return reverse_lazy("wei:wei_survey", kwargs={"pk": self.object.pk})
|
||||||
if PermissionBackend.check_perm(self.request, "wei.add_weimembership", WEIMembership(
|
# On redirige vers la validation uniquement si c'est explicitement demandé (et stocké dans la vue)
|
||||||
club=self.object.wei,
|
if self.should_validate and self.request.user.has_perm("wei.add_weimembership"):
|
||||||
user=self.object.user,
|
|
||||||
date_start=date.today(),
|
|
||||||
date_end=date.today(),
|
|
||||||
fee=0,
|
|
||||||
registration=self.object,
|
|
||||||
)):
|
|
||||||
return reverse_lazy("wei:validate_registration", kwargs={"pk": self.object.pk})
|
return reverse_lazy("wei:validate_registration", kwargs={"pk": self.object.pk})
|
||||||
return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.wei.pk})
|
return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.wei.pk})
|
||||||
|
|
||||||
@ -836,18 +899,23 @@ class WEIValidateRegistrationView(ProtectQuerysetMixin, ProtectedCreateView):
|
|||||||
extra_context = {"title": _("Validate WEI registration")}
|
extra_context = {"title": _("Validate WEI registration")}
|
||||||
|
|
||||||
def get_sample_object(self):
|
def get_sample_object(self):
|
||||||
|
"""
|
||||||
|
Return a sample object for permission checking
|
||||||
|
"""
|
||||||
registration = WEIRegistration.objects.get(pk=self.kwargs["pk"])
|
registration = WEIRegistration.objects.get(pk=self.kwargs["pk"])
|
||||||
return WEIMembership(
|
return WEIMembership(
|
||||||
club=registration.wei,
|
|
||||||
user=registration.user,
|
user=registration.user,
|
||||||
date_start=date.today(),
|
club=registration.wei,
|
||||||
date_end=date.today() + timedelta(days=1),
|
date_start=registration.wei.date_start,
|
||||||
fee=0,
|
fee=registration.wei.membership_fee_paid if registration.user.profile.paid else registration.wei.membership_fee_unpaid,
|
||||||
|
# Add any fields needed for proper permission checking
|
||||||
registration=registration,
|
registration=registration,
|
||||||
)
|
)
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
wei = WEIRegistration.objects.get(pk=self.kwargs["pk"]).wei
|
registration = WEIRegistration.objects.get(pk=self.kwargs["pk"])
|
||||||
|
|
||||||
|
wei = registration.wei
|
||||||
today = date.today()
|
today = date.today()
|
||||||
# We can't validate anyone once the WEI is started and before the membership start date
|
# 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:
|
if today >= wei.date_start or today < wei.membership_start:
|
||||||
@ -878,7 +946,14 @@ class WEIValidateRegistrationView(ProtectQuerysetMixin, ProtectedCreateView):
|
|||||||
date_start__gte=bde.membership_start,
|
date_start__gte=bde.membership_start,
|
||||||
).exists()
|
).exists()
|
||||||
|
|
||||||
context["fee"] = registration.fee
|
fee = registration.fee
|
||||||
|
context["fee"] = fee
|
||||||
|
|
||||||
|
# Calculer le montant total nécessaire (frais + caution si transaction)
|
||||||
|
total_needed = fee
|
||||||
|
if registration.caution_type == 'note':
|
||||||
|
total_needed += registration.wei.caution_amount
|
||||||
|
context["total_needed"] = total_needed
|
||||||
|
|
||||||
form = context["form"]
|
form = context["form"]
|
||||||
if registration.soge_credit:
|
if registration.soge_credit:
|
||||||
@ -890,7 +965,7 @@ class WEIValidateRegistrationView(ProtectQuerysetMixin, ProtectedCreateView):
|
|||||||
|
|
||||||
def get_form_class(self):
|
def get_form_class(self):
|
||||||
registration = WEIRegistration.objects.get(pk=self.kwargs["pk"])
|
registration = WEIRegistration.objects.get(pk=self.kwargs["pk"])
|
||||||
if registration.first_year and 'sleected_bus_pk' not in registration.information:
|
if registration.first_year and 'selected_bus_pk' not in registration.information:
|
||||||
return WEIMembership1AForm
|
return WEIMembership1AForm
|
||||||
return WEIMembershipForm
|
return WEIMembershipForm
|
||||||
|
|
||||||
@ -900,8 +975,24 @@ class WEIValidateRegistrationView(ProtectQuerysetMixin, ProtectedCreateView):
|
|||||||
form.fields["last_name"].initial = registration.user.last_name
|
form.fields["last_name"].initial = registration.user.last_name
|
||||||
form.fields["first_name"].initial = registration.user.first_name
|
form.fields["first_name"].initial = registration.user.first_name
|
||||||
|
|
||||||
if "caution_check" in form.fields:
|
# Ajouter le champ caution_check uniquement pour les non-première année et le rendre obligatoire
|
||||||
form.fields["caution_check"].initial = registration.caution_check
|
if not registration.first_year:
|
||||||
|
if registration.caution_type == 'check':
|
||||||
|
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")
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
form.fields["caution_check"] = forms.BooleanField(
|
||||||
|
required=True,
|
||||||
|
initial=False,
|
||||||
|
label=_("Create deposit transaction"),
|
||||||
|
help_text=_("A transaction of %(amount).2f€ will be created from the user's Note account") % {
|
||||||
|
'amount': registration.wei.caution_amount / 100
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
if registration.soge_credit:
|
if registration.soge_credit:
|
||||||
form.fields["credit_type"].disabled = True
|
form.fields["credit_type"].disabled = True
|
||||||
@ -985,10 +1076,20 @@ class WEIValidateRegistrationView(ProtectQuerysetMixin, ProtectedCreateView):
|
|||||||
if credit_type is None or registration.soge_credit:
|
if credit_type is None or registration.soge_credit:
|
||||||
credit_amount = 0
|
credit_amount = 0
|
||||||
|
|
||||||
if not registration.soge_credit and user.note.balance + credit_amount < fee:
|
# Calculer le montant total nécessaire (frais + caution si transaction)
|
||||||
# Users must have money before registering to the WEI.
|
total_needed = fee
|
||||||
|
if registration.caution_type == 'note':
|
||||||
|
total_needed += club.caution_amount
|
||||||
|
|
||||||
|
# Vérifier que l'utilisateur a assez d'argent pour tout payer
|
||||||
|
if not registration.soge_credit and user.note.balance + credit_amount < total_needed:
|
||||||
form.add_error('credit_type',
|
form.add_error('credit_type',
|
||||||
_("This user don't have enough money to join this club, and can't have a negative balance."))
|
_("This user doesn't have enough money to join this club and pay the deposit. "
|
||||||
|
"Current balance: %(balance)d€, credit: %(credit)d€, needed: %(needed)d€") % {
|
||||||
|
'balance': user.note.balance,
|
||||||
|
'credit': credit_amount,
|
||||||
|
'needed': total_needed}
|
||||||
|
)
|
||||||
return super().form_invalid(form)
|
return super().form_invalid(form)
|
||||||
|
|
||||||
if credit_amount:
|
if credit_amount:
|
||||||
@ -1028,6 +1129,18 @@ class WEIValidateRegistrationView(ProtectQuerysetMixin, ProtectedCreateView):
|
|||||||
membership.refresh_from_db()
|
membership.refresh_from_db()
|
||||||
membership.roles.add(WEIRole.objects.get(name="Adhérent⋅e WEI"))
|
membership.roles.add(WEIRole.objects.get(name="Adhérent⋅e WEI"))
|
||||||
|
|
||||||
|
# Créer la transaction de caution si nécessaire
|
||||||
|
if registration.caution_type == 'note':
|
||||||
|
from note.models import Transaction
|
||||||
|
Transaction.objects.create(
|
||||||
|
source=user.note,
|
||||||
|
destination=club.note,
|
||||||
|
quantity=1,
|
||||||
|
amount=club.caution_amount,
|
||||||
|
reason=_("Caution %(name)s") % {'name': club.name},
|
||||||
|
valid=True,
|
||||||
|
)
|
||||||
|
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
@ -1247,6 +1360,7 @@ class WEI1AListView(LoginRequiredMixin, ProtectQuerysetMixin, SingleTableView):
|
|||||||
def get_queryset(self, filter_permissions=True, **kwargs):
|
def get_queryset(self, filter_permissions=True, **kwargs):
|
||||||
qs = super().get_queryset(filter_permissions, **kwargs)
|
qs = super().get_queryset(filter_permissions, **kwargs)
|
||||||
qs = qs.filter(first_year=True, membership__isnull=False)
|
qs = qs.filter(first_year=True, membership__isnull=False)
|
||||||
|
qs = qs.filter(wei=self.club)
|
||||||
qs = qs.order_by('-membership__bus')
|
qs = qs.order_by('-membership__bus')
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
@ -1289,8 +1403,22 @@ class WEIAttributeBus1ANextView(LoginRequiredMixin, RedirectView):
|
|||||||
if not wei.exists():
|
if not wei.exists():
|
||||||
raise Http404
|
raise Http404
|
||||||
wei = wei.get()
|
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...
|
# On cherche d'abord les 1A qui ont une inscription validée (membership) mais pas de bus
|
||||||
if qs.exists():
|
qs = WEIRegistration.objects.filter(
|
||||||
return reverse_lazy('wei:wei_bus_1A', args=(qs.first().pk, ))
|
wei=wei,
|
||||||
return reverse_lazy('wei:wei_1A_list', args=(wei.pk, ))
|
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):
|
def format_value(self, value):
|
||||||
if value is None:
|
if value is None:
|
||||||
value = 0xFFFFFF
|
value = 0xFFFFFF
|
||||||
return "#{:06X}".format(value)
|
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):
|
def value_from_datadict(self, data, files, name):
|
||||||
val = super().value_from_datadict(data, files, name)
|
val = super().value_from_datadict(data, files, name)
|
||||||
return int(val[1:], 16)
|
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