Compare commits

..

116 commits

Author SHA1 Message Date
e1c9a4474d
fix(prepare_django): make the .static dir 2025-02-17 17:11:51 +01:00
e74e03d36b
doc(readme): adapt to settings refactor 2025-02-17 17:11:51 +01:00
c8dc0ca34e
doc(readme): missing depencies 2025-02-17 17:11:48 +01:00
982c82ba31 Merge pull request 'fix(kfet/promo): new subscribers may arrive in august' (#838) from Morpheus/gestioCOF:master into master
Reviewed-on: #838
2025-01-11 16:47:22 +01:00
531ba575c8 Update kfet/forms.py
Correction de l'assignation des promos
2025-01-11 16:46:31 +01:00
def9b68a90 Merge pull request 'django-apps' (#847) from django-apps into master
Reviewed-on: #847
2025-01-11 15:02:15 +01:00
7cd4338a3a
fix(cof_settings): Serve files at the right url 2025-01-11 14:39:49 +01:00
f5bfbddfbe
fix(bds_settings): Serve files at the right url 2025-01-11 14:16:13 +01:00
9e185c8cb5
feat: Refactor settings 2024-12-28 21:27:22 +01:00
b8c963779a
fix: shell.nix 2024-12-28 17:23:52 +01:00
57ff8fe131
chore: use Django LTS 2024-12-28 17:23:04 +01:00
0fdc1a2a46
fix(k-fet/accouts/new): reverse path at trigramme creation 2024-12-23 11:27:19 +01:00
aafbab29ff
chore: Finished version bump 2024-12-20 00:20:31 +01:00
fb66c064cd
chore: Partial version bump 2024-12-19 14:07:35 +01:00
2126224e15 Merge pull request 'Thubrecht/daphne' (#815) from thubrecht/daphne into master
Reviewed-on: #815
2024-07-30 18:40:56 +02:00
d6109a9312 dev: update requirements and directly read the files 2024-07-12 14:54:14 +02:00
a69bd0426f kfet/open: Add comment to test 2024-07-12 14:54:14 +02:00
81a4dbef7c dev: set explicitely DJANGO_SETTINGS_MODULE 2024-07-12 14:54:14 +02:00
4fedf3453d kfet: remove redundant static tag 2024-07-12 14:54:14 +02:00
8607d77c84 dev: update requirements 2024-07-12 14:54:14 +02:00
bc55a3067e Remove useless migrations 2024-07-12 14:54:14 +02:00
dd68ad91cd Update django-hCaptcha 2024-07-12 14:54:14 +02:00
2f71246509 assertDictContainsSubset is deprecated 2024-07-12 14:54:14 +02:00
a20a1c11d6 Explicitely set transform=repr in assertQuerysetEquals 2024-07-12 14:54:14 +02:00
0e1ff1765a assertEquals is deprecated 2024-07-12 14:54:14 +02:00
177d413f4c Use AutoField instead of BigAutoField 2024-07-12 14:54:14 +02:00
01dd16c795 url -> re_path 2024-07-12 14:54:14 +02:00
84c87c1b4b Replace unique_together by UniqueConstraint 2024-07-12 14:54:14 +02:00
1b143b322f Update changelog 2024-07-12 14:54:14 +02:00
f9456e3c29 cof has been renamed to gestioasso 2024-07-12 14:54:14 +02:00
dd1350f1c2 Fix typo 2024-07-12 14:54:14 +02:00
8f4cb68d31 Only run kf tests in sequential mode (to fix issues with channels) 2024-07-12 14:54:14 +02:00
3a3f96a8df Try not running tests in parallel 2024-07-12 14:54:14 +02:00
7d8926e459 Try to flush old messages in tests 2024-07-12 14:54:14 +02:00
3fee014384 Update kfet.open tests 2024-07-12 14:54:14 +02:00
cd351786bb Remove default_app_config 2024-07-12 14:54:14 +02:00
7362c2fa2a Update django-djconfig 2024-07-12 14:54:14 +02:00
efbc947145 Change backend name as the old one is deprecated 2024-07-12 14:54:14 +02:00
0c45262fbc ugettext -> gettext 2024-07-12 14:54:14 +02:00
cabd277b4a Update redis, and implement a custom channel layer to send datetime/decimal objects 2024-07-12 14:54:14 +02:00
4108efe8c9 Fix kfet.ope tests 2024-07-12 14:54:14 +02:00
693e4252d5 Fix kpsul tests 2024-07-12 14:54:14 +02:00
3aa928e8f0 Simplify group_send for kpsul 2024-07-12 14:54:14 +02:00
5e2e68960b Channels 3 2024-07-12 14:54:14 +02:00
91e9beee11 Add default django asgi handler 2024-07-12 14:54:14 +02:00
ac286209ed Fix app import 2024-07-12 14:54:14 +02:00
b03cda5962 keyOrder is deprecated, using a list in Meta gives the correct order 2024-07-12 14:54:14 +02:00
4feb567af7 Update django-redis-cache and fix vagrant setup 2024-07-12 14:54:14 +02:00
1ac47885d0 Update django version 2024-07-12 14:54:14 +02:00
071c810605 Update base consumers 2024-07-12 14:54:14 +02:00
7f00ce0ff1 Add default http router 2024-07-12 14:54:14 +02:00
95136cb4eb Update daphne version 2024-07-12 14:54:14 +02:00
e299997aa8 Update to django channels 2 2024-07-12 14:54:14 +02:00
40f34926bb Fix vagrant setup w/ daphne 2024-07-12 14:54:14 +02:00
69976a878a Merge pull request 'Envoi de mail lors de la création d'un trigramme' (#833) from agroudiev/mail-creation-trigramme into master
Reviewed-on: #833
2024-07-06 16:54:25 +02:00
6621ae3950 style(kfet): suppression de return 2024-07-06 16:49:35 +02:00
9288daaf9e feat(kfet): envoi de mail lors de la création d'un trigramme 2024-07-06 12:14:49 +02:00
e92c500940 feat(shell.nix): Switch to python 3.9 2024-02-11 19:59:29 +01:00
Tom Hubrecht
d75eaf583f Merge branch 'master' into 'master'
Modification du délai pour l'indicateur K-Fêt ouverte

See merge request klub-dev-ens/gestioCOF!529
2023-12-10 10:11:33 +01:00
55bd3ab51d
Modification du délai du websocket 2023-12-08 21:17:53 +01:00
Tom Hubrecht
f640a25f59 Merge branch 'petitcours-template-tweak' into 'master'
[petitcours] Tweak `eleve.txt` template

See merge request klub-dev-ens/gestioCOF!528
2023-10-03 15:20:40 +02:00
Leo Lanteri--Thauvin
f881c7cd8b [petitcours] Tweak eleve.txt template 2023-09-11 16:44:45 +02:00
b548b87c25 Version 0.15.1 et Changelog 2023-06-15 13:52:53 +02:00
Tom Hubrecht
a72302291f Merge branch 'send_neg' into 'master'
feat(kfet): Change l'adresse utilisée pour envoyer les mails de négatif

See merge request klub-dev-ens/gestioCOF!526
2023-06-15 13:33:44 +02:00
a0bde75f50 feat(kfet): Change l'adresse utilisée pour envoyer les mails de négatif 2023-06-15 13:03:54 +02:00
Tom Hubrecht
44b19c12e5 Merge branch 'send_neg' into 'master'
fix(kfet): Récupère lors d'une erreur due à smtplib

See merge request klub-dev-ens/gestioCOF!525
2023-06-15 10:48:23 +02:00
f97d339a1c fix(kfet): Récupère lors d'une erreur due à smtplib 2023-06-14 20:56:25 +02:00
Tom Hubrecht
094116e88d Merge branch 'thubrecht/date-adhesion' into 'master'
Rajout de la date d'adhésion sur les profils COF

Closes #303

See merge request klub-dev-ens/gestioCOF!521
2023-05-26 09:31:45 +02:00
b32a07fc22 Version 0.15 et mise à jour du Changelog 2023-05-22 20:42:23 +02:00
Tom Hubrecht
4fc9902cf6 Merge branch 'thubrecht/contact-soiree' into 'master'
feat(kfet): Ajout d'un formulaire de demande de soirée

See merge request klub-dev-ens/gestioCOF!523
2023-05-22 20:37:38 +02:00
7164cfa37a feat(kfet): Ajout d'un formulaire de demande de soirée 2023-05-22 20:30:05 +02:00
Tom Hubrecht
90f96fb5c9 Merge branch 'thubrecht/contact' into 'master'
feat(kfet): Ajoute un formulaire de contact

Closes #302

See merge request klub-dev-ens/gestioCOF!520
2023-05-22 19:06:26 +02:00
e50249355d feat(kfet): Ajoute un formulaire de contact 2023-05-22 18:59:46 +02:00
Tom Hubrecht
c304d734d9 Merge branch 'thubrecht/comptes-inactifs' into 'master'
feat(kfet): Désactive l'envoi des mails pour les comptes gelés

See merge request klub-dev-ens/gestioCOF!522
2023-05-22 18:34:51 +02:00
c36dd30bce fix(kfet): Affiche la bonne information 2023-05-22 18:26:24 +02:00
2571cc955e feat(kfet): Désactive l'envoi des mails pour les comptes gelés
On utilise la fonctionnalité `is_frozen` pour marquer les comptes qui n'ont plus d'adresse valide, et on répare le formulaire de màj de compte.
2023-05-22 18:23:50 +02:00
3eaac5c68f feat(cof): Rajoute la date d'adhésion dans les profils 2023-05-22 11:28:23 +02:00
af4c8e0744 Update shell.nix and use django-types 2023-05-22 10:57:11 +02:00
14e0a3ef0a Version 0.14 et mise à jour du changelog 2023-05-19 20:18:11 +02:00
Tom Hubrecht
83078d4726 Merge branch 'thubrecht/date-js' into 'master'
Thubrecht/date js

See merge request klub-dev-ens/gestioCOF!518
2023-05-19 17:34:27 +02:00
cb262ad479 fix(kfet): Update timezone data for moment.js 2023-05-19 16:45:15 +02:00
5c47118834 Update gitignore and shell.nix 2023-05-19 15:14:55 +02:00
30e842ce80 shell.nix: Update to use virtualenv 2023-05-19 14:59:19 +02:00
892bf51163 Run black on all files 2023-05-19 14:57:48 +02:00
e20d7ca6c2 requirements: Fix required versions 2023-05-19 14:43:25 +02:00
Tom Hubrecht
1b09293206 Version 0.13 && Update changelog 2023-02-19 10:32:47 +01:00
Tom Hubrecht
e7da476697 Merge branch 'thubrecht/surnom' into 'master'
Rend le surnom lisible par la personne

Closes #297

See merge request klub-dev-ens/gestioCOF!506
2023-01-31 17:06:28 +01:00
Tom Hubrecht
761ab6df90 Merge branch '_aandres/inventory_sum_amounts' into 'master'
Affiche les montants des valeurs des stocks sur l'affichage d'un inventaire

See merge request klub-dev-ens/gestioCOF!515
2023-01-28 15:34:56 +01:00
Tom Hubrecht
a8d4035d33 Merge branch 'thubrecht/rappels_negatifs' into 'master'
On n'envoie des mails de rappel que lorsque le négatif est toujours d'actualité

Closes #298

See merge request klub-dev-ens/gestioCOF!509
2023-01-28 15:33:23 +01:00
b80426c56f feat(kfet): message info about prices 2023-01-28 15:28:54 +01:00
429e611daa feat(kfet): more values and formatting 2023-01-28 15:28:54 +01:00
Tom Hubrecht
5160da7862 Merge branch '292_fix_cancel_js' into 'master'
fix(kfet): fix js error when cancelling already canceled operation

Closes #292

See merge request klub-dev-ens/gestioCOF!516
2023-01-28 15:20:53 +01:00
aad3775222 fix(kfet): fix js error when cancelling already canceled operation 2023-01-28 15:13:55 +01:00
4b92716092 feat: poc inventory amount value
and lint
2023-01-23 21:53:46 +01:00
dfa5b4bf69 changelog: add current date 2022-10-03 18:37:41 +02:00
Tom Hubrecht
1be5dcb6af Merge branch 'thubrecht/kfetcms-css' into 'master'
kfetcms: Update the fixtures and fix the navbar behaviour due to a longer menu

See merge request klub-dev-ens/gestioCOF!513
2022-10-03 10:54:37 +02:00
a891ec56a6 dev: add nixos setup 2022-10-03 10:34:06 +02:00
7a52690a63 kfet: fix pipeline 2022-10-03 10:33:29 +02:00
a2f396ce7a Changelog: Update 2022-10-03 10:33:04 +02:00
85e30056a6 kfetcms: Update the fixtures and fix the navbar behaviour due to a longer menu 2022-10-03 10:22:32 +02:00
Tom Hubrecht
69de48f285 Version 0.12 2022-06-17 21:45:34 +02:00
Tom Hubrecht
eba36f2712 Merge branch 'dodo/kfet-history-limit-exceptions' into 'master'
Dodo/kfet history limit exceptions

See merge request klub-dev-ens/gestioCOF!508
2022-05-20 12:08:59 +02:00
Dorian Lesbre
bfdb34aae7 Dodo/kfet history limit exceptions 2022-05-20 12:08:59 +02:00
fcf2002cd7 On n'affiche le négatif que s'il existe vraiment 2022-01-11 18:10:00 +01:00
b236d6a950 Si last_rappel vaut None il n'est pas inclus dans le __lt 2022-01-11 18:10:00 +01:00
4b29097f02 On sauvegarde la date de fin du négatif 2022-01-11 18:10:00 +01:00
87f383bef1 On n'envoie des mails de rappel que lorsque le négatif est toujours d'actualité 2022-01-11 18:10:00 +01:00
Tom Hubrecht
1ad025e046 Merge branch 'dodo/fix_stat_labels' into 'master'
Dodo/fix stat labels

Closes #296

See merge request klub-dev-ens/gestioCOF!510
2022-01-07 11:07:51 +01:00
Dorian Lesbre
b3c047738a Ajout accent K-Fêt 2022-01-06 16:00:26 +01:00
Dorian Lesbre
17a9ae3302 Update CHANGELOG 2022-01-05 10:50:45 +01:00
Dorian Lesbre
e41bcbb6d7 Removed duplicate import to please flake8 2022-01-05 10:48:04 +01:00
Dorian Lesbre
e384bfb0f3 Fix issue #296 2022-01-05 10:45:32 +01:00
373ff1f62c Rend le surnom lisible par la personne 2021-11-25 14:44:40 +01:00
Martin Pepin
65eb95a3c9 Merge branch 'thubrecht/bds-membres' into 'master'
Réinitialisation des adhésions

Closes #294

See merge request klub-dev-ens/gestioCOF!503
2021-10-27 14:33:18 +02:00
1b8dd971b0 Ajoute un mécanisme de réinitialisation des adhésions 2021-10-26 10:26:22 +02:00
713d686047 Corrige l'affichage de la date dans le formulaire 2021-10-26 09:24:44 +02:00
282 changed files with 3291 additions and 1091 deletions

View file

@ -0,0 +1 @@
0x0000000000000000000000000000000000000000

View file

@ -0,0 +1 @@
10000000-ffff-ffff-ffff-000000000001

View file

@ -0,0 +1 @@
k-feste_token

1
.credentials/SECRET_KEY Normal file
View file

@ -0,0 +1 @@
insecure-key

1
.envrc Normal file
View file

@ -0,0 +1 @@
use nix

4
.gitignore vendored
View file

@ -5,6 +5,7 @@ cof/settings.py
settings.py settings.py
*~ *~
venv/ venv/
.venv/
.vagrant .vagrant
/src /src
media/ media/
@ -18,4 +19,5 @@ media/
.cache .cache
# VSCode # VSCode
.vscode/ .vscode/
.direnv

View file

@ -43,13 +43,21 @@ variables:
# Keep this disabled for now, as it may kill GitLab... # Keep this disabled for now, as it may kill GitLab...
# coverage: '/TOTAL.*\s(\d+\.\d+)\%$/' # coverage: '/TOTAL.*\s(\d+\.\d+)\%$/'
kfettest:
stage: test
extends: .test_template
variables:
DJANGO_SETTINGS_MODULE: "gestioasso.settings.cof_prod"
script:
- coverage run manage.py test kfet
coftest: coftest:
stage: test stage: test
extends: .test_template extends: .test_template
variables: variables:
DJANGO_SETTINGS_MODULE: "gestioasso.settings.cof_prod" DJANGO_SETTINGS_MODULE: "gestioasso.settings.cof_prod"
script: script:
- coverage run manage.py test gestioncof bda kfet petitscours shared --parallel - coverage run manage.py test gestioncof bda petitscours shared --parallel
bdstest: bdstest:
stage: test stage: test

View file

@ -23,8 +23,60 @@ adhérents ni des cotisations.
## TODO Prod ## TODO Prod
- Lancer `python manage.py update_translation_fields` après la migration
- Mettre à jour les units systemd `daphne.service` et `worker.service`
- Créer un compte hCaptcha (https://www.hcaptcha.com/), au COF, et remplacer les secrets associés - Créer un compte hCaptcha (https://www.hcaptcha.com/), au COF, et remplacer les secrets associés
## Version ??? - ??/??/????
## Version 0.15.1 - 15/06/2023
### K-Fêt
- Rattrape les erreurs d'envoi de mail de négatif
- Utilise l'adresse chefs pour les envois de négatifs
## Version 0.15 - 22/05/2023
### K-Fêt
- Rajoute un formulaire de contact
- Rajoute un formulaire de demande de soirée
- Désactive les mails d'envoi de négatifs sur les comptes gelés
## Version 0.14 - 19/05/2023
- Répare les dépendances en spécifiant toutes les versions
### K-Fêt
- Répare la gestion des changement d'heure via moment.js
## Version 0.13 - 19/02/2023
### K-Fêt
- Rajoute la valeur des inventaires
- Résout les problèmes de négatif ne disparaissant pas
- Affiche son surnom s'il y en a un
- Bugfixes
## Version 0.12.1 - 03/10/2022
### K-Fêt
- Fixe un problème de rendu causé par l'agrandissement du menu
- Mise à jour vers Channels 3.x et Django 3.2
## Version 0.12 - 17/06/2022
### K-Fêt
- Ajoute une exception à la limite d'historique pour les comptes `LIQ` et `#13`
- Répare le problème des étiquettes LIQ/Comptes K-Fêt inversées dans les stats des articles K-Fêt
## Version 0.11 - 26/10/2021 ## Version 0.11 - 26/10/2021
### COF ### COF

View file

@ -18,7 +18,7 @@ Il vous faudra installer pip, les librairies de développement de python ainsi
que sqlite3, un moteur de base de données léger et simple d'utilisation. Sous que sqlite3, un moteur de base de données léger et simple d'utilisation. Sous
Debian et dérivées (Ubuntu, ...) : Debian et dérivées (Ubuntu, ...) :
sudo apt-get install python3-pip python3-dev python3-venv sqlite3 sudo apt-get install python3-pip python3-dev python3-venv sqlite3 libsasl2-dev python-dev-is-python3 libldap2-dev libssl-dev
Si vous décidez d'utiliser un environnement virtuel Python (virtualenv; Si vous décidez d'utiliser un environnement virtuel Python (virtualenv;
fortement conseillé), déplacez-vous dans le dossier où est installé GestioCOF fortement conseillé), déplacez-vous dans le dossier où est installé GestioCOF
@ -30,7 +30,15 @@ Pour l'activer, il faut taper
. venv/bin/activate . venv/bin/activate
depuis le même dossier. depuis le même dossier. Pour préparer l'environnement à l'utilisation de `./manage.py`
(qui permet de faire des tests en local), il faut également taper
export CREDENTIALS_DIRECTORY=$(realpath .credentials)
export DJANGO_SETTINGS_MODULE=gestioasso.settings.local
export GESTIOCOF_DEBUG=true
export GESTIOCOF_STATIC_ROOT=$(realpath .static)
export GESTIOBDS_DEBUG=true
export GESTIOBDS_STATIC_ROOT=$(realpath .static)
Vous pouvez maintenant installer les dépendances Python depuis le fichier Vous pouvez maintenant installer les dépendances Python depuis le fichier
`requirements-devel.txt` : `requirements-devel.txt` :

View file

@ -211,7 +211,6 @@ class AttributionAdminForm(forms.ModelForm):
class AttributionAdmin(ReadOnlyMixin, admin.ModelAdmin): class AttributionAdmin(ReadOnlyMixin, admin.ModelAdmin):
list_display = ("id", "spectacle", "participant", "given", "paid") list_display = ("id", "spectacle", "participant", "given", "paid")
search_fields = ( search_fields = (
"spectacle__title", "spectacle__title",

View file

@ -2,7 +2,6 @@ import random
class Algorithm(object): class Algorithm(object):
shows = None shows = None
ranks = None ranks = None
origranks = None origranks = None

View file

@ -81,7 +81,7 @@ class Command(MyBaseCommand):
shows = random.sample( shows = random.sample(
list(tirage.spectacle_set.all()), tirage.spectacle_set.count() // 2 list(tirage.spectacle_set.all()), tirage.spectacle_set.count() // 2
) )
for (rank, show) in enumerate(shows): for rank, show in enumerate(shows):
choices.append( choices.append(
ChoixSpectacle( ChoixSpectacle(
participant=part, participant=part,

View file

@ -6,7 +6,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [migrations.swappable_dependency(settings.AUTH_USER_MODEL)] dependencies = [migrations.swappable_dependency(settings.AUTH_USER_MODEL)]
operations = [ operations = [

View file

@ -35,7 +35,6 @@ def fill_tirage_fields(apps, schema_editor):
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("bda", "0001_initial")] dependencies = [("bda", "0001_initial")]
operations = [ operations = [

View file

@ -5,7 +5,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("bda", "0002_add_tirage")] dependencies = [("bda", "0002_add_tirage")]
operations = [ operations = [

View file

@ -5,7 +5,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("bda", "0003_update_tirage_and_spectacle")] dependencies = [("bda", "0003_update_tirage_and_spectacle")]
operations = [ operations = [

View file

@ -5,7 +5,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("bda", "0004_mails-rappel")] dependencies = [("bda", "0004_mails-rappel")]
operations = [ operations = [

View file

@ -18,7 +18,6 @@ def forwards_func(apps, schema_editor):
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("bda", "0005_encoding")] dependencies = [("bda", "0005_encoding")]
operations = [ operations = [

View file

@ -5,7 +5,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("bda", "0006_add_tirage_switch")] dependencies = [("bda", "0006_add_tirage_switch")]
operations = [ operations = [

View file

@ -5,7 +5,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("bda", "0007_extends_spectacle")] dependencies = [("bda", "0007_extends_spectacle")]
operations = [ operations = [

View file

@ -6,7 +6,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("bda", "0008_py3")] dependencies = [("bda", "0008_py3")]
operations = [ operations = [

View file

@ -21,7 +21,6 @@ def forwards_func(apps, schema_editor):
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("bda", "0009_revente")] dependencies = [("bda", "0009_revente")]
operations = [ operations = [

View file

@ -5,7 +5,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("bda", "0010_spectaclerevente_shotgun")] dependencies = [("bda", "0010_spectaclerevente_shotgun")]
operations = [ operations = [

View file

@ -5,7 +5,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("bda", "0011_tirage_appear_catalogue")] dependencies = [("bda", "0011_tirage_appear_catalogue")]
operations = [ operations = [

View file

@ -13,7 +13,6 @@ def swap_double_choice(apps, schema_editor):
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("bda", "0011_tirage_appear_catalogue")] dependencies = [("bda", "0011_tirage_appear_catalogue")]
operations = [ operations = [

View file

@ -6,7 +6,6 @@ from django.db import migrations
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("bda", "0012_notif_time"), ("bda", "0012_swap_double_choice")] dependencies = [("bda", "0012_notif_time"), ("bda", "0012_swap_double_choice")]
operations = [] operations = []

View file

@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("bda", "0013_merge_20180524_2123")] dependencies = [("bda", "0013_merge_20180524_2123")]
operations = [ operations = [

View file

@ -29,7 +29,6 @@ def set_participant_payment(apps, schema_editor):
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("bda", "0014_attribution_paid_field")] dependencies = [("bda", "0014_attribution_paid_field")]
operations = [ operations = [

View file

@ -4,7 +4,6 @@ from django.db import migrations
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("bda", "0015_move_bda_payment")] dependencies = [("bda", "0015_move_bda_payment")]
operations = [ operations = [

View file

@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("bda", "0016_delete_participant_paid")] dependencies = [("bda", "0016_delete_participant_paid")]
operations = [ operations = [

View file

@ -5,7 +5,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("bda", "0017_participant_accepte_charte"), ("bda", "0017_participant_accepte_charte"),
] ]

View file

@ -0,0 +1,23 @@
# Generated by Django 3.2.13 on 2022-06-30 10:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bda", "0018_auto_20201021_1818"),
]
operations = [
migrations.AlterUniqueTogether(
name="choixspectacle",
unique_together=set(),
),
migrations.AddConstraint(
model_name="choixspectacle",
constraint=models.UniqueConstraint(
fields=("participant", "spectacle"), name="unique_participation"
),
),
]

View file

@ -253,7 +253,11 @@ class ChoixSpectacle(models.Model):
class Meta: class Meta:
ordering = ("priority",) ordering = ("priority",)
unique_together = (("participant", "spectacle"),) constraints = [
models.UniqueConstraint(
fields=["participant", "spectacle"], name="unique_participation"
)
]
verbose_name = "voeu" verbose_name = "voeu"
verbose_name_plural = "voeux" verbose_name_plural = "voeux"

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %} {% extends "base_title.html" %}
{% load staticfiles %} {% load static %}
{% block extra_head %} {% block extra_head %}
<link type="text/css" rel="stylesheet" href="{% static "bda/css/bda.css" %}" /> <link type="text/css" rel="stylesheet" href="{% static "bda/css/bda.css" %}" />

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %} {% extends "base_title.html" %}
{% load staticfiles %} {% load static %}
{% block realcontent %} {% block realcontent %}
<h2>État des inscriptions BdA</h2> <h2>État des inscriptions BdA</h2>

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %} {% extends "base_title.html" %}
{% load staticfiles %} {% load static %}
{% block extra_head %} {% block extra_head %}
<script type="text/javascript" src="{% static 'vendor/jquery/jquery-ui.min.js' %}" ></script> <script type="text/javascript" src="{% static 'vendor/jquery/jquery-ui.min.js' %}" ></script>

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %} {% extends "base_title.html" %}
{% load staticfiles %} {% load static %}
{% block realcontent %} {% block realcontent %}
<h2>{{ spectacle }}</h2> <h2>{{ spectacle }}</h2>

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %} {% extends "base_title.html" %}
{% load staticfiles %} {% load static %}
{%block realcontent %} {%block realcontent %}

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %} {% extends "base_title.html" %}
{% load staticfiles %} {% load static %}
{% block realcontent %} {% block realcontent %}
<h2>Inscription à une revente</h2> <h2>Inscription à une revente</h2>

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %} {% extends "base_title.html" %}
{% load staticfiles %} {% load static %}
{% block realcontent %} {% block realcontent %}

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %} {% extends "base_title.html" %}
{% load staticfiles %} {% load static %}
{% block realcontent %} {% block realcontent %}

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %} {% extends "base_title.html" %}
{% load staticfiles%} {% load static %}
{% block realcontent %} {% block realcontent %}
<h2>Inscriptions pour BdA-Revente</h2> <h2>Inscriptions pour BdA-Revente</h2>

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %} {% extends "base_title.html" %}
{% load staticfiles %} {% load static %}
{% block realcontent %} {% block realcontent %}

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %} {% extends "base_title.html" %}
{% load staticfiles %} {% load static %}
{% block extra_head %} {% block extra_head %}
<link type="text/css" rel="stylesheet" href="{% static "bda/css/bda.css" %}" /> <link type="text/css" rel="stylesheet" href="{% static "bda/css/bda.css" %}" />

View file

@ -1,74 +1,80 @@
from django.conf.urls import url from django.urls import re_path
from bda import views from bda import views
from bda.views import SpectacleListView from bda.views import SpectacleListView
from gestioncof.decorators import buro_required from gestioncof.decorators import buro_required
urlpatterns = [ urlpatterns = [
url( re_path(
r"^inscription/(?P<tirage_id>\d+)$", r"^inscription/(?P<tirage_id>\d+)$",
views.inscription, views.inscription,
name="bda-tirage-inscription", name="bda-tirage-inscription",
), ),
url(r"^places/(?P<tirage_id>\d+)$", views.places, name="bda-places-attribuees"), re_path(r"^places/(?P<tirage_id>\d+)$", views.places, name="bda-places-attribuees"),
url(r"^etat-places/(?P<tirage_id>\d+)$", views.etat_places, name="bda-etat-places"), re_path(
url(r"^tirage/(?P<tirage_id>\d+)$", views.tirage, name="bda-tirage"), r"^etat-places/(?P<tirage_id>\d+)$", views.etat_places, name="bda-etat-places"
url( ),
re_path(r"^tirage/(?P<tirage_id>\d+)$", views.tirage, name="bda-tirage"),
re_path(
r"^spectacles/(?P<tirage_id>\d+)$", r"^spectacles/(?P<tirage_id>\d+)$",
buro_required(SpectacleListView.as_view()), buro_required(SpectacleListView.as_view()),
name="bda-liste-spectacles", name="bda-liste-spectacles",
), ),
url( re_path(
r"^spectacles/(?P<tirage_id>\d+)/(?P<spectacle_id>\d+)$", r"^spectacles/(?P<tirage_id>\d+)/(?P<spectacle_id>\d+)$",
views.spectacle, views.spectacle,
name="bda-spectacle", name="bda-spectacle",
), ),
url( re_path(
r"^spectacles/unpaid/(?P<tirage_id>\d+)$", r"^spectacles/unpaid/(?P<tirage_id>\d+)$",
views.UnpaidParticipants.as_view(), views.UnpaidParticipants.as_view(),
name="bda-unpaid", name="bda-unpaid",
), ),
url( re_path(
r"^spectacles/autocomplete$", r"^spectacles/autocomplete$",
views.spectacle_autocomplete, views.spectacle_autocomplete,
name="bda-spectacle-autocomplete", name="bda-spectacle-autocomplete",
), ),
url( re_path(
r"^participants/autocomplete$", r"^participants/autocomplete$",
views.participant_autocomplete, views.participant_autocomplete,
name="bda-participant-autocomplete", name="bda-participant-autocomplete",
), ),
# Urls BdA-Revente # Urls BdA-Revente
url( re_path(
r"^revente/(?P<tirage_id>\d+)/manage$", r"^revente/(?P<tirage_id>\d+)/manage$",
views.revente_manage, views.revente_manage,
name="bda-revente-manage", name="bda-revente-manage",
), ),
url( re_path(
r"^revente/(?P<tirage_id>\d+)/subscribe$", r"^revente/(?P<tirage_id>\d+)/subscribe$",
views.revente_subscribe, views.revente_subscribe,
name="bda-revente-subscribe", name="bda-revente-subscribe",
), ),
url( re_path(
r"^revente/(?P<tirage_id>\d+)/tirages$", r"^revente/(?P<tirage_id>\d+)/tirages$",
views.revente_tirages, views.revente_tirages,
name="bda-revente-tirages", name="bda-revente-tirages",
), ),
url( re_path(
r"^revente/(?P<spectacle_id>\d+)/buy$", r"^revente/(?P<spectacle_id>\d+)/buy$",
views.revente_buy, views.revente_buy,
name="bda-revente-buy", name="bda-revente-buy",
), ),
url( re_path(
r"^revente/(?P<revente_id>\d+)/confirm$", r"^revente/(?P<revente_id>\d+)/confirm$",
views.revente_confirm, views.revente_confirm,
name="bda-revente-confirm", name="bda-revente-confirm",
), ),
url( re_path(
r"^revente/(?P<tirage_id>\d+)/shotgun$", r"^revente/(?P<tirage_id>\d+)/shotgun$",
views.revente_shotgun, views.revente_shotgun,
name="bda-revente-shotgun", name="bda-revente-shotgun",
), ),
url(r"^mails-rappel/(?P<spectacle_id>\d+)$", views.send_rappel, name="bda-rappels"), re_path(
url(r"^catalogue/(?P<request_type>[a-z]+)$", views.catalogue, name="bda-catalogue"), r"^mails-rappel/(?P<spectacle_id>\d+)$", views.send_rappel, name="bda-rappels"
),
re_path(
r"^catalogue/(?P<request_type>[a-z]+)$", views.catalogue, name="bda-catalogue"
),
] ]

View file

@ -274,13 +274,13 @@ def do_tirage(tirage_elt, token):
results = Algorithm(data["shows"], data["members"], choices)(token) results = Algorithm(data["shows"], data["members"], choices)(token)
# On compte les places attribuées et les déçus # On compte les places attribuées et les déçus
for (_, members, losers) in results: for _, members, losers in results:
data["total_slots"] += len(members) data["total_slots"] += len(members)
data["total_losers"] += len(losers) data["total_losers"] += len(losers)
# On calcule le déficit et les bénéfices pour le BdA # On calcule le déficit et les bénéfices pour le BdA
# FIXME: le traitement de l'opéra est sale # FIXME: le traitement de l'opéra est sale
for (show, members, _) in results: for show, members, _ in results:
deficit = (show.slots - len(members)) * show.price deficit = (show.slots - len(members)) * show.price
data["total_sold"] += show.slots * show.price data["total_sold"] += show.slots * show.price
if deficit >= 0: if deficit >= 0:
@ -293,8 +293,8 @@ def do_tirage(tirage_elt, token):
# so assign a single object for each Participant id # so assign a single object for each Participant id
members_uniq = {} members_uniq = {}
members2 = {} members2 = {}
for (show, members, _) in results: for show, members, _ in results:
for (member, _, _, _) in members: for member, _, _, _ in members:
if member.id not in members_uniq: if member.id not in members_uniq:
members_uniq[member.id] = member members_uniq[member.id] = member
members2[member] = [] members2[member] = []

View file

@ -1 +0,0 @@
default_app_config = "bds.apps.BdsConfig"

View file

@ -1,5 +1,4 @@
from django import apps as global_apps from django.apps import AppConfig, apps as global_apps
from django.apps import AppConfig
from django.db.models import Q from django.db.models import Q
from django.db.models.signals import post_migrate from django.db.models.signals import post_migrate

View file

@ -36,4 +36,6 @@ class ProfileForm(forms.ModelForm):
class Meta: class Meta:
model = BDSProfile model = BDSProfile
exclude = ["user"] exclude = ["user"]
widgets = {"birthdate": forms.DateInput(attrs={"type": "date"})} widgets = {
"birthdate": forms.DateInput(attrs={"type": "date"}, format="%Y-%m-%d")
}

View file

@ -8,7 +8,6 @@ import bds.models
class Migration(migrations.Migration): class Migration(migrations.Migration):
initial = True initial = True
dependencies = [migrations.swappable_dependency(settings.AUTH_USER_MODEL)] dependencies = [migrations.swappable_dependency(settings.AUTH_USER_MODEL)]

View file

@ -9,7 +9,6 @@ def create_bds_buro_group(apps, schema_editor):
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("bds", "0001_initial")] dependencies = [("bds", "0001_initial")]
operations = [ operations = [

View file

@ -4,7 +4,6 @@ from django.db import migrations
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("bds", "0002_bds_group"), ("bds", "0002_bds_group"),
] ]

View file

@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("bds", "0003_staff_permission"), ("bds", "0003_staff_permission"),
] ]

View file

@ -4,7 +4,6 @@ from django.db import migrations
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("bds", "0004_is_member_cotiz_type"), ("bds", "0004_is_member_cotiz_type"),
] ]

View file

@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("bds", "0005_remove_bdsprofile_certificate_file"), ("bds", "0005_remove_bdsprofile_certificate_file"),
] ]

View file

@ -3,6 +3,7 @@ from os.path import splitext
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.db import models from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from shared.utils import choices_length from shared.utils import choices_length
@ -93,6 +94,16 @@ class BDSProfile(models.Model):
), ),
) )
@classmethod
def expired_members(cls):
now = timezone.now()
qs = cls.objects.filter(is_member=True)
if now.month > 1 and now.month < 7:
return qs.filter(cotisation_period="SE1")
elif now.month < 2 or now.month > 8:
return qs.none()
return qs
class Meta: class Meta:
verbose_name = _("Profil BDS") verbose_name = _("Profil BDS")
verbose_name_plural = _("Profils BDS") verbose_name_plural = _("Profils BDS")

View file

@ -1,4 +1,4 @@
{% load staticfiles %} {% load static %}
{% load bulma_utils %} {% load bulma_utils %}
<!DOCTYPE html> <!DOCTYPE html>

View file

@ -0,0 +1,22 @@
{% extends "bds/base.html" %}
{% block content %}
<h1 class="title">Liste des adhésions expirées</h1>
{% if object_list %}
<div class="content">
<ul>
{% for p in object_list %}
<li>{{ p.user.first_name }} {{ p.user.last_name }} ({{ p.user.username }}), {{ p.get_cotisation_period_display }}</li>
{% endfor %}
</ul>
</div>
<div class="buttons is-centered">
<a class="button is-danger" href="{% url 'bds:members.reset' %}">Réinitialiser les adhésions expirées</a>
</div>
{% endif %}
{% endblock %}

View file

@ -36,6 +36,8 @@
<a class=button href="{% url 'bds:export.members' %}">Télécharger la liste des membres (CSV)</a> <a class=button href="{% url 'bds:export.members' %}">Télécharger la liste des membres (CSV)</a>
<a class=button href="{% url 'bds:members.expired' %}">Liste des adhésions expirées ({{ nb_expired }})</a>
<br> <br>
<br> <br>

View file

@ -5,100 +5,100 @@
{% block content %} {% block content %}
{% for form in forms.values %} {% for form in forms.values %}
{% for error in form.non_field_errors %} {% for error in form.non_field_errors %}
<div class="notification is-danger"> <div class="notification is-danger">
{{ error }} {{ error }}
</div> </div>
{% endfor %} {% endfor %}
{% endfor %} {% endfor %}
<h1 class="title">{% trans "Modification du profil " %}{{ view.user.username }}</h1> <h1 class="title">{% trans "Modification du profil " %}{{ view.user.username }}</h1>
<div class="container"> <div class="container">
<form method="post" action="" id="user-update-form"> <form method="post" action="" id="user-update-form">
{% csrf_token %} {% csrf_token %}
{% for form in forms.values %} {% for form in forms.values %}
{% include "bds/forms/form.html" with form=form errors=False %} {% include "bds/forms/form.html" with form=form errors=False %}
{% endfor %} {% endfor %}
</form> </form>
<form method="post" action="{% url 'bds:user.delete' view.user.pk %}" id="user-delete-form"> <form method="post" action="{% url 'bds:user.delete' view.user.pk %}" id="user-delete-form">
{% csrf_token %} {% csrf_token %}
</form> </form>
<div class="columns is-gapless mt-5"> <div class="columns is-gapless mt-5">
<div class="column is-5"> <div class="column is-5">
<button id="user-update-button" class="button is-fullwidth is-primary">Enregistrer</button> <button id="user-update-button" class="button is-fullwidth is-primary">Enregistrer</button>
</div>
<div class="column is-2">
</div>
<div class="column is-5">
<button id="user-delete-button" class="button is-fullwidth is-danger">Supprimer</button>
</div>
</div> </div>
<div class="column is-2">
</div>
<div class="column is-5">
<button id="user-delete-button" class="button is-fullwidth is-danger">Supprimer</button>
</div>
</div>
</div> </div>
<!-- Hidden by default --> <!-- Hidden by default -->
<div id="confirm-delete-modal" class="modal"> <div id="confirm-delete-modal" class="modal">
<div class="modal-background"></div> <div class="modal-background"></div>
<div class="modal-card"> <div class="modal-card">
<header class="modal-card-head"> <header class="modal-card-head">
<p class="modal-card-title">Confirmer la suppression</p> <p class="modal-card-title">Confirmer la suppression</p>
<button id= "modal-close" class="delete" aria-label="close"></button> <button id="modal-close" class="delete" aria-label="close"></button>
</header> </header>
<section class="modal-card-body"> <section class="modal-card-body">
Voulez-vous réellement supprimer ce compte ? Attention, cette opération est irréversible ! Voulez-vous réellement supprimer ce compte ? Attention, cette opération est irréversible !
</section> </section>
<footer class="modal-card-foot"> <footer class="modal-card-foot">
<button id="confirm-delete-button" class="button is-primary">Supprimer</button> <button id="confirm-delete-button" class="button is-primary">Supprimer</button>
<button id="cancel-delete-button" class="button">Annuler</button> <button id="cancel-delete-button" class="button">Annuler</button>
</footer> </footer>
</div> </div>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function() { $(document).ready(function() {
"use strict"; "use strict";
// Adapted from https://bulma.io/lib/main.js // Adapted from https://bulma.io/lib/main.js
function openModal(target) { function openModal(target) {
$(document).addClass('is-clipped'); $(document).addClass('is-clipped');
$(`#${target}`).addClass('is-active'); $(`#${target}`).addClass('is-active');
} }
function closeModals() { function closeModals() {
$(document).removeClass('is-clipped'); $(document).removeClass('is-clipped');
$(".modal").removeClass('is-active'); $(".modal").removeClass('is-active');
} }
// Si on clique sur enregistrer, ça marche // Si on clique sur enregistrer, ça marche
$("#user-update-button").on("click", function() { $("#user-update-button").on("click", function() {
$("#user-update-form").submit(); $("#user-update-form").submit();
}) })
// Si on clique sur supprimer, confirmation demandée
$("#user-delete-button").on("click", function() {
openModal("confirm-delete-modal");
});
$(".modal-background, #modal-close, #cancel-delete-button").on("click", closeModals);
$("#confirm-delete-button").on("click", function() {
$("#user-delete-form").submit();
});
$(document).on("keydown", function(e) {
if (e.key == "Escape") {
closeModals();
}
if (e.key == "Enter") {
$("#user-update-form").submit();
}
});
// Si on clique sur supprimer, confirmation demandée
$("#user-delete-button").on("click", function () {
openModal("confirm-delete-modal");
}); });
$(".modal-background, #modal-close, #cancel-delete-button").on("click", closeModals);
$("#confirm-delete-button").on("click", function() {
$("#user-delete-form").submit();
});
$(document).on("keydown", function (e) {
if (e.key == "Escape") {
closeModals();
}
if (e.key == "Enter") {
$("#user-update-form").submit();
}
});
});
</script> </script>
{% endblock %} {% endblock %}

View file

@ -31,7 +31,7 @@ class TestHomeView(TestCase):
user, backend="django.contrib.auth.backends.ModelBackend" user, backend="django.contrib.auth.backends.ModelBackend"
) )
resp = self.client.get(reverse("bds:home")) resp = self.client.get(reverse("bds:home"))
self.assertEquals(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
class TestRegistrationView(TestCase): class TestRegistrationView(TestCase):
@ -48,12 +48,12 @@ class TestRegistrationView(TestCase):
# Logged-in but unprivileged GET # Logged-in but unprivileged GET
client.force_login(user, backend="django.contrib.auth.backends.ModelBackend") client.force_login(user, backend="django.contrib.auth.backends.ModelBackend")
resp = client.get(url) resp = client.get(url)
self.assertEquals(resp.status_code, 403) self.assertEqual(resp.status_code, 403)
# Burô user GET # Burô user GET
give_bds_buro_permissions(user) give_bds_buro_permissions(user)
resp = client.get(url) resp = client.get(url)
self.assertEquals(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
@mock.patch("gestioncof.signals.messages") @mock.patch("gestioncof.signals.messages")
def test_get(self, mock_messages): def test_get(self, mock_messages):
@ -68,9 +68,9 @@ class TestRegistrationView(TestCase):
# Logged-in but unprivileged GET # Logged-in but unprivileged GET
client.force_login(user, backend="django.contrib.auth.backends.ModelBackend") client.force_login(user, backend="django.contrib.auth.backends.ModelBackend")
resp = client.get(url) resp = client.get(url)
self.assertEquals(resp.status_code, 403) self.assertEqual(resp.status_code, 403)
# Burô user GET # Burô user GET
give_bds_buro_permissions(user) give_bds_buro_permissions(user)
resp = client.get(url) resp = client.get(url)
self.assertEquals(resp.status_code, 200) self.assertEqual(resp.status_code, 200)

View file

@ -15,4 +15,10 @@ urlpatterns = [
), ),
path("user/delete/<int:pk>", views.UserDeleteView.as_view(), name="user.delete"), path("user/delete/<int:pk>", views.UserDeleteView.as_view(), name="user.delete"),
path("members", views.export_members, name="export.members"), path("members", views.export_members, name="export.members"),
path(
"members/expired",
views.ResetMembershipListView.as_view(),
name="members.expired",
),
path("members/reset", views.ResetMembershipView.as_view(), name="members.reset"),
] ]

View file

@ -8,7 +8,7 @@ from django.http import HttpResponse
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.urls import reverse, reverse_lazy from django.urls import reverse, reverse_lazy
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.views.generic import DeleteView, TemplateView from django.views.generic import DeleteView, ListView, RedirectView, TemplateView
from bds.autocomplete import bds_search from bds.autocomplete import bds_search
from bds.forms import ProfileForm, UserForm, UserFromClipperForm, UserFromScratchForm from bds.forms import ProfileForm, UserForm, UserFromClipperForm, UserFromScratchForm
@ -30,6 +30,7 @@ class Home(StaffRequiredMixin, TemplateView):
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["member_count"] = BDSProfile.objects.filter(is_member=True).count() context["member_count"] = BDSProfile.objects.filter(is_member=True).count()
context["nb_expired"] = BDSProfile.expired_members().count()
return context return context
@ -143,6 +144,28 @@ class UserDeleteView(StaffRequiredMixin, DeleteView):
return super().delete(request, *args, **kwargs) return super().delete(request, *args, **kwargs)
class ResetMembershipListView(StaffRequiredMixin, ListView):
model = BDSProfile
template_name = "bds/expired_members.html"
def get_queryset(self):
return BDSProfile.expired_members()
class ResetMembershipView(StaffRequiredMixin, RedirectView):
url = reverse_lazy("bds:members.expired")
def get(self, request, *args, **kwargs):
qs = BDSProfile.expired_members()
nb = qs.count()
qs.update(cotisation_period="NO", is_member=False, mails_bds=False)
messages.success(request, f"{nb} adhésions réinitialisées")
return super().get(request, *args, **kwargs)
@permission_required("bds.is_team") @permission_required("bds.is_team")
def export_members(request): def export_members(request):
response = HttpResponse(content_type="text/csv") response = HttpResponse(content_type="text/csv")

View file

@ -5,7 +5,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
initial = True initial = True
dependencies = [migrations.swappable_dependency(settings.AUTH_USER_MODEL)] dependencies = [migrations.swappable_dependency(settings.AUTH_USER_MODEL)]

View file

@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
initial = True initial = True
dependencies = [] dependencies = []

View file

@ -5,7 +5,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL), migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("events", "0001_event"), ("events", "0001_event"),

View file

@ -6,7 +6,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL), migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("events", "0002_event_subscribers"), ("events", "0002_event_subscribers"),

View file

@ -5,7 +5,6 @@ from django.db import migrations
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL), migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("events", "0003_options_and_extra_fields"), ("events", "0003_options_and_extra_fields"),

View file

@ -0,0 +1,63 @@
# Generated by Django 3.2.13 on 2022-06-30 10:39
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("events", "0004_unique_constraints"),
]
operations = [
migrations.AlterUniqueTogether(
name="extrafield",
unique_together=set(),
),
migrations.AlterUniqueTogether(
name="extrafieldcontent",
unique_together=set(),
),
migrations.AlterUniqueTogether(
name="option",
unique_together=set(),
),
migrations.AlterUniqueTogether(
name="optionchoice",
unique_together=set(),
),
migrations.AlterUniqueTogether(
name="registration",
unique_together=set(),
),
migrations.AddConstraint(
model_name="extrafield",
constraint=models.UniqueConstraint(
fields=("event", "name"), name="unique_extra_field"
),
),
migrations.AddConstraint(
model_name="extrafieldcontent",
constraint=models.UniqueConstraint(
fields=("field", "registration"), name="unique_extra_field_content"
),
),
migrations.AddConstraint(
model_name="option",
constraint=models.UniqueConstraint(
fields=("event", "name"), name="unique_event_option"
),
),
migrations.AddConstraint(
model_name="optionchoice",
constraint=models.UniqueConstraint(
fields=("option", "choice"), name="unique_option_choice"
),
),
migrations.AddConstraint(
model_name="registration",
constraint=models.UniqueConstraint(
fields=("event", "user"), name="unique_registration"
),
),
]

View file

@ -72,9 +72,13 @@ class Option(models.Model):
multi_choices = models.BooleanField(_("choix multiples"), default=False) multi_choices = models.BooleanField(_("choix multiples"), default=False)
class Meta: class Meta:
constraints = [
models.UniqueConstraint(
fields=["event", "name"], name="unique_event_option"
)
]
verbose_name = _("option d'événement") verbose_name = _("option d'événement")
verbose_name_plural = _("options d'événement") verbose_name_plural = _("options d'événement")
unique_together = [["event", "name"]]
def __str__(self): def __str__(self):
return self.name return self.name
@ -87,9 +91,13 @@ class OptionChoice(models.Model):
choice = models.CharField(_("choix"), max_length=200) choice = models.CharField(_("choix"), max_length=200)
class Meta: class Meta:
constraints = [
models.UniqueConstraint(
fields=["option", "choice"], name="unique_option_choice"
)
]
verbose_name = _("choix d'option d'événement") verbose_name = _("choix d'option d'événement")
verbose_name_plural = _("choix d'option d'événement") verbose_name_plural = _("choix d'option d'événement")
unique_together = [["option", "choice"]]
def __str__(self): def __str__(self):
return self.choice return self.choice
@ -118,7 +126,9 @@ class ExtraField(models.Model):
field_type = models.CharField(_("type de champ"), max_length=9, choices=FIELD_TYPE) field_type = models.CharField(_("type de champ"), max_length=9, choices=FIELD_TYPE)
class Meta: class Meta:
unique_together = [["event", "name"]] constraints = [
models.UniqueConstraint(fields=["event", "name"], name="unique_extra_field")
]
class ExtraFieldContent(models.Model): class ExtraFieldContent(models.Model):
@ -137,9 +147,13 @@ class ExtraFieldContent(models.Model):
) )
class Meta: class Meta:
constraints = [
models.UniqueConstraint(
fields=["field", "registration"], name="unique_extra_field_content"
)
]
verbose_name = _("contenu d'un champ événement supplémentaire") verbose_name = _("contenu d'un champ événement supplémentaire")
verbose_name_plural = _("contenus d'un champ événement supplémentaire") verbose_name_plural = _("contenus d'un champ événement supplémentaire")
unique_together = [["field", "registration"]]
def __str__(self): def __str__(self):
max_length = 50 max_length = 50
@ -163,9 +177,13 @@ class Registration(models.Model):
) )
class Meta: class Meta:
constraints = [
models.UniqueConstraint(
fields=["event", "user"], name="unique_registration"
)
]
verbose_name = _("inscription à un événement") verbose_name = _("inscription à un événement")
verbose_name_plural = _("inscriptions à un événement") verbose_name_plural = _("inscriptions à un événement")
unique_together = [["event", "user"]]
def __str__(self): def __str__(self):
return "inscription de {} à {}".format(self.user, self.event) return "inscription de {} à {}".format(self.user, self.event)

View file

@ -1,8 +1,15 @@
"""
ASGI entrypoint. Configures Django and then runs the application
defined in the ASGI_APPLICATION setting.
"""
import os import os
from channels.asgi import get_channel_layer import django
from channels.routing import get_default_application
if "DJANGO_SETTINGS_MODULE" not in os.environ: if "DJANGO_SETTINGS_MODULE" not in os.environ:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gestioasso.settings") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gestioasso.settings.local")
channel_layer = get_channel_layer() django.setup()
application = get_default_application()

View file

@ -1,3 +1,20 @@
from channels.routing import include from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from django.urls import path
routing = [include("kfet.routing.routing", path=r"^/ws/k-fet")] from kfet.routing import KFRouter
application = ProtocolTypeRouter(
{
# WebSocket chat handler
"websocket": AuthMiddlewareStack(
URLRouter(
[
path("ws/k-fet", KFRouter),
]
)
),
"http": get_asgi_application(),
}
)

View file

@ -7,6 +7,8 @@ Surcharge les settings définis dans common.py
import os import os
from datetime import timedelta from datetime import timedelta
from django.utils import timezone
from .common import * # NOQA from .common import * # NOQA
from .common import ( from .common import (
AUTHENTICATION_BACKENDS, AUTHENTICATION_BACKENDS,
@ -65,8 +67,8 @@ INSTALLED_APPS = (
"wagtail.images", "wagtail.images",
"wagtail.search", "wagtail.search",
"wagtail.admin", "wagtail.admin",
"wagtail.core", "wagtail",
"wagtail.contrib.modeladmin", # "wagtail.contrib.modeladmin",
"wagtail.contrib.routable_page", "wagtail.contrib.routable_page",
"wagtailmenus", "wagtailmenus",
"modelcluster", "modelcluster",
@ -83,7 +85,6 @@ MIDDLEWARE = (
+ MIDDLEWARE + MIDDLEWARE
+ [ + [
"djconfig.middleware.DjConfigMiddleware", "djconfig.middleware.DjConfigMiddleware",
"wagtail.core.middleware.SiteMiddleware",
"wagtail.contrib.redirects.middleware.RedirectMiddleware", "wagtail.contrib.redirects.middleware.RedirectMiddleware",
] ]
) )
@ -107,6 +108,8 @@ MEDIA_URL = "/gestion/media/"
CORS_ORIGIN_WHITELIST = ("bda.ens.fr", "www.bda.ens.fr" "cof.ens.fr", "www.cof.ens.fr") CORS_ORIGIN_WHITELIST = ("bda.ens.fr", "www.bda.ens.fr" "cof.ens.fr", "www.cof.ens.fr")
ASGI_APPLICATION = "gestioasso.routing.application"
# --- # ---
# Auth-related stuff # Auth-related stuff
# --- # ---
@ -145,7 +148,7 @@ CACHES = {
CHANNEL_LAYERS = { CHANNEL_LAYERS = {
"default": { "default": {
"BACKEND": "asgi_redis.RedisChannelLayer", "BACKEND": "shared.channels.ChannelLayer",
"CONFIG": { "CONFIG": {
"hosts": [ "hosts": [
( (
@ -158,11 +161,9 @@ CHANNEL_LAYERS = {
) )
] ]
}, },
"ROUTING": "gestioasso.routing.routing",
} }
} }
# --- # ---
# reCAPTCHA settings # reCAPTCHA settings
# https://github.com/praekelt/django-recaptcha # https://github.com/praekelt/django-recaptcha
@ -204,8 +205,9 @@ MAIL_DATA = {
"REPLYTO": "cof@ens.fr", "REPLYTO": "cof@ens.fr",
}, },
"rappels": {"FROM": "Le BdA <bda@ens.fr>", "REPLYTO": "Le BdA <bda@ens.fr>"}, "rappels": {"FROM": "Le BdA <bda@ens.fr>", "REPLYTO": "Le BdA <bda@ens.fr>"},
"rappel_negatif": { "kfet": {
"FROM": "La K-Fêt <k-fet@ens.fr>", "FROM": "La K-Fêt <chefs-k-fet@ens.fr>",
"REPLYTO": "La K-Fêt <chefs-k-fet@ens.fr>",
}, },
"revente": { "revente": {
"FROM": "BdA-Revente <bda-revente@ens.fr>", "FROM": "BdA-Revente <bda-revente@ens.fr>",
@ -224,3 +226,8 @@ KFET_HISTORY_DATE_LIMIT = timedelta(days=7)
# Limite plus longue pour les chefs/trez # Limite plus longue pour les chefs/trez
# (qui ont la permission kfet.access_old_history) # (qui ont la permission kfet.access_old_history)
KFET_HISTORY_LONG_DATE_LIMIT = timedelta(days=30) KFET_HISTORY_LONG_DATE_LIMIT = timedelta(days=30)
# These accounts don't represent actual people and can be freely accessed
# Identification based on trigrammes
KFET_HISTORY_NO_DATE_LIMIT_TRIGRAMMES = ["LIQ", "#13"]
KFET_HISTORY_NO_DATE_LIMIT = timezone.datetime(1794, 10, 30) # AKA the distant past

View file

@ -101,7 +101,7 @@ TEMPLATES = [
DATABASES = { DATABASES = {
"default": { "default": {
"ENGINE": "django.db.backends.postgresql_psycopg2", "ENGINE": "django.db.backends.postgresql",
"NAME": DBNAME, "NAME": DBNAME,
"USER": DBUSER, "USER": DBUSER,
"PASSWORD": DBPASSWD, "PASSWORD": DBPASSWD,
@ -111,6 +111,7 @@ DATABASES = {
SITE_ID = 1 SITE_ID = 1
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
# --- # ---
# Internationalization # Internationalization

View file

@ -47,8 +47,7 @@ CACHES = {"default": {"BACKEND": "django.core.cache.backends.locmem.LocMemCache"
# Use the default in memory asgi backend for local development # Use the default in memory asgi backend for local development
CHANNEL_LAYERS = { CHANNEL_LAYERS = {
"default": { "default": {
"BACKEND": "asgiref.inmemory.ChannelLayer", "BACKEND": "channels.layers.InMemoryChannelLayer",
"ROUTING": "gestioasso.routing.routing",
} }
} }

194
gestioasso/settings_bds.py Normal file
View file

@ -0,0 +1,194 @@
"""
Django settings for the gestioBDS project.
"""
import os
from pathlib import Path
from loadcredential import Credentials
credentials = Credentials(env_prefix="GESTIOBDS_")
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# WARNING: keep the secret key used in production secret!
SECRET_KEY = credentials["SECRET_KEY"]
# WARNING: don't run with debug turned on in production!
DEBUG = credentials.get_json("DEBUG", False)
ALLOWED_HOSTS = credentials.get_json("ALLOWED_HOSTS", [])
ADMINS = credentials.get_json("ADMINS", [])
SERVER_EMAIL = credentials.get("SERVER_EMAIL")
EMAIL_HOST = credentials.get("EMAIL_HOST")
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
##
# Installed Apps configuration
INSTALLED_APPS = [
"shared",
# Must be before 'django.contrib.admin'.
# https://django-autocomplete-light.readthedocs.io/en/master/install.html
"dal",
"dal_select2",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.sites",
"django.contrib.messages",
"django.contrib.admin",
"django.contrib.admindocs",
"gestioasso.apps.IgnoreSrcStaticFilesConfig",
"django_cas_ng",
"bootstrapform",
"widget_tweaks",
"bds",
"events",
"clubs",
"authens",
]
##
# Middleware configuration
MIDDLEWARE = [
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"django.middleware.security.SecurityMiddleware",
"django.middleware.locale.LocaleMiddleware",
]
##
# URL configuration
ROOT_URLCONF = "gestioasso.urls"
##
# Templates configuration
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
"django.template.context_processors.i18n",
"django.template.context_processors.media",
"django.template.context_processors.static",
]
},
}
]
##
# Database configuration
DATABASES = credentials.get_json(
"DATABASES",
default={
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": (BASE_DIR / "db.sqlite3"),
}
},
)
CACHES = credentials.get_json(
"CACHES",
default={
"default": {
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
},
},
)
CORS_ORIGIN_WHITELIST = credentials.get("CORS_ORIGIN_WHITELIST", [])
SITE_ID = 1
###
# Staticfiles configuration
STATIC_ROOT = credentials["STATIC_ROOT"]
STATIC_URL = "/static/"
MEDIA_ROOT = credentials.get("MEDIA_ROOT", (BASE_DIR / "media"))
MEDIA_URL = "/media/"
##
# Authens and Authentication configuration
AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.ModelBackend",
"authens.backends.ENSCASBackend",
"authens.backends.OldCASBackend",
]
AUTHENS_USE_OLDCAS = False
LOGIN_URL = "authens:login"
LOGIN_REDIRECT_URL = "bds:home"
LOGOUT_REDIRECT_URL = "bds:home"
# ---
# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/
# ---
LANGUAGE_CODE = "fr-fr"
TIME_ZONE = "Europe/Paris"
USE_I18N = True
USE_L10N = True
USE_TZ = True
LANGUAGES = (("fr", "Français"), ("en", "English"))
FORMAT_MODULE_PATH = "gestioasso.locale"
##
# Development configuration
if DEBUG:
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
def show_toolbar(request):
"""
On active la debug-toolbar en mode développement local sauf :
- dans l'admin où ça ne sert pas à grand chose;
- si la variable d'environnement DJANGO_NO_DDT est à 1 → ça permet de la désactiver
sans modifier ce fichier en exécutant `export DJANGO_NO_DDT=1` dans le terminal
qui lance `./manage.py runserver`.
Autre side effect de cette fonction : on ne fait pas la vérification de INTERNAL_IPS
que ferait la debug-toolbar par défaut, ce qui la fait fonctionner aussi à
l'intérieur de Vagrant (comportement non testé depuis un moment…)
"""
env_no_ddt = bool(os.environ.get("DJANGO_NO_DDT", None))
return not (env_no_ddt or request.path.startswith("/admin/"))
##
# Django Debug Toolbar configuration
DEBUG_TOOLBAR_CONFIG = {"SHOW_TOOLBAR_CALLBACK": show_toolbar}
INSTALLED_APPS += ["debug_toolbar"]
MIDDLEWARE = ["debug_toolbar.middleware.DebugToolbarMiddleware"] + MIDDLEWARE

318
gestioasso/settings_cof.py Normal file
View file

@ -0,0 +1,318 @@
"""
Django settings for the gestioCOF project.
"""
import os
from datetime import datetime, timedelta
from pathlib import Path
from django.urls import reverse_lazy
from loadcredential import Credentials
credentials = Credentials(env_prefix="GESTIOCOF_")
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# WARNING: keep the secret key used in production secret!
SECRET_KEY = credentials["SECRET_KEY"]
# WARNING: don't run with debug turned on in production!
DEBUG = credentials.get_json("DEBUG", False)
ALLOWED_HOSTS = credentials.get_json("ALLOWED_HOSTS", [])
ADMINS = credentials.get_json("ADMINS", [])
SERVER_EMAIL = credentials.get("SERVER_EMAIL")
EMAIL_HOST = credentials.get("EMAIL_HOST")
LDAP_SERVER_URL = credentials.get("LDAP_SERVER_URL")
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
##
# Installed Apps configuration
INSTALLED_APPS = [
"gestioncof",
# Must be before django admin
# https://github.com/infoportugal/wagtail-modeltranslation/issues/193
"wagtail_modeltranslation",
"wagtail_modeltranslation.makemigrations",
"wagtail_modeltranslation.migrate",
"modeltranslation",
"shared",
# Must be before 'django.contrib.admin'.
# https://django-autocomplete-light.readthedocs.io/en/master/install.html
"dal",
"dal_select2",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.sites",
"django.contrib.messages",
"django.contrib.admin",
"django.contrib.admindocs",
"gestioasso.apps.IgnoreSrcStaticFilesConfig",
"django_cas_ng",
"bootstrapform",
"widget_tweaks",
"bda",
"petitscours",
"hcaptcha",
"kfet",
"kfet.open",
"channels",
"djconfig",
"wagtail.contrib.forms",
"wagtail.contrib.redirects",
"wagtail.embeds",
"wagtail.sites",
"wagtail.users",
"wagtail.snippets",
"wagtail.documents",
"wagtail.images",
"wagtail.search",
"wagtail.admin",
"wagtail",
# "wagtail.contrib.modeladmin",
"wagtail.contrib.routable_page",
"wagtailmenus",
"modelcluster",
"taggit",
"kfet.auth",
"kfet.cms",
"gestioncof.cms",
"django_js_reverse",
]
##
# Middleware configuration
MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"django.middleware.security.SecurityMiddleware",
"django.middleware.locale.LocaleMiddleware",
"djconfig.middleware.DjConfigMiddleware",
"wagtail.contrib.redirects.middleware.RedirectMiddleware",
]
##
# URL configuration
ROOT_URLCONF = "gestioasso.urls"
##
# Templates configuration
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"wagtailmenus.context_processors.wagtailmenus",
"djconfig.context_processors.config",
"gestioncof.shared.context_processor",
"kfet.auth.context_processors.temporary_auth",
"kfet.context_processors.config",
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
"django.template.context_processors.i18n",
"django.template.context_processors.media",
"django.template.context_processors.static",
]
},
}
]
##
# Wagtail configuration
WAGTAIL_SITE_NAME = "GestioCOF"
WAGTAIL_ENABLE_UPDATE_CHECK = False
TAGGIT_CASE_INSENSITIVE = True
##
# Django-js-reverse settings
JS_REVERSE_JS_VAR_NAME = "django_urls"
# Quand on aura namespace les urls...
# JS_REVERSE_INCLUDE_ONLY_NAMESPACES = ['k-fet']
##
# K-Fêt history configuration
# L'historique n'est accesible que d'aujourd'hui
# à aujourd'hui - KFET_HISTORY_DATE_LIMIT
KFET_HISTORY_DATE_LIMIT = timedelta(days=7)
# Limite plus longue pour les chefs/trez
# (qui ont la permission kfet.access_old_history)
KFET_HISTORY_LONG_DATE_LIMIT = timedelta(days=30)
# These accounts don't represent actual people and can be freely accessed
# Identification based on trigrammes
KFET_HISTORY_NO_DATE_LIMIT_TRIGRAMMES = ["LIQ", "#13"]
KFET_HISTORY_NO_DATE_LIMIT = datetime(1794, 10, 30) # AKA the distant past
##
# Database configuration
DATABASES = credentials.get_json(
"DATABASES",
default={
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": (BASE_DIR / "db.sqlite3"),
}
},
)
CACHES = credentials.get_json(
"CACHES",
default={
"default": {
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
},
},
)
CHANNEL_LAYERS = credentials.get_json(
"CHANNEL_LAYERS",
default={
"default": {
"BACKEND": "channels.layers.InMemoryChannelLayer",
}
},
)
CORS_ORIGIN_WHITELIST = credentials.get("CORS_ORIGIN_WHITELIST", [])
SITE_ID = 1
###
# Staticfiles configuration
STATIC_ROOT = credentials["STATIC_ROOT"]
STATIC_URL = "/static/"
MEDIA_ROOT = credentials.get("MEDIA_ROOT", (BASE_DIR / "media"))
MEDIA_URL = "/media/"
##
# Authentication configuration
AUTHENTICATION_BACKENDS = [
"kfet.auth.backends.BlockFrozenAccountBackend", # Must be in first
"django.contrib.auth.backends.ModelBackend",
"gestioncof.shared.COFCASBackend",
"kfet.auth.backends.GenericBackend",
]
LOGIN_URL = "cof-login"
LOGIN_REDIRECT_URL = reverse_lazy("home")
# FIXME: Switch to authens
CAS_SERVER_URL = "https://cas.eleves.ens.fr/"
CAS_VERSION = "2"
CAS_LOGIN_MSG = None
CAS_IGNORE_REFERER = True
CAS_REDIRECT_URL = "/"
CAS_EMAIL_FORMAT = "%s@clipper.ens.fr"
##
# h-captcha configuration
HCAPTCHA_SITEKEY = credentials["HCAPTCHA_SITEKEY"]
HCAPTCHA_SECRET = credentials["HCAPTCHA_SECRET"]
##
# K-Fêt token for the openness indicator
KFETOPEN_TOKEN = credentials["KFETOPEN_TOKEN"]
##
# Mail configuration
MAIL_DATA = {
"petits_cours": {
"FROM": "Le COF <cof@ens.fr>",
"BCC": "archivescof@gmail.com",
"REPLYTO": "cof@ens.fr",
},
"rappels": {
"FROM": "Le BdA <bda@ens.fr>",
"REPLYTO": "Le BdA <bda@ens.fr>",
},
"rappel_negatif": {
"FROM": "La K-Fêt <chefs-k-fet@ens.fr>",
"REPLYTO": "La K-Fêt <chefs-k-fet@ens.fr>",
},
"revente": {
"FROM": "BdA-Revente <bda-revente@ens.fr>",
"REPLYTO": "BdA-Revente <bda-revente@ens.fr>",
},
}
# ---
# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/
# ---
LANGUAGE_CODE = "fr-fr"
TIME_ZONE = "Europe/Paris"
USE_I18N = True
USE_L10N = True
USE_TZ = True
LANGUAGES = (("fr", "Français"), ("en", "English"))
FORMAT_MODULE_PATH = "gestioasso.locale"
##
# Development configuration
if DEBUG:
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
def show_toolbar(request):
"""
On active la debug-toolbar en mode développement local sauf :
- dans l'admin où ça ne sert pas à grand chose;
- si la variable d'environnement DJANGO_NO_DDT est à 1 → ça permet de la désactiver
sans modifier ce fichier en exécutant `export DJANGO_NO_DDT=1` dans le terminal
qui lance `./manage.py runserver`.
Autre side effect de cette fonction : on ne fait pas la vérification de INTERNAL_IPS
que ferait la debug-toolbar par défaut, ce qui la fait fonctionner aussi à
l'intérieur de Vagrant (comportement non testé depuis un moment…)
"""
env_no_ddt = bool(os.environ.get("DJANGO_NO_DDT", None))
return not (env_no_ddt or request.path.startswith("/admin/"))
##
# Django Debug Toolbar configuration
DEBUG_TOOLBAR_CONFIG = {"SHOW_TOOLBAR_CALLBACK": show_toolbar}
INSTALLED_APPS += ["debug_toolbar"]
MIDDLEWARE = ["debug_toolbar.middleware.DebugToolbarMiddleware"] + MIDDLEWARE

View file

@ -1,6 +1,7 @@
""" """
Fichier principal de configuration des urls du projet GestioCOF Fichier principal de configuration des urls du projet GestioCOF
""" """
from django.conf import settings from django.conf import settings
from django.conf.urls.i18n import i18n_patterns from django.conf.urls.i18n import i18n_patterns
from django.conf.urls.static import static from django.conf.urls.static import static
@ -35,7 +36,7 @@ app_dict = {
"events": "gestion/event_v2/", # the events module is still experimental ! "events": "gestion/event_v2/", # the events module is still experimental !
"authens": "gestion/authens/", "authens": "gestion/authens/",
} }
for (app_name, url_prefix) in app_dict.items(): for app_name, url_prefix in app_dict.items():
if app_name in settings.INSTALLED_APPS: if app_name in settings.INSTALLED_APPS:
urlpatterns += [path(url_prefix, include("{}.urls".format(app_name)))] urlpatterns += [path(url_prefix, include("{}.urls".format(app_name)))]
@ -58,10 +59,10 @@ if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
# Wagtail URLs (wagtail.core urls must be last, as catch-all) # Wagtail URLs (wagtail urls must be last, as catch-all)
if "wagtail.core" in settings.INSTALLED_APPS: if "wagtail" in settings.INSTALLED_APPS:
from wagtail import urls as wagtail_urls
from wagtail.admin import urls as wagtailadmin_urls from wagtail.admin import urls as wagtailadmin_urls
from wagtail.core import urls as wagtail_urls
from wagtail.documents import urls as wagtaildocs_urls from wagtail.documents import urls as wagtaildocs_urls
urlpatterns += [ urlpatterns += [

View file

@ -1 +0,0 @@
default_app_config = "gestioncof.apps.GestioncofConfig"

View file

@ -6,7 +6,7 @@ from django.contrib.auth.models import Group, Permission, User
from django.db.models import Q from django.db.models import Q
from django.urls import reverse from django.urls import reverse
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from gestioncof.models import ( from gestioncof.models import (
Club, Club,

View file

@ -1 +0,0 @@
default_app_config = "gestioncof.cms.apps.COFCMSAppConfig"

View file

@ -3,9 +3,9 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import django.db.models.deletion import django.db.models.deletion
import wagtail.blocks
import wagtail.contrib.routable_page.models import wagtail.contrib.routable_page.models
import wagtail.core.blocks import wagtail.fields
import wagtail.core.fields
import wagtail.images.blocks import wagtail.images.blocks
from django.db import migrations, models from django.db import migrations, models
@ -13,7 +13,6 @@ import gestioncof.cms.models
class Migration(migrations.Migration): class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
@ -73,18 +72,14 @@ class Migration(migrations.Migration):
blank=True, null=True, verbose_name="Description rapide" blank=True, null=True, verbose_name="Description rapide"
), ),
), ),
("body", wagtail.core.fields.RichTextField(verbose_name="Contenu")), ("body", wagtail.fields.RichTextField(verbose_name="Contenu")),
( (
"body_fr", "body_fr",
wagtail.core.fields.RichTextField( wagtail.fields.RichTextField(null=True, verbose_name="Contenu"),
null=True, verbose_name="Contenu"
),
), ),
( (
"body_en", "body_en",
wagtail.core.fields.RichTextField( wagtail.fields.RichTextField(null=True, verbose_name="Contenu"),
null=True, verbose_name="Contenu"
),
), ),
( (
"is_event", "is_event",
@ -139,46 +134,40 @@ class Migration(migrations.Migration):
to="wagtailcore.Page", to="wagtailcore.Page",
), ),
), ),
("body", wagtail.core.fields.RichTextField(verbose_name="Description")), ("body", wagtail.fields.RichTextField(verbose_name="Description")),
( (
"body_fr", "body_fr",
wagtail.core.fields.RichTextField( wagtail.fields.RichTextField(null=True, verbose_name="Description"),
null=True, verbose_name="Description"
),
), ),
( (
"body_en", "body_en",
wagtail.core.fields.RichTextField( wagtail.fields.RichTextField(null=True, verbose_name="Description"),
null=True, verbose_name="Description"
),
), ),
( (
"links", "links",
wagtail.core.fields.StreamField( wagtail.fields.StreamField(
[ [
( (
"lien", "lien",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
( (
"url", "url",
wagtail.core.blocks.URLBlock(required=True), wagtail.blocks.URLBlock(required=True),
), ),
("texte", wagtail.core.blocks.CharBlock()), ("texte", wagtail.blocks.CharBlock()),
] ]
), ),
), ),
( (
"contact", "contact",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
( (
"email", "email",
wagtail.core.blocks.EmailBlock( wagtail.blocks.EmailBlock(required=True),
required=True
),
), ),
("texte", wagtail.core.blocks.CharBlock()), ("texte", wagtail.blocks.CharBlock()),
] ]
), ),
), ),
@ -187,31 +176,29 @@ class Migration(migrations.Migration):
), ),
( (
"links_fr", "links_fr",
wagtail.core.fields.StreamField( wagtail.fields.StreamField(
[ [
( (
"lien", "lien",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
( (
"url", "url",
wagtail.core.blocks.URLBlock(required=True), wagtail.blocks.URLBlock(required=True),
), ),
("texte", wagtail.core.blocks.CharBlock()), ("texte", wagtail.blocks.CharBlock()),
] ]
), ),
), ),
( (
"contact", "contact",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
( (
"email", "email",
wagtail.core.blocks.EmailBlock( wagtail.blocks.EmailBlock(required=True),
required=True
),
), ),
("texte", wagtail.core.blocks.CharBlock()), ("texte", wagtail.blocks.CharBlock()),
] ]
), ),
), ),
@ -221,31 +208,29 @@ class Migration(migrations.Migration):
), ),
( (
"links_en", "links_en",
wagtail.core.fields.StreamField( wagtail.fields.StreamField(
[ [
( (
"lien", "lien",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
( (
"url", "url",
wagtail.core.blocks.URLBlock(required=True), wagtail.blocks.URLBlock(required=True),
), ),
("texte", wagtail.core.blocks.CharBlock()), ("texte", wagtail.blocks.CharBlock()),
] ]
), ),
), ),
( (
"contact", "contact",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
( (
"email", "email",
wagtail.core.blocks.EmailBlock( wagtail.blocks.EmailBlock(required=True),
required=True
),
), ),
("texte", wagtail.core.blocks.CharBlock()), ("texte", wagtail.blocks.CharBlock()),
] ]
), ),
), ),
@ -287,17 +272,17 @@ class Migration(migrations.Migration):
), ),
( (
"introduction", "introduction",
wagtail.core.fields.RichTextField(verbose_name="Introduction"), wagtail.fields.RichTextField(verbose_name="Introduction"),
), ),
( (
"introduction_fr", "introduction_fr",
wagtail.core.fields.RichTextField( wagtail.fields.RichTextField(
null=True, verbose_name="Introduction" null=True, verbose_name="Introduction"
), ),
), ),
( (
"introduction_en", "introduction_en",
wagtail.core.fields.RichTextField( wagtail.fields.RichTextField(
null=True, verbose_name="Introduction" null=True, verbose_name="Introduction"
), ),
), ),
@ -330,27 +315,27 @@ class Migration(migrations.Migration):
), ),
( (
"body", "body",
wagtail.core.fields.StreamField( wagtail.fields.StreamField(
[ [
( (
"heading", "heading",
wagtail.core.blocks.CharBlock(classname="full title"), wagtail.blocks.CharBlock(classname="full title"),
), ),
("paragraph", wagtail.core.blocks.RichTextBlock()), ("paragraph", wagtail.blocks.RichTextBlock()),
("image", wagtail.images.blocks.ImageChooserBlock()), ("image", wagtail.images.blocks.ImageChooserBlock()),
( (
"iframe", "iframe",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
( (
"url", "url",
wagtail.core.blocks.URLBlock( wagtail.blocks.URLBlock(
"Adresse de la page" "Adresse de la page"
), ),
), ),
( (
"height", "height",
wagtail.core.blocks.CharBlock( wagtail.blocks.CharBlock(
"Hauteur (en pixels)" "Hauteur (en pixels)"
), ),
), ),
@ -362,27 +347,27 @@ class Migration(migrations.Migration):
), ),
( (
"body_fr", "body_fr",
wagtail.core.fields.StreamField( wagtail.fields.StreamField(
[ [
( (
"heading", "heading",
wagtail.core.blocks.CharBlock(classname="full title"), wagtail.blocks.CharBlock(classname="full title"),
), ),
("paragraph", wagtail.core.blocks.RichTextBlock()), ("paragraph", wagtail.blocks.RichTextBlock()),
("image", wagtail.images.blocks.ImageChooserBlock()), ("image", wagtail.images.blocks.ImageChooserBlock()),
( (
"iframe", "iframe",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
( (
"url", "url",
wagtail.core.blocks.URLBlock( wagtail.blocks.URLBlock(
"Adresse de la page" "Adresse de la page"
), ),
), ),
( (
"height", "height",
wagtail.core.blocks.CharBlock( wagtail.blocks.CharBlock(
"Hauteur (en pixels)" "Hauteur (en pixels)"
), ),
), ),
@ -395,27 +380,27 @@ class Migration(migrations.Migration):
), ),
( (
"body_en", "body_en",
wagtail.core.fields.StreamField( wagtail.fields.StreamField(
[ [
( (
"heading", "heading",
wagtail.core.blocks.CharBlock(classname="full title"), wagtail.blocks.CharBlock(classname="full title"),
), ),
("paragraph", wagtail.core.blocks.RichTextBlock()), ("paragraph", wagtail.blocks.RichTextBlock()),
("image", wagtail.images.blocks.ImageChooserBlock()), ("image", wagtail.images.blocks.ImageChooserBlock()),
( (
"iframe", "iframe",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
( (
"url", "url",
wagtail.core.blocks.URLBlock( wagtail.blocks.URLBlock(
"Adresse de la page" "Adresse de la page"
), ),
), ),
( (
"height", "height",
wagtail.core.blocks.CharBlock( wagtail.blocks.CharBlock(
"Hauteur (en pixels)" "Hauteur (en pixels)"
), ),
), ),
@ -449,17 +434,17 @@ class Migration(migrations.Migration):
), ),
( (
"introduction", "introduction",
wagtail.core.fields.RichTextField(verbose_name="Introduction"), wagtail.fields.RichTextField(verbose_name="Introduction"),
), ),
( (
"introduction_fr", "introduction_fr",
wagtail.core.fields.RichTextField( wagtail.fields.RichTextField(
null=True, verbose_name="Introduction" null=True, verbose_name="Introduction"
), ),
), ),
( (
"introduction_en", "introduction_en",
wagtail.core.fields.RichTextField( wagtail.fields.RichTextField(
null=True, verbose_name="Introduction" null=True, verbose_name="Introduction"
), ),
), ),

View file

@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("cofcms", "0001_initial")] dependencies = [("cofcms", "0001_initial")]
operations = [ operations = [

View file

@ -1,12 +1,11 @@
# Generated by Django 2.2.8 on 2019-12-20 16:22 # Generated by Django 2.2.8 on 2019-12-20 16:22
import wagtail.core.blocks import wagtail.blocks
import wagtail.core.fields import wagtail.fields
from django.db import migrations from django.db import migrations
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("cofcms", "0002_auto_20190523_1521"), ("cofcms", "0002_auto_20190523_1521"),
] ]
@ -15,26 +14,26 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name="cofdirectoryentrypage", model_name="cofdirectoryentrypage",
name="links", name="links",
field=wagtail.core.fields.StreamField( field=wagtail.fields.StreamField(
[ [
( (
"lien", "lien",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
("url", wagtail.core.blocks.URLBlock(required=True)), ("url", wagtail.blocks.URLBlock(required=True)),
("texte", wagtail.core.blocks.CharBlock()), ("texte", wagtail.blocks.CharBlock()),
] ]
), ),
), ),
( (
"contact", "contact",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
( (
"email", "email",
wagtail.core.blocks.EmailBlock(required=True), wagtail.blocks.EmailBlock(required=True),
), ),
("texte", wagtail.core.blocks.CharBlock()), ("texte", wagtail.blocks.CharBlock()),
] ]
), ),
), ),
@ -45,26 +44,26 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name="cofdirectoryentrypage", model_name="cofdirectoryentrypage",
name="links_en", name="links_en",
field=wagtail.core.fields.StreamField( field=wagtail.fields.StreamField(
[ [
( (
"lien", "lien",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
("url", wagtail.core.blocks.URLBlock(required=True)), ("url", wagtail.blocks.URLBlock(required=True)),
("texte", wagtail.core.blocks.CharBlock()), ("texte", wagtail.blocks.CharBlock()),
] ]
), ),
), ),
( (
"contact", "contact",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
( (
"email", "email",
wagtail.core.blocks.EmailBlock(required=True), wagtail.blocks.EmailBlock(required=True),
), ),
("texte", wagtail.core.blocks.CharBlock()), ("texte", wagtail.blocks.CharBlock()),
] ]
), ),
), ),
@ -76,26 +75,26 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name="cofdirectoryentrypage", model_name="cofdirectoryentrypage",
name="links_fr", name="links_fr",
field=wagtail.core.fields.StreamField( field=wagtail.fields.StreamField(
[ [
( (
"lien", "lien",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
("url", wagtail.core.blocks.URLBlock(required=True)), ("url", wagtail.blocks.URLBlock(required=True)),
("texte", wagtail.core.blocks.CharBlock()), ("texte", wagtail.blocks.CharBlock()),
] ]
), ),
), ),
( (
"contact", "contact",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
( (
"email", "email",
wagtail.core.blocks.EmailBlock(required=True), wagtail.blocks.EmailBlock(required=True),
), ),
("texte", wagtail.core.blocks.CharBlock()), ("texte", wagtail.blocks.CharBlock()),
] ]
), ),
), ),

View file

@ -1,12 +1,11 @@
# Generated by Django 2.2.15 on 2020-08-29 21:14 # Generated by Django 2.2.15 on 2020-08-29 21:14
import wagtail.core.blocks import wagtail.blocks
import wagtail.core.fields import wagtail.fields
from django.db import migrations from django.db import migrations
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("cofcms", "0003_directory_entry_optional_links"), ("cofcms", "0003_directory_entry_optional_links"),
] ]
@ -15,35 +14,35 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name="cofdirectoryentrypage", model_name="cofdirectoryentrypage",
name="links", name="links",
field=wagtail.core.fields.StreamField( field=wagtail.fields.StreamField(
[ [
( (
"lien", "lien",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
("url", wagtail.core.blocks.URLBlock(required=True)), ("url", wagtail.blocks.URLBlock(required=True)),
("texte", wagtail.core.blocks.CharBlock()), ("texte", wagtail.blocks.CharBlock()),
] ]
), ),
), ),
( (
"contact", "contact",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
( (
"email", "email",
wagtail.core.blocks.EmailBlock(required=True), wagtail.blocks.EmailBlock(required=True),
), ),
("texte", wagtail.core.blocks.CharBlock()), ("texte", wagtail.blocks.CharBlock()),
] ]
), ),
), ),
( (
"info", "info",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
("nom", wagtail.core.blocks.CharBlock(required=False)), ("nom", wagtail.blocks.CharBlock(required=False)),
("texte", wagtail.core.blocks.CharBlock(required=True)), ("texte", wagtail.blocks.CharBlock(required=True)),
] ]
), ),
), ),
@ -54,35 +53,35 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name="cofdirectoryentrypage", model_name="cofdirectoryentrypage",
name="links_en", name="links_en",
field=wagtail.core.fields.StreamField( field=wagtail.fields.StreamField(
[ [
( (
"lien", "lien",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
("url", wagtail.core.blocks.URLBlock(required=True)), ("url", wagtail.blocks.URLBlock(required=True)),
("texte", wagtail.core.blocks.CharBlock()), ("texte", wagtail.blocks.CharBlock()),
] ]
), ),
), ),
( (
"contact", "contact",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
( (
"email", "email",
wagtail.core.blocks.EmailBlock(required=True), wagtail.blocks.EmailBlock(required=True),
), ),
("texte", wagtail.core.blocks.CharBlock()), ("texte", wagtail.blocks.CharBlock()),
] ]
), ),
), ),
( (
"info", "info",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
("nom", wagtail.core.blocks.CharBlock(required=False)), ("nom", wagtail.blocks.CharBlock(required=False)),
("texte", wagtail.core.blocks.CharBlock(required=True)), ("texte", wagtail.blocks.CharBlock(required=True)),
] ]
), ),
), ),
@ -94,35 +93,35 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name="cofdirectoryentrypage", model_name="cofdirectoryentrypage",
name="links_fr", name="links_fr",
field=wagtail.core.fields.StreamField( field=wagtail.fields.StreamField(
[ [
( (
"lien", "lien",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
("url", wagtail.core.blocks.URLBlock(required=True)), ("url", wagtail.blocks.URLBlock(required=True)),
("texte", wagtail.core.blocks.CharBlock()), ("texte", wagtail.blocks.CharBlock()),
] ]
), ),
), ),
( (
"contact", "contact",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
( (
"email", "email",
wagtail.core.blocks.EmailBlock(required=True), wagtail.blocks.EmailBlock(required=True),
), ),
("texte", wagtail.core.blocks.CharBlock()), ("texte", wagtail.blocks.CharBlock()),
] ]
), ),
), ),
( (
"info", "info",
wagtail.core.blocks.StructBlock( wagtail.blocks.StructBlock(
[ [
("nom", wagtail.core.blocks.CharBlock(required=False)), ("nom", wagtail.blocks.CharBlock(required=False)),
("texte", wagtail.core.blocks.CharBlock(required=True)), ("texte", wagtail.blocks.CharBlock(required=True)),
] ]
), ),
), ),

View file

@ -0,0 +1,203 @@
# Generated by Django 4.2.17 on 2024-12-19 12:27
import wagtail.blocks
import wagtail.fields
import wagtail.images.blocks
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("cofcms", "0004_auto_20200829_2314"),
]
operations = [
migrations.AlterField(
model_name="cofdirectoryentrypage",
name="links",
field=wagtail.fields.StreamField(
[
(
"lien",
wagtail.blocks.StructBlock(
[
("url", wagtail.blocks.URLBlock(required=True)),
("texte", wagtail.blocks.CharBlock()),
]
),
),
(
"contact",
wagtail.blocks.StructBlock(
[
("email", wagtail.blocks.EmailBlock(required=True)),
("texte", wagtail.blocks.CharBlock()),
]
),
),
(
"info",
wagtail.blocks.StructBlock(
[
("nom", wagtail.blocks.CharBlock(required=False)),
("texte", wagtail.blocks.CharBlock(required=True)),
]
),
),
],
blank=True,
use_json_field=True,
),
),
migrations.AlterField(
model_name="cofdirectoryentrypage",
name="links_en",
field=wagtail.fields.StreamField(
[
(
"lien",
wagtail.blocks.StructBlock(
[
("url", wagtail.blocks.URLBlock(required=True)),
("texte", wagtail.blocks.CharBlock()),
]
),
),
(
"contact",
wagtail.blocks.StructBlock(
[
("email", wagtail.blocks.EmailBlock(required=True)),
("texte", wagtail.blocks.CharBlock()),
]
),
),
(
"info",
wagtail.blocks.StructBlock(
[
("nom", wagtail.blocks.CharBlock(required=False)),
("texte", wagtail.blocks.CharBlock(required=True)),
]
),
),
],
blank=True,
null=True,
use_json_field=True,
),
),
migrations.AlterField(
model_name="cofdirectoryentrypage",
name="links_fr",
field=wagtail.fields.StreamField(
[
(
"lien",
wagtail.blocks.StructBlock(
[
("url", wagtail.blocks.URLBlock(required=True)),
("texte", wagtail.blocks.CharBlock()),
]
),
),
(
"contact",
wagtail.blocks.StructBlock(
[
("email", wagtail.blocks.EmailBlock(required=True)),
("texte", wagtail.blocks.CharBlock()),
]
),
),
(
"info",
wagtail.blocks.StructBlock(
[
("nom", wagtail.blocks.CharBlock(required=False)),
("texte", wagtail.blocks.CharBlock(required=True)),
]
),
),
],
blank=True,
null=True,
use_json_field=True,
),
),
migrations.AlterField(
model_name="cofpage",
name="body",
field=wagtail.fields.StreamField(
[
("heading", wagtail.blocks.CharBlock(form_classname="full title")),
("paragraph", wagtail.blocks.RichTextBlock()),
("image", wagtail.images.blocks.ImageChooserBlock()),
(
"iframe",
wagtail.blocks.StructBlock(
[
("url", wagtail.blocks.URLBlock("Adresse de la page")),
(
"height",
wagtail.blocks.CharBlock("Hauteur (en pixels)"),
),
]
),
),
],
use_json_field=True,
),
),
migrations.AlterField(
model_name="cofpage",
name="body_en",
field=wagtail.fields.StreamField(
[
("heading", wagtail.blocks.CharBlock(form_classname="full title")),
("paragraph", wagtail.blocks.RichTextBlock()),
("image", wagtail.images.blocks.ImageChooserBlock()),
(
"iframe",
wagtail.blocks.StructBlock(
[
("url", wagtail.blocks.URLBlock("Adresse de la page")),
(
"height",
wagtail.blocks.CharBlock("Hauteur (en pixels)"),
),
]
),
),
],
null=True,
use_json_field=True,
),
),
migrations.AlterField(
model_name="cofpage",
name="body_fr",
field=wagtail.fields.StreamField(
[
("heading", wagtail.blocks.CharBlock(form_classname="full title")),
("paragraph", wagtail.blocks.RichTextBlock()),
("image", wagtail.images.blocks.ImageChooserBlock()),
(
"iframe",
wagtail.blocks.StructBlock(
[
("url", wagtail.blocks.URLBlock("Adresse de la page")),
(
"height",
wagtail.blocks.CharBlock("Hauteur (en pixels)"),
),
]
),
),
],
null=True,
use_json_field=True,
),
),
]

View file

@ -1,12 +1,11 @@
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
from django.db import models from django.db import models
from wagtail.admin.edit_handlers import FieldPanel, StreamFieldPanel from wagtail import blocks
from wagtail.admin.panels import FieldPanel
from wagtail.contrib.routable_page.models import RoutablePageMixin, route from wagtail.contrib.routable_page.models import RoutablePageMixin, route
from wagtail.core import blocks from wagtail.fields import RichTextField, StreamField
from wagtail.core.fields import RichTextField, StreamField
from wagtail.core.models import Page
from wagtail.images.blocks import ImageChooserBlock from wagtail.images.blocks import ImageChooserBlock
from wagtail.images.edit_handlers import ImageChooserPanel from wagtail.models import Page
# Page pouvant afficher des actualités # Page pouvant afficher des actualités
@ -69,10 +68,11 @@ class COFPage(Page):
("paragraph", blocks.RichTextBlock()), ("paragraph", blocks.RichTextBlock()),
("image", ImageChooserBlock()), ("image", ImageChooserBlock()),
("iframe", IFrameBlock()), ("iframe", IFrameBlock()),
] ],
use_json_field=True,
) )
content_panels = Page.content_panels + [StreamFieldPanel("body")] content_panels = Page.content_panels + [FieldPanel("body")]
subpage_types = ["COFDirectoryPage", "COFPage"] subpage_types = ["COFDirectoryPage", "COFPage"]
parent_page_types = ["COFPage", "COFRootPage"] parent_page_types = ["COFPage", "COFRootPage"]
@ -127,7 +127,7 @@ class COFActuPage(RoutablePageMixin, Page):
all_day = models.BooleanField("Toute la journée", default=False, blank=True) all_day = models.BooleanField("Toute la journée", default=False, blank=True)
content_panels = Page.content_panels + [ content_panels = Page.content_panels + [
ImageChooserPanel("image"), FieldPanel("image"),
FieldPanel("chapo"), FieldPanel("chapo"),
FieldPanel("body", classname="full"), FieldPanel("body", classname="full"),
FieldPanel("is_event"), FieldPanel("is_event"),
@ -204,6 +204,7 @@ class COFDirectoryEntryPage(Page):
), ),
], ],
blank=True, blank=True,
use_json_field=True,
) )
image = models.ForeignKey( image = models.ForeignKey(
@ -216,9 +217,9 @@ class COFDirectoryEntryPage(Page):
) )
content_panels = Page.content_panels + [ content_panels = Page.content_panels + [
ImageChooserPanel("image"), FieldPanel("image"),
FieldPanel("body", classname="full"), FieldPanel("body", classname="full"),
StreamFieldPanel("links"), FieldPanel("links"),
] ]
subpage_types = [] subpage_types = []

View file

@ -2,7 +2,7 @@ from datetime import date, timedelta
from django import template from django import template
from django.utils import formats, timezone from django.utils import formats, timezone
from django.utils.translation import ugettext as _ from django.utils.translation import gettext as _
from ..models import COFActuPage, COFRootPage from ..models import COFActuPage, COFRootPage

View file

@ -3,7 +3,7 @@ from django.contrib.auth import get_user_model
from django.contrib.auth.forms import AuthenticationForm from django.contrib.auth.forms import AuthenticationForm
from django.forms.formsets import BaseFormSet, formset_factory from django.forms.formsets import BaseFormSet, formset_factory
from django.forms.widgets import CheckboxSelectMultiple, RadioSelect from django.forms.widgets import CheckboxSelectMultiple, RadioSelect
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from djconfig.forms import ConfigForm from djconfig.forms import ConfigForm
from bda.models import Spectacle from bda.models import Spectacle
@ -276,7 +276,9 @@ class RegistrationProfileForm(forms.ModelForm):
self.fields["mailing_bda_revente"].initial = True self.fields["mailing_bda_revente"].initial = True
self.fields["mailing_unernestaparis"].initial = True self.fields["mailing_unernestaparis"].initial = True
self.fields.keyOrder = [ class Meta:
model = CofProfile
fields = [
"login_clipper", "login_clipper",
"phone", "phone",
"occupation", "occupation",
@ -290,22 +292,6 @@ class RegistrationProfileForm(forms.ModelForm):
"comments", "comments",
] ]
class Meta:
model = CofProfile
fields = (
"login_clipper",
"phone",
"occupation",
"departement",
"is_cof",
"type_cotiz",
"mailing_cof",
"mailing_bda",
"mailing_bda_revente",
"mailing_unernestaparis",
"comments",
)
STATUS_CHOICES = ( STATUS_CHOICES = (
("no", "Non"), ("no", "Non"),

View file

@ -6,7 +6,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [migrations.swappable_dependency(settings.AUTH_USER_MODEL)] dependencies = [migrations.swappable_dependency(settings.AUTH_USER_MODEL)]
operations = [ operations = [

View file

@ -5,7 +5,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("gestioncof", "0001_initial")] dependencies = [("gestioncof", "0001_initial")]
operations = [ operations = [

View file

@ -5,7 +5,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("gestioncof", "0002_enable_unprocessed_demandes")] dependencies = [("gestioncof", "0002_enable_unprocessed_demandes")]
operations = [ operations = [

View file

@ -25,7 +25,6 @@ def create_mail(apps, schema_editor):
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("gestioncof", "0003_event_image")] dependencies = [("gestioncof", "0003_event_image")]
operations = [ operations = [

View file

@ -5,7 +5,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("gestioncof", "0004_registration_mail")] dependencies = [("gestioncof", "0004_registration_mail")]
operations = [ operations = [

View file

@ -6,7 +6,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("bda", "0004_mails-rappel"), ("bda", "0004_mails-rappel"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL), migrations.swappable_dependency(settings.AUTH_USER_MODEL),

View file

@ -6,7 +6,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("gestioncof", "0006_add_calendar")] dependencies = [("gestioncof", "0006_add_calendar")]
operations = [ operations = [

View file

@ -10,7 +10,6 @@ def forwards(apps, schema_editor):
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("gestioncof", "0007_alter_club")] dependencies = [("gestioncof", "0007_alter_club")]
operations = [ operations = [

View file

@ -5,7 +5,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("gestioncof", "0008_py3")] dependencies = [("gestioncof", "0008_py3")]
operations = [migrations.DeleteModel(name="Clipper")] operations = [migrations.DeleteModel(name="Clipper")]

View file

@ -4,7 +4,6 @@ from django.db import migrations
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("gestioncof", "0009_delete_clipper")] dependencies = [("gestioncof", "0009_delete_clipper")]
operations = [migrations.DeleteModel(name="CustomMail")] operations = [migrations.DeleteModel(name="CustomMail")]

View file

@ -5,7 +5,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("gestioncof", "0010_delete_custommail")] dependencies = [("gestioncof", "0010_delete_custommail")]
operations = [ operations = [

Some files were not shown because too many files have changed in this diff Show more