Compare commits

...

944 commits

Author SHA1 Message Date
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
Martin Pépin
1c880b265e
Version 1.11 2021-10-26 19:49:05 +02:00
Martin Pépin
75fbdc7efb
CHANGELOG: todo prod: faire un compte hcaptcha 2021-10-26 19:47:38 +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
Martin Pepin
77aa269c90 Merge branch 'Mails_rappel_kfet' into 'master'
Reminder mails for negative K-Psul accounts

See merge request klub-dev-ens/gestioCOF!492
2021-10-22 22:44:55 +02:00
Martin Pépin
9a143521d5
Update changelog 2021-10-22 22:37:56 +02:00
Martin Pépin
a77cf59b18
Rappels négatifs K-Fêt: ajustements cosmétiques 2021-10-22 22:36:30 +02:00
Alseidon
d8cabda678
First draft of reminder mail for negative K-Psul accounts 2021-10-22 21:29:34 +02:00
Martin Pépin
f086140dad
Update changelog 2021-10-22 21:12:16 +02:00
Martin Pepin
4d1ae8f540 Merge branch 'thubrecht/embed' into 'master'
On utilise |richtext pour les champs RichText, ce qui permet de bien faire les rendus

Closes #274

See merge request klub-dev-ens/gestioCOF!500
2021-10-22 21:04:20 +02:00
Ludovic Stephan
6d824a58be Merge branch 'thubrecht/ordre-consos' into 'master'
Corrige le tri des articles dans K-Psul

See merge request klub-dev-ens/gestioCOF!502
2021-10-12 16:05:26 +02:00
20880114aa Corrige le tri des articles dans K-Psul 2021-10-12 15:57:09 +02:00
Ludovic Stephan
df180d7446 Merge branch 'thubrecht/promo' into 'master'
Déplace le choix de la promo dans le formulaire

Closes #215

See merge request klub-dev-ens/gestioCOF!501
2021-07-01 09:03:47 +00:00
ef1793a348 Avec une seule majuscule 2021-07-01 10:29:54 +02:00
2d677b2093 Utilise des callables pour les choix 2021-07-01 10:29:14 +02:00
f70eacfc37 Déplace le choix de la promo dans le formulaire 2021-06-27 00:23:49 +02:00
264a0a852f On utilise |richtext pour les champs RichText, ce qui permet de bien faire les rendus 2021-06-26 22:52:23 +02:00
7ca7f7298a Update CHANGELOG 2021-06-17 21:28:08 +02:00
Tom Hubrecht
a5c822e7f7 Merge branch 'Aufinal/remove_negative' into 'master'
Fonctionnement du négatif + erreurs de K-Psul

Closes #279

See merge request klub-dev-ens/gestioCOF!494
2021-06-17 19:22:14 +00:00
Ludovic Stephan
6b316c482b Remove obsolete section 2021-06-17 17:22:17 +02:00
Ludovic Stephan
4060730ec5 Remove logging 2021-06-17 10:49:35 +02:00
Ludovic Stephan
c6cfc311e0 CHANGELOG 2021-06-17 10:45:53 +02:00
Ludovic Stephan
4326ba9016 Oublis de renaming 2021-06-17 10:42:15 +02:00
Ludovic Stephan
4205e0ad0e Tests 2021-06-17 10:42:15 +02:00
Ludovic Stephan
964eec6ab1 Adapte le JS aux nouvelles erreurs 2021-06-17 10:42:13 +02:00
Ludovic Stephan
29236e0b0e Nouvelle gestion des erreurs JSON 2021-06-17 10:40:51 +02:00
Ludovic Stephan
1939a54fef Tests du nouveau comportement 2021-06-17 10:40:51 +02:00
Ludovic Stephan
348881d207 Migration 2021-06-17 10:40:51 +02:00
Ludovic Stephan
ef8c1b8bf2 Nouveau fonctionnement des négatifs 2021-06-17 10:40:51 +02:00
Tom Hubrecht
8743301105 Merge branch 'Aufinal/let_it_go' into 'master'
Change le fonctionnement du gel de compte

Closes #280

See merge request klub-dev-ens/gestioCOF!493
2021-06-15 15:24:44 +00:00
Ludovic Stephan
6a11139588 Fix tests 2021-06-15 16:52:56 +02:00
Ludovic Stephan
a34b83c236 Use backend to enforce frozen accounts 2021-06-15 16:52:50 +02:00
Ludovic Stephan
02584982f6 gnagnagna 2021-06-15 14:48:35 +02:00
Ludovic Stephan
7bf0c5f09e Fix frozen forms 2021-06-15 14:07:43 +02:00
Ludovic Stephan
b9aaf6a19c Fix test 2021-06-15 14:07:43 +02:00
Ludovic Stephan
16dee0c143 Remove print 2021-06-15 14:07:43 +02:00
Ludovic Stephan
a947b9d3f2 Fix decorator 2021-06-15 14:07:43 +02:00
Ludovic Stephan
93d283fecb Remove unused permission 2021-06-15 14:07:43 +02:00
Ludovic Stephan
63738e8e02 Frozen error display 2021-06-15 14:07:40 +02:00
Ludovic Stephan
1e44550e12 New frozen function 2021-06-15 14:05:39 +02:00
Ludovic Stephan
4136cb6868 Unfreeze every account 2021-06-15 14:05:39 +02:00
Ludovic Stephan
99809209e0 Change les permissions pour geler/dégeler un compte 2021-06-15 14:05:39 +02:00
Ludovic Stephan
0351f6728b CHANGELOG 2021-05-05 02:10:44 +02:00
Ludovic Stephan
7efc7e6b94 Merge branch 'thubrecht/autocomplete-css' into 'master'
On modifie le curseur quand on survole un compte dans l'autocomplete

See merge request klub-dev-ens/gestioCOF!499
2021-05-05 00:06:15 +00:00
7d21a5a1fc On supprime des sélecteurs inutiles 2021-05-05 01:57:46 +02:00
dba785bf13 Pareil, mais dans gestiocof 2021-05-05 00:59:47 +02:00
71878caf2c On modifie le curseur quand on survole un compte dans l'autocomplete 2021-05-05 00:03:52 +02:00
Tom Hubrecht
db42028228 Merge branch 'Aufinal/backbone' into 'master'
Refactor le JS de K-Psul via Backbone : 2e étape

Closes #267 and #290

See merge request klub-dev-ens/gestioCOF!400
2021-05-04 21:17:09 +00:00
Ludovic Stephan
7171a7567c Remove double negative 2021-05-04 21:43:48 +02:00
Ludovic Stephan
339223bec0 Black 2021-05-04 18:12:47 +02:00
Ludovic Stephan
d62a8d61de Search fix and CSS update 2021-05-04 17:52:13 +02:00
Ludovic Stephan
f6c83dc692 FINALLY fix this f***ing whitespace mess 2021-05-04 17:52:13 +02:00
Ludovic Stephan
a984d1fd6f Clarity 2021-05-04 17:52:13 +02:00
Ludovic Stephan
f901ea9396 Remove useless kpsul.html code 2021-05-04 17:52:13 +02:00
Ludovic Stephan
17d96f1775 New account manager logic 2021-05-04 17:52:13 +02:00
Ludovic Stephan
c10e5fe45c Refactor Account model a bit 2021-05-04 17:52:13 +02:00
Martin Pépin
9bbe3f50cb
Update CHANGELOG.md 2021-04-18 18:17:38 +02:00
Martin Pépin
1f4a4ec76f
Update CHANGELOG.md 2021-04-18 17:46:54 +02:00
Martin Pepin
2befa584aa Merge branch 'Aufinal/remove_24' into 'master'
Remove limit for purchases

Closes #289

See merge request klub-dev-ens/gestioCOF!498
2021-04-18 08:35:24 +00:00
Ludovic Stephan
b48d32f4bc Remove limit for purchases 2021-04-16 16:42:12 +02:00
Tom Hubrecht
e36e88e77a Merge branch 'Aufinal/no_warnings' into 'master'
Fix : plus de warnings chelous pendant les tests

See merge request klub-dev-ens/gestioCOF!495
2021-03-17 22:12:01 +00:00
Tom Hubrecht
8e9fc341ca Merge branch 'Aufinal/forbidden_kfet' into 'master'
Test plus général pour l'erreur de permissions K-Fêt

See merge request klub-dev-ens/gestioCOF!491
2021-03-16 23:22:18 +01:00
Ludovic Stephan
c14c2d54a5 More general forbidden test 2021-03-16 23:04:03 +01:00
Tom Hubrecht
6adfaba8e9 Merge branch 'Aufinal/account_update_forms' into 'master'
Refactor la vue `account_update`

Closes #232 and #119

See merge request klub-dev-ens/gestioCOF!490
2021-03-16 23:02:12 +01:00
Tom Hubrecht
06005014f9 Merge branch 'Aufinal/delete_balance_offset' into 'master'
Supprime le champ `balance_offset` et harmonise la gestion des négatifs

Closes #281

See merge request klub-dev-ens/gestioCOF!489
2021-03-16 22:42:13 +01:00
Ludovic Stephan
4268a30d51 CHANGELOG 2021-03-16 22:10:33 +01:00
Tom Hubrecht
c71e6d22bf Merge branch 'Aufinal/hcaptcha' into 'master'
Remplace recaptcha par hcaptcha

Closes #262

See merge request klub-dev-ens/gestioCOF!497
2021-03-16 22:00:48 +01:00
Ludovic Stephan
4df3ef4dd9 Fix secret import 2021-03-04 23:28:55 +01:00
Ludovic Stephan
af95e64344 TODO de prod 2021-03-04 23:14:10 +01:00
Ludovic Stephan
ac8ad15ad1 Fix tests: mock captcha clean method 2021-03-04 18:30:51 +01:00
Ludovic Stephan
47dd078b6a Remplace recaptcha par hcaptcha 2021-03-04 17:56:42 +01:00
Ludovic Stephan
472a44c30f Remove useless buttons 2021-03-03 23:11:39 +01:00
Ludovic Stephan
b72ea9ebf9 Forgot a warning 2021-02-28 02:56:12 +01:00
Ludovic Stephan
f9958e4da0 Fix : plus de warnings chelous pendant les tests 2021-02-28 02:35:40 +01:00
Ludovic Stephan
47f406e09e Fix tests 2021-02-23 22:52:39 +01:00
Ludovic Stephan
1450b65dcd Rework complet de account_update 2021-02-23 22:52:39 +01:00
Ludovic Stephan
aac94afcd0 Améliore le formulaire de mdp K-Fêt 2021-02-23 22:52:39 +01:00
Ludovic Stephan
209360f535 Delete self-update form 2021-02-23 22:52:39 +01:00
Ludovic Stephan
b224fedf28 Fix frozen account display 2021-02-23 22:52:39 +01:00
Ludovic Stephan
1ab071d16e LINT 2021-02-23 22:52:27 +01:00
Ludovic Stephan
1cf6f6f3e7 Fix migration conflict 2021-02-23 22:41:04 +01:00
Ludovic Stephan
a421bec625 Fix templates 2021-02-23 22:33:00 +01:00
Ludovic Stephan
4e758fbba0 Delete balance_offset field 2021-02-23 22:33:00 +01:00
Martin Pepin
2350109a33 Merge branch 'Aufinal/migration_checks' into 'master'
CI: ne lance `migration_checks` que sur nos propres apps

See merge request klub-dev-ens/gestioCOF!488
2021-02-23 21:18:36 +01:00
Ludovic Stephan
778637d60e Merge branch 'dodo/limit-history-acces' into 'master'
Limit kfet history access

See merge request klub-dev-ens/gestioCOF!487
2021-02-20 22:58:59 +01:00
Dorian Lesbre
23f7865140 Switch back from config to settings 2021-02-20 20:59:54 +01:00
Dorian Lesbre
cc7c4306f4 Added change description to CHANGELOG 2021-02-20 19:10:49 +01:00
Dorian Lesbre
1183e50f60 Fixed tests 2021-02-19 13:48:12 +01:00
Dorian Lesbre
a8de7e0ae0 makemigrations 2021-02-19 13:38:36 +01:00
Dorian Lesbre
30a39ef2f6 Switch from account test to user test 2021-02-19 12:16:43 +01:00
Dorian Lesbre
9a635148bb Switched from datetime.today() to timezone.now() 2021-02-19 12:13:23 +01:00
Dorian Lesbre
4b95b65be2 Removed unused import 2021-02-19 11:55:18 +01:00
Dorian Lesbre
884ec2535b Fixed stupid errors 2021-02-19 11:51:48 +01:00
Dorian Lesbre
beba3052dd Switched from hardcoded settings to config 2021-02-19 11:46:42 +01:00
Dorian Lesbre
46242ad2c0 Added separate permission for chef/trez 2021-02-19 10:48:24 +01:00
Dorian Lesbre
fa8c57269c Added help_text to history form 2021-02-19 10:32:12 +01:00
Dorian Lesbre
b97bc8bfa8 Changed accoutn comparaison from id to equality 2021-02-19 10:26:05 +01:00
Dorian Lesbre
89fc309c01 Returned 403 on dubious history request 2021-02-19 10:18:47 +01:00
Ludovic Stephan
d7367476bc Fix app names 2021-02-18 17:41:52 +01:00
Ludovic Stephan
7297baaf7e Only check migrations for custom apps 2021-02-18 17:30:28 +01:00
Ludovic Stephan
8bf7914728 Merge branch 'kerl/fix_bds_production_urls' into 'master'
Hotfixes appliqués en production pour GestioBDS

See merge request klub-dev-ens/gestioCOF!484
2021-02-18 17:02:21 +01:00
Ludovic Stephan
71fbbcff8a Merge branch 'kerl/rm_login_clipper' into 'master'
Admin : supprime la colonne login_clipper dans la liste des Users

See merge request klub-dev-ens/gestioCOF!486
2021-02-18 17:01:05 +01:00
Dorian Lesbre
9303772f9a Renamed week_ago => history_limit and removed print 2021-02-10 22:19:52 +01:00
559b36b6f0 Limite le datepicker pour ne pas demander plus de temps que possible dans l'historique 2021-02-10 22:13:50 +01:00
Dorian Lesbre
fbafdb7134 Added kfet history date limit when not accessing own account 2021-02-10 21:32:44 +01:00
Martin Pépin
a53bd94737
admin: rm the login_clipper column in the user list 2021-02-09 22:42:49 +01:00
Ludovic Stephan
46ef12309a Merge branch 'kerl/rename_cof_gestioAsso' into 'master'
Renomme le dossier cof/ en gestioasso/

See merge request klub-dev-ens/gestioCOF!485
2021-02-08 19:29:07 +01:00
Martin Pépin
4f60ba35eb
Update the settings' docstrings 2021-02-08 19:19:54 +01:00
Martin Pépin
f29b3f0187
Make "GestioBDS" appear in the README 2021-02-07 18:11:17 +01:00
Martin Pépin
aa3462aaee
Update the CI config wrt the new project name 2021-02-07 18:11:06 +01:00
Martin Pépin
7c35357060
Fix a reverse url resolution on the BDS home page 2021-02-07 17:39:28 +01:00
Martin Pépin
726b3f55a0
Rename the cof/ folder to gestioasso/
This is a much more sensible name since it contains configuration
applicable to both GestioCOF and GestioBDS.

The next logical step would be to rename the `gestioncof/` folder to
`cof/`.
2021-02-07 17:17:15 +01:00
Martin Pepin
63eeb5b7a9 Merge branch 'Aufinal/single_checkout' into 'master'
Fix "Checkout is not iterable" error

See merge request klub-dev-ens/gestioCOF!483
2021-02-07 16:40:48 +01:00
Martin Pépin
7081380058
Only redirect / → /gestion in development 2021-02-07 16:29:47 +01:00
Ludovic Stephan
288de95c49 Checkout form is single-option now 2021-02-06 18:58:25 +01:00
Martin Pépin
9a01d1e877
CHANGELOG: add missing items in the v0.9 release 2021-02-06 17:17:47 +01:00
Martin Pépin
10746c0469
Version 0.9 2021-02-06 17:01:22 +01:00
Basile Clement
5c8eca15b6 Merge branch 'kerl/admin_autocomplete' into 'master'
Admin: on utilise la recherche builtin de Django

See merge request klub-dev-ens/gestioCOF!476
2021-02-04 22:16:27 +01:00
Martin Pepin
ef64f9ce5c Merge branch 'Buro_rights_by_BDS' into 'master'
Added basic buro right handling while updating member

See merge request klub-dev-ens/gestioCOF!482
2021-01-30 15:06:52 +01:00
Alseidon
9762838921
Basic Buro right handling - minor corrections 2021-01-30 14:59:04 +01:00
Alseidon
bf6d6d6430
Added basic buro right handling while updating member 2021-01-30 14:57:24 +01:00
Martin Pepin
ba9aa06b4f Merge branch 'dodo/bds_export_csv' into 'master'
Dodo/bds export csv

Closes #285

See merge request klub-dev-ens/gestioCOF!481
2021-01-29 19:38:55 +01:00
Dorian Lesbre
880dc31353 Update CHANGELOG.md 2021-01-29 09:37:37 +01:00
Dorian Lesbre
9a78fca507 Switched to named url 2021-01-29 09:34:56 +01:00
Ludovic Stephan
4bc56d34e0 Fix tests 2021-01-21 21:08:57 +01:00
Ludovic Stephan
79f0757e9f Fix kfet stats 2021-01-21 20:55:23 +01:00
Dorian Lesbre
a2eed13717 Added download button to home template 2021-01-21 20:38:15 +01:00
Dorian Lesbre
830aba984e Added bds/members to export members list as CSV 2021-01-21 20:32:36 +01:00
Ludovic Stephan
33319cfe76 Merge branch 'newbie' into 'master'
Reset comptes COF

See merge request klub-dev-ens/gestioCOF!479
2021-01-07 09:32:33 +01:00
Alseidon
44b001bd3c Satisfy Lord Black 2021-01-07 09:19:56 +01:00
Martin Pepin
ab9d95055e Merge branch 'Tragicus/kfetTriArticles' into 'master'
kfet articles vendus en premier dans inventaire et commandes

Closes #219

See merge request klub-dev-ens/gestioCOF!477
2021-01-06 21:41:39 +01:00
Martin Pépin
40391d8814
Update CHANGELOG.md 2021-01-06 21:32:41 +01:00
Martin Pépin
681507f211
Happy new year! 2021-01-06 21:31:47 +01:00
Ludovic Stephan
7f133316a4 Merge branch 'Aufinal/black_required' into 'master'
Add black to requirements-devel

See merge request klub-dev-ens/gestioCOF!480
2020-12-17 18:58:59 +01:00
Ludovic Stephan
0bdbcf59fa Add black to requirements-devel 2020-12-10 16:46:53 +01:00
Ludovic Stephan
0bad404b71 Merge branch 'Dodo/date_fermeture_bda' into 'master'
Ajout date de fermeture de tirage BDA sur la page d'acceuil

Closes #172

See merge request klub-dev-ens/gestioCOF!478
2020-12-10 14:20:56 +01:00
Alseidon
c100f2fc8d Version 1.1 remise à zéro comptes COF 2020-12-09 23:00:00 +01:00
Alseidon
ba74779f95 Version 1.0 remise à zéro comptes COF 2020-12-09 22:40:32 +01:00
Quentin VERMANDE
035bbe68a5 make black happy 2020-12-09 22:22:12 +01:00
Alseidon
319db68655 Ra0 effective 2020-12-09 22:11:21 +01:00
Quentin VERMANDE
9d2c13e67c kfetTriArticles 2020-12-09 22:03:54 +01:00
Alseidon
73c068055b Remise à zéro basique comptes COF 2020-12-09 21:57:40 +01:00
Dorian Lesbre
30ce8d13af Ajout date de fermeture de tirage BDA sur la page d'acceuil 2020-12-09 21:16:49 +01:00
Ludovic Stephan
340f8f16a7 Merge branch 'kerl/fix_vagrant' into 'master'
Mise à jour du setup vagrant

See merge request klub-dev-ens/gestioCOF!475
2020-12-07 20:56:09 +01:00
Martin Pépin
0ce1e62586
Fichier bootstrap.sh mieux commenté 2020-12-07 20:09:25 +01:00
Martin Pépin
783fe1de32
Liste des paquets dans un fichier séparé 2020-12-07 20:09:24 +01:00
Martin Pépin
49fde85187
Admin: on utilise la recherche builtin de Django 2020-12-04 19:33:17 +01:00
Martin Pepin
479e751b7c Merge branch 'Aufinal/can_resell_paid' into 'master'
On peut revendre une place dès qu'on l'a payée

Closes #277

See merge request klub-dev-ens/gestioCOF!473
2020-12-04 18:01:22 +01:00
Martin Pépin
f2c1ff2abd
Update CHANGELOG 2020-12-04 17:53:56 +01:00
Ludovic Stephan
8b73460165
Make flake8 happy 2020-12-04 17:52:33 +01:00
Ludovic Stephan
411d7e7dce
On peut revendre une place qu'on a payée 2020-12-04 17:52:21 +01:00
Martin Pepin
f952d50b12 Merge branch 'Aufinal/email_validation' into 'master'
Utilise un EmailField pour valider des emails

See merge request klub-dev-ens/gestioCOF!471
2020-12-04 17:29:07 +01:00
Ludovic Stephan
7324a72e6e Merge branch 'kerl/make_kfetloaddevdata_idempotent' into 'master'
Rend kfetloaddevdata idempotent

See merge request klub-dev-ens/gestioCOF!474
2020-12-04 17:17:38 +01:00
Martin Pépin
ad73cc987d
CHANGELOG 2020-12-04 17:16:35 +01:00
Ludovic Stephan
e9e0c79b40
Migration 2020-12-04 17:15:15 +01:00
Ludovic Stephan
badee498a3
Use EmailField for email field 2020-12-04 17:15:15 +01:00
Martin Pepin
72cd55716b Merge branch 'Aufinal/inventory_delete' into 'master'
Permet l'annulation d'un inventaire

Closes #251

See merge request klub-dev-ens/gestioCOF!457
2020-12-04 17:13:32 +01:00
Martin Pépin
a7cbd2d451
CHANGELOG 2020-12-04 17:02:36 +01:00
Ludovic Stephan
b9699637aa
Message de confirmation plus clair 2020-12-04 17:01:25 +01:00
Ludovic Stephan
521be6db85
Tests 2020-12-04 17:01:25 +01:00
Ludovic Stephan
f3701d91fc
Url and template for InventoryDeleteView 2020-12-04 17:01:25 +01:00
Ludovic Stephan
59dacda37d
Inventory deletion view 2020-12-04 17:01:25 +01:00
Martin Pépin
7f58b5fa00
Vagrant: toutes les units systemd sont là 2020-12-04 16:58:25 +01:00
Martin Pépin
df222f18a3
Update the vagrant config → should work now 2020-12-04 16:10:27 +01:00
Martin Pépin
5d22a4cac4
Rend kfetloaddevdata idempotent
Problème :

Le script assigne des trigrammes 001, 002, 003, etc aux comptes COF des
Gaulois et des Romains en utilisant l'ordre du queryset
CofProfile.objects.all().
L'ordre des comptes dans le queryset n'est pas spécifié et peut varier
d'une exécution à l'autre, ça pose problème dans la suite :

Account.objects.get_or_create(trigramme=trigramme, cofprofile=profile)

Cette command essaie de créer un nouveau trigramme pour certains comptes
quand l'ordre change.

Solution :

Ordonner le queryset.
2020-12-04 12:44:09 +01:00
Martin Pépin
cc3a436750
Version 0.8 2020-12-03 20:22:31 +01:00
Ludovic Stephan
404d3f4f4c Merge branch 'Aufinal/spectacle_paid' into 'master'
Fix `paid` field in `bda/spectacles`

See merge request klub-dev-ens/gestioCOF!472
2020-10-29 11:15:41 +01:00
Ludovic Stephan
43fcdc8526 Fix paid field in bda/spectacles 2020-10-28 14:35:45 +01:00
Ludovic Stephan
35f896b40f CHANGELOG 2020-10-23 10:25:23 +02:00
Ludovic Stephan
fb1a38cff3 Merge branch 'Aufinal/bda_admin_misc' into 'master'
Ergonomie de l'admin du BdA

Closes #276

See merge request klub-dev-ens/gestioCOF!469
2020-10-23 10:11:15 +02:00
Ludovic Stephan
f88795a60e Use same qset for every field 2020-10-22 19:34:59 +02:00
Ludovic Stephan
0ffebdf82f Merge branch 'Aufinal/meta' into 'master'
Fix : autocomplétion sans classe `Meta`

See merge request klub-dev-ens/gestioCOF!468
2020-10-22 18:54:17 +02:00
Ludovic Stephan
147b8514ef Limite les select au tirage concerné 2020-10-21 18:22:48 +02:00
Ludovic Stephan
d535cf24a3 Migration 2020-10-21 18:22:19 +02:00
Ludovic Stephan
84dab59c72 Ordre des participants + unicité 2020-10-21 18:22:05 +02:00
Ludovic Stephan
22cf0d403e Permet d'archiver un tirage 2020-10-21 18:21:40 +02:00
Ludovic Stephan
a525cffaff Fix participant autocomplete 2020-10-21 16:02:01 +02:00
Martin Pepin
1af602c9f7 Merge branch 'Aufinal/listing' into 'master'
Indique si les places sont sur listing

Closes #213

See merge request klub-dev-ens/gestioCOF!467
2020-09-22 21:48:40 +02:00
Martin Pépin
8a17aa2caa
Update CHANGELOG 2020-09-22 21:35:50 +02:00
Ludovic Stephan
7a9d96d83a
Indique si les places sont sur listing 2020-09-22 21:34:53 +02:00
Martin Pépin
3869c02dfa
Merge branch 'Aufinal/fix-fa-again' into master 2020-09-22 21:23:49 +02:00
Martin Pépin
848eb2274a
Update CHANGELOG 2020-09-22 21:23:20 +02:00
Ludovic Stephan
ebd8b7ccdb
Fix fa path in petitscours 2020-09-22 21:22:16 +02:00
Martin Pépin
3c6ab35390
Update CHANGELOG 2020-09-22 21:20:14 +02:00
Martin Pepin
57901c0013 Merge branch 'Aufinal/stat_2' into 'master'
Repassage sur les stats

Closes #246 and #255

See merge request klub-dev-ens/gestioCOF!462
2020-09-22 21:06:46 +02:00
Ludovic Stephan
d172dad0ab Merge branch 'thubrecht/creation-compte' into 'master'
Empêche la modification des informations COF lors de la création d'un compte K-Psul

Closes #230

See merge request klub-dev-ens/gestioCOF!464
2020-09-21 16:43:17 +02:00
Tom Hubrecht
d0b7000747 Empêche la modification des informations COF lors de la création d'un compte K-Psul 2020-09-19 19:14:44 +02:00
Martin Pepin
84ff0d7182 Merge branch 'Aufinal/history_form' into 'master'
On utilise un vrai formulaire pour l'historique

Closes #242

See merge request klub-dev-ens/gestioCOF!461
2020-09-17 21:04:42 +02:00
Martin Pepin
600927b21c Merge branch 'Aufinal/rip-custommail' into 'master'
Supprime `custommail` de gestioCOF

Closes #227

See merge request klub-dev-ens/gestioCOF!459
2020-09-17 20:22:11 +02:00
Ludovic Stephan
d965050563 Fix tests again 2020-09-16 19:31:10 +02:00
Ludovic Stephan
a14c9d9574 Fix tests 2020-09-16 19:19:29 +02:00
Ludovic Stephan
8f9c94fe10 Plein de nettoyage partout 2020-09-16 17:16:49 +02:00
Ludovic Stephan
46f447ec5d Formulaires pour nettoyage 2020-09-16 17:16:14 +02:00
Ludovic Stephan
4dbf11f91e Template tweaks 2020-09-15 21:10:36 +02:00
Martin Pepin
569ce0ba25 Merge branch 'Aufinal/open_password' into 'master'
Fix : fermeture manuelle de la K-Fêt avec mot de passe

Closes #183

See merge request klub-dev-ens/gestioCOF!460
2020-09-15 20:22:05 +02:00
Ludovic Stephan
aa955a06ef Fin des adaptations 2020-09-15 20:05:54 +02:00
Ludovic Stephan
a9eb32217f Adapte history.js pour serialize() 2020-09-15 20:05:32 +02:00
Ludovic Stephan
c7998f56f0 Datetimepicker tweaks 2020-09-15 20:05:06 +02:00
Ludovic Stephan
a6e58dcd68 On utilise le render par défaut 2020-09-15 20:04:35 +02:00
Ludovic Stephan
49591fa67e Use form to clean data 2020-09-15 20:03:37 +02:00
Ludovic Stephan
9f9724b1d1 Arrow function works now 2020-09-15 19:57:27 +02:00
Ludovic Stephan
205dc93f4b FilterHistoryForm est un formulaire décent 2020-09-15 19:40:45 +02:00
Martin Pepin
7f6d4527ed Merge branch 'Aufinal/petitscours_uniqueness' into 'master'
Fix : KeyError sur les petits cours

See merge request klub-dev-ens/gestioCOF!458
2020-09-15 19:38:15 +02:00
Ludovic Stephan
43a2f8db53 Use arrow functions everywhere for consistency 2020-09-15 16:44:32 +02:00
Ludovic Stephan
ba4cc01ed4 Fix formatting 2020-09-15 16:37:41 +02:00
Ludovic Stephan
11d94ecba8 Fix this shenanigans 2020-09-15 16:34:19 +02:00
Ludovic Stephan
82d58d23c9 Remove all traces of custommail 2020-09-15 11:49:32 +02:00
Ludovic Stephan
6377dd5c95 BdA : tests 2020-09-15 11:49:18 +02:00
Ludovic Stephan
f364928004 Remove custommail in bda 2020-09-15 11:49:05 +02:00
Ludovic Stephan
dc070278f7 Gestioncof : tests 2020-09-15 11:48:36 +02:00
Ludovic Stephan
561a121e04 Remove custommail in gestioncof 2020-09-15 11:48:21 +02:00
Ludovic Stephan
b03cf05ef7 Petits cours : tests 2020-09-15 11:47:53 +02:00
Ludovic Stephan
edf6a03bc4 Phase out custommail in petitscours 2020-09-15 11:47:28 +02:00
Ludovic Stephan
eb3cba31a7 Emails as text files 2020-09-15 11:15:12 +02:00
Ludovic Stephan
1ffda1a5c4 Better uniqueness checks 2020-09-14 11:40:21 +02:00
Martin Pépin
2bc97a115c
Version 0.7.2 2020-09-08 20:06:26 +02:00
Ludovic Stephan
b8072f4346 Merge branch 'kerl/404' into 'master'
Nouvelle page 404

See merge request klub-dev-ens/gestioCOF!454
2020-09-07 20:33:43 +02:00
Martin Pépin
cedd3cf816
404: english text looks better in italic 2020-09-07 20:16:16 +02:00
Martin Pépin
2c833daa7f
404.html: English version + tighter header 2020-09-07 20:10:34 +02:00
Martin Pepin
2a05c2247c
Apply suggestion to gestioncof/templates/404.html 2020-09-07 20:10:34 +02:00
Martin Pépin
c957ab2b72
Add K-Psul on the 404 page 2020-09-07 20:10:34 +02:00
Martin Pépin
98cce25f4c
cofsite-looking 404 ? 2020-09-07 20:10:26 +02:00
Martin Pepin
ba6ddfc516 Merge branch 'Aufinal/kfet-auth' into 'master'
Groupes et perms K-Fêt

See merge request klub-dev-ens/gestioCOF!438
2020-09-07 20:09:19 +02:00
Ludovic Stephan
c5d7eb9d30 Move permission handling to loadkfetdevdata 2020-09-07 14:57:41 +02:00
Ludovic Stephan
d3185f25c3 Black 2020-09-07 14:57:41 +02:00
Ludovic Stephan
007b5006d4 Use convenience imports 2020-09-07 14:57:41 +02:00
Ludovic Stephan
2d36c85085 Fix dev data 2020-09-07 14:57:41 +02:00
Ludovic Stephan
d6fa738a25 Fix tests 2020-09-07 14:57:41 +02:00
Ludovic Stephan
c145191e55 Use new models and mixins 2020-09-07 14:57:41 +02:00
Ludovic Stephan
91852bd4a0 Template fixes 2020-09-07 14:57:41 +02:00
Ludovic Stephan
6f5fa19fc3 M2M form mixin 2020-09-07 14:57:41 +02:00
Ludovic Stephan
e92d50593c New models 2020-09-07 14:57:41 +02:00
Ludovic Stephan
0590bc3aab Merge branch 'kerl/kfet_autocomplete_fix' into 'master'
Remets le lien pour inscrire des nouveaux comptes en K-Fêt sur la page d'autocomplétion

See merge request klub-dev-ens/gestioCOF!456
2020-09-07 14:43:04 +02:00
Martin Pépin
3286ad09df
Update CHANGELOG 2020-09-07 11:35:25 +02:00
Martin Pépin
3da0a613f7
K-Fêt autocompletion shows the 'new user' link 2020-09-07 11:32:28 +02:00
Ludovic Stephan
34be9e2393 Merge branch 'kerl/fix_exte_login_bug' into 'master'
Meilleure gestion des erreurs dans le formulaire de login Exté → pas de crash

See merge request klub-dev-ens/gestioCOF!455
2020-09-06 20:59:48 +02:00
Martin Pépin
97bdeed97a
Prevent a crash in exte login form error handling 2020-09-05 23:53:31 +02:00
Martin Pépin
8016b16904
Version 0.7.1 2020-09-05 00:02:28 +02:00
Ludovic Stephan
6e8926595d Merge branch 'kerl/gestion_prefix' into 'master'
Ajoute le préfixe /gestion dans toutes les urls sauf celles de la K-Fêt et de Wagtail

Closes #256

See merge request klub-dev-ens/gestioCOF!450
2020-09-02 23:45:34 +02:00
Ludovic Stephan
a9b6bc65a2 Merge branch 'kerl/discard_weird_ldap_users' into 'master'
Ignore les comptes LDAP bizarres (e.g. root)

See merge request klub-dev-ens/gestioCOF!453
2020-09-02 23:44:33 +02:00
Martin Pépin
b1fd6e6021
Discard the (weird) ldap accounts that have no uid 2020-09-02 21:34:21 +02:00
Martin Pepin
576d43f44d Merge branch 'sakarah/club-email-bug' into 'master'
Replace all "pont" by "." in COF clubs emails

See merge request klub-dev-ens/gestioCOF!452
2020-09-02 20:42:36 +02:00
Martin Pépin
c55a2c8c8e
Update changelog 2020-09-02 20:35:17 +02:00
Guillaume Bertholon
65c979ea59
Replace all "pont" by "." in COF clubs emails
This patches wrongly displayed "Contact : fromages@lists.enspontfr" on
https://cof.ens.fr/gestion/sitecof/annuaires-des-clubs/
2020-09-02 20:34:25 +02:00
Martin Pépin
dcd592ed11
Fix 100 tests wrt. 754a0b70e (big url changes) 2020-09-02 20:28:19 +02:00
Martin Pépin
e401303a08
User-friendly redirect : / → /gestion 2020-09-02 20:25:46 +02:00
Martin Pépin
2b72f3b40b
All pages go under /gestion except wagtail & k-fet 2020-09-02 20:23:11 +02:00
Martin Pepin
2aae281120 Merge branch 'Aufinal/urls' into 'master'
Améliore les URLs de gestiocof

Closes #265

See merge request klub-dev-ens/gestioCOF!439
2020-09-02 20:15:12 +02:00
Ludovic Stephan
1387da3b54
black 20 2020-09-02 20:06:28 +02:00
Ludovic Stephan
e868e6eb18
No bds prefix for prod 2020-09-02 20:06:28 +02:00
Ludovic Stephan
fc988e3fad
Fix isort 2020-09-02 20:06:28 +02:00
Ludovic Stephan
205b5c206b
Fix tests 2020-09-02 20:06:28 +02:00
Ludovic Stephan
ab9b4d14ef
Some changes to mega urls 2020-09-02 20:06:28 +02:00
Ludovic Stephan
5f8b8661bf
Better URL management 2020-09-02 20:06:28 +02:00
Ludovic Stephan
858a0c61e2
Rend à gestiocof ce qui est à gestiocof 2020-09-02 20:06:27 +02:00
Martin Pepin
12d3ef0c02 Merge branch 'Aufinal/wakemeup' into 'master'
On est en septembre !

See merge request klub-dev-ens/gestioCOF!451
2020-09-02 19:57:04 +02:00
Ludovic Stephan
da40ed1d8c Migration 2020-09-01 15:27:28 +02:00
Martin Pépin
f10bd1eea2
Update changelog 2020-08-30 12:48:51 +02:00
Martin Pepin
8576023b42 Merge branch 'Evarin/css-sitecof' into 'master'
Améliorations CSS + directoryentrypage sitecof encore

See merge request klub-dev-ens/gestioCOF!447
2020-08-30 12:47:11 +02:00
Evarin
24eaaa277f Sitecof : Affiche titre des pages dans <title> 2020-08-30 12:11:13 +02:00
Evarin
8f4e3bb048 isort linting migration 2020-08-29 23:39:31 +02:00
Evarin
7775e45b60 Black linting migration 2020-08-29 23:23:52 +02:00
Evarin
b3ada0eb89 Sitecof css modifs mineures 2020-08-29 23:21:20 +02:00
Evarin
74b9721fbd Sitecof : Champ libre dans directoryentry 2020-08-29 23:15:28 +02:00
Evarin
7db75c0060 Sitecof CSS ++ 2020-08-29 23:14:19 +02:00
Martin Pepin
d96b3d26b6 Merge branch 'Evarin/css-sitecof' into 'master'
Améliorations mineures CSS sitecof

See merge request klub-dev-ens/gestioCOF!446
2020-08-29 22:54:29 +02:00
Evarin
72210e1980 Sitecof : améliogrations CSS 2020-08-29 22:18:32 +02:00
Evarin
359f85a42d Sitecof : CSS fixes 2020-08-29 21:34:28 +02:00
Martin Pépin
95cac47f4e
Version 0.7 2020-08-29 19:28:38 +02:00
Martin Pepin
7dc32add35 Merge branch 'Aufinal/kfet_autocomplete' into 'master'
Rajoute un nombre min de caractères pour la création d'un compte

See merge request klub-dev-ens/gestioCOF!440
2020-08-29 12:25:43 +02:00
Martin Pepin
0011cfe8f7 Merge branch 'Aufinal/bds_perms' into 'master'
Le groupe BDS a des permissions normales

Closes #263

See merge request klub-dev-ens/gestioCOF!444
2020-08-29 12:24:35 +02:00
Ludovic Stephan
5a7c4f64d5 changelog 2020-08-28 18:46:13 +02:00
Ludovic Stephan
46893a8df5 Min chars for autocompletion 2020-08-28 18:45:07 +02:00
Ludovic Stephan
81b45f74e3 changelog 2020-08-28 18:42:37 +02:00
Ludovic Stephan
c6dfcea5e2 Remove signals import 2020-08-28 18:41:40 +02:00
Ludovic Stephan
198e456c22 Fix BDS group perms 2020-08-28 18:41:40 +02:00
Martin Pepin
1518f4c703 Merge branch 'Aufinal/misc_bds' into 'master'
Quelques améliorations pour le BDS

Closes #270

See merge request klub-dev-ens/gestioCOF!443
2020-08-28 18:38:49 +02:00
Martin Pépin
2d59565f61
Update changelog 2020-08-28 18:23:20 +02:00
Ludovic Stephan
d3384dc5fc
Remove context processor 2020-08-28 18:23:20 +02:00
Ludovic Stephan
e7cc705350
Add member count to home 2020-08-28 18:23:20 +02:00
Ludovic Stephan
8fa635773c
Notifications are closable 2020-08-28 18:23:20 +02:00
Ludovic Stephan
1ac3e0f976
Plug logout link 2020-08-28 18:23:19 +02:00
Ludovic Stephan
f811230c25
Add comment field 2020-08-28 18:23:19 +02:00
Martin Pepin
74c3afe9ca Merge branch 'Aufinal/black20' into 'master'
Fix la CI pour black

See merge request klub-dev-ens/gestioCOF!445
2020-08-28 18:18:15 +02:00
Ludovic Stephan
0875ef1278 Black v20 2020-08-28 18:00:54 +02:00
Martin Pepin
1d707aad41 Merge branch 'Aufinal/delete_bds_user' into 'master'
Possibilité de supprimer un utilisateur sur gestioBDS

Closes #271

See merge request klub-dev-ens/gestioCOF!442
2020-08-25 20:17:51 +02:00
Martin Pépin
fef19024d8
Update changelog 2020-08-25 20:04:26 +02:00
Ludovic Stephan
566e968849
Fix cance button 2020-08-25 20:04:26 +02:00
Ludovic Stephan
55c69ae42b
Styling 2020-08-25 20:04:26 +02:00
Ludovic Stephan
40839458a5
Form logic for user deletion 2020-08-25 20:04:26 +02:00
Ludovic Stephan
a259dd524f
UserDelete view 2020-08-25 20:04:26 +02:00
Ludovic Stephan
85c750d380
Delete unused template 2020-08-25 20:04:26 +02:00
Martin Pépin
826e45f619
Move CaptchaFrom from views.py to forms.py 2020-08-25 19:24:54 +02:00
Martin Pépin
5989f65154
Fix linting issues 2020-08-25 19:24:02 +02:00
Martin Pepin
2cf0ccbb6b Merge branch 'Aufinal/ldap_mail' into 'master'
Utilise le mail LDAP lors de l'inscription d'utilisateurs

Closes #268

See merge request klub-dev-ens/gestioCOF!437
2020-08-25 19:08:25 +02:00
Ludovic Stephan
1677768177 Merge branch 'kerl/bds_authens' into 'master'
Authens pour le BDS

See merge request klub-dev-ens/gestioCOF!441
2020-08-24 15:38:24 +02:00
Martin Pépin
7a7e02adab
Bump authens to 0.1b0 2020-08-24 15:30:50 +02:00
Martin Pépin
62d26560d9
Fix BDS {MEDIA,STATIC}_{URL,ROOT} 2020-08-24 14:56:26 +02:00
Martin Pépin
df9639715b
Move COF-specific settings (channels) to common.py 2020-08-24 14:55:27 +02:00
Evarin
72237fef60 Sitecof : captcha pour les listes mail 2020-08-22 12:34:08 +02:00
Ludovic Stephan
8fa07bb845 Fix tests 2020-08-03 14:54:58 +02:00
Ludovic Stephan
7931f50611 Use ldap email 2020-08-03 14:30:21 +02:00
Ludovic Stephan
910536c6d3 Add email to ldap autocomplete 2020-08-03 14:30:12 +02:00
Martin Pépin
3d830884b1
Use authens in GestioBDS 2020-07-30 12:04:04 +02:00
Martin Pépin
9110e5b185
Update changelog 2020-07-27 23:10:18 +02:00
Ludovic Stephan
22f60163fe Merge branch 'kerl/bds_rm_certificat_medical' into 'master'
Le BDS n'a pas besoin du certificat médical

See merge request klub-dev-ens/gestioCOF!435
2020-07-27 22:41:14 +02:00
Martin Pépin
8661716df9
BDS doesn't need the certificate file 2020-07-27 22:14:20 +02:00
Martin Pepin
ae64f09869 Merge branch 'Aufinal/bds_create_user' into 'master'
Création d'utilisateurs pour le BDS

See merge request klub-dev-ens/gestioCOF!433
2020-07-27 21:41:12 +02:00
Ludovic Stephan
422e2f7b42 Fix date input 2020-07-26 22:34:56 +02:00
Ludovic Stephan
f990934425 On utilise un vrai dict 2020-07-26 22:24:41 +02:00
Ludovic Stephan
effed1b5c5 Fix template 2020-07-26 22:12:38 +02:00
Ludovic Stephan
efbb9c2be3 Encore plus de doc 2020-07-26 22:10:09 +02:00
Ludovic Stephan
a6c9cf11bd Meilleure doc 2020-07-26 22:10:09 +02:00
Ludovic Stephan
26fa9dc898 Add create user from scratch 2020-07-26 22:10:09 +02:00
Ludovic Stephan
ee1d158f2d Plug into autocomplete and urls 2020-07-26 22:10:09 +02:00
Ludovic Stephan
5e5b224f89 User creation views 2020-07-26 22:10:09 +02:00
Ludovic Stephan
f33416b712 Use mixin in UserUpdateView 2020-07-26 22:10:09 +02:00
Ludovic Stephan
b6626093e5 Mixin pour forms multiples 2020-07-26 22:10:09 +02:00
Martin Pepin
15936751c0 Merge branch 'Aufinal/bulma_bds' into 'master'
CSS pour le BDS avec Bulma

See merge request klub-dev-ens/gestioCOF!432
2020-07-26 19:37:40 +02:00
Ludovic Stephan
9efc200f74 Fusionne base et base_layout 2020-07-26 19:24:40 +02:00
Ludovic Stephan
54e8f95667 Logout button fix 2020-07-26 19:06:38 +02:00
Ludovic Stephan
a5ccd40ec1 Merge branch 'kerl/prod_hotfix' into 'master'
Bump some channels/redis requirements

See merge request klub-dev-ens/gestioCOF!434
2020-07-26 17:24:38 +02:00
Martin Pépin
b4fbc3edf8
BDS CSS: use plain black for text 2020-07-26 17:17:20 +02:00
Martin Pépin
eb10c904e0
Bump some channels/redis requirements 2020-07-25 22:18:43 +02:00
Ludovic Stephan
c8c8c6abc8 Message fixes 2020-07-20 19:06:19 +02:00
Ludovic Stephan
e64f405299 Tweaks 2020-07-20 11:34:28 +02:00
Ludovic Stephan
aa2f691f1e Chromium support 2020-07-20 11:30:31 +02:00
Ludovic Stephan
8cd9434664 Fix autocomplete width 2020-07-20 11:30:31 +02:00
Ludovic Stephan
e323f2f755 Bulmafy navbar 2020-07-20 11:30:31 +02:00
Ludovic Stephan
deae1c4639 FontAwesome : gestioncof -> shared 2020-07-20 11:30:31 +02:00
Ludovic Stephan
62281cb3b7 Templates update 2020-07-20 11:30:31 +02:00
Ludovic Stephan
6454931e70 bds is now in scss 2020-07-20 11:30:31 +02:00
Ludovic Stephan
6e88f1a887 Form utils for bulma 2020-07-20 11:30:31 +02:00
Ludovic Stephan
2e28986503 Bulma files 2020-07-20 11:30:31 +02:00
Ludovic Stephan
b24935b938 Merge branch 'kerl/bds_update_user' into 'master'
BDS: vue pour modifier un compte existant

See merge request klub-dev-ens/gestioCOF!430
2020-07-20 11:25:01 +02:00
Martin Pépin
ac06211841 Make bds tests resilient to LOGIN_URL changes 2020-07-20 11:12:01 +02:00
Martin Pépin
5c1e2e9cda Basic tests for BDS registration views 2020-07-20 11:12:01 +02:00
Martin Pépin
c1e48579f1 BDS: UserUpdateView 2020-07-20 11:11:53 +02:00
Ludovic Stephan
c6a6e7fafa Merge branch 'kerl/factor_autocompletion_views3' into 'master'
Vue et template génériques d'autocomplétion

See merge request klub-dev-ens/gestioCOF!429
2020-07-18 17:46:04 +02:00
Martin Pépin
be064262da
Fix kfet autocompletion hightlighting 2020-07-18 16:24:07 +02:00
Martin Pépin
9ac030fd16
Instantiate the Compose classes in their own file 2020-07-18 16:07:12 +02:00
Martin Pépin
7caee5665b
Make isort happy… 2020-07-18 16:07:12 +02:00
Martin Pépin
e7517195cd
Generic autocompletion view 2020-07-18 16:07:12 +02:00
Martin Pépin
30783d677b
Minor changelog update, version 0.5 2020-07-11 10:09:25 +02:00
Martin Pépin
c863b2010e
Update changelog 2020-07-05 20:06:33 +02:00
Ludovic Stephan
24d7d90c28 Merge branch 'kerl/factor_autocompletion_views2' into 'master'
Petite réorganisation de l'autocomplétion

See merge request klub-dev-ens/gestioCOF!428
2020-07-05 18:20:26 +02:00
Martin Pépin
f2b1962e1c
Autocompletion: more idiomatic permission handling 2020-07-05 16:38:59 +02:00
Ludovic Stephan
68ccd4722f Merge branch 'kerl/factor_autocompletion_views1' into 'master'
Mécanisme de dé-duplication des résultats plus souple pour l'autocomplétion

See merge request klub-dev-ens/gestioCOF!427
2020-07-05 11:25:35 +02:00
Martin Pépin
9a90f19502
Separate the autocompletion logic form the views 2020-07-05 11:15:50 +02:00
Martin Pépin
fbbc9937f6
Fix a typo 2020-07-05 11:14:51 +02:00
Martin Pépin
e9f00b4f06
Update the isort config for version 5.* 2020-07-04 13:40:32 +02:00
Martin Pépin
c7ca96bce5
Autocompletion: new de-duplication mechanism 2020-07-04 13:06:24 +02:00
Ludovic Stephan
637572ab58 Merge branch 'kerl/bds_autocomplete' into 'master'
Autocomplétion du BDS et deuxième ébauche de page d'accueil

See merge request klub-dev-ens/gestioCOF!422
2020-07-01 23:26:01 +02:00
Ludovic Stephan
28370c8e67 Merge branch 'kerl/bds_settings' into 'master'
Séparation des settings cof / bds

See merge request klub-dev-ens/gestioCOF!420
2020-06-30 12:47:46 +02:00
Martin Pépin
701ea96a90
BDS autocompletion: add missing span in html 2020-06-29 20:49:02 +02:00
Martin Pépin
de1bba3695
Don't crash on LDAP errors 2020-06-29 20:47:36 +02:00
Martin Pépin
56f1edebe3
BDS: fancier home page 2020-06-29 20:47:36 +02:00
Martin Pépin
c52bac05b3
Restrict bds views to the staff 2020-06-29 20:47:36 +02:00
Martin Pépin
5d24786e20
BDS: user search on the home page 2020-06-29 20:47:35 +02:00
Martin Pépin
bca75dbf98
Add user-search in the BDS app 2020-06-29 20:47:35 +02:00
Martin Pépin
0789da7bed
Move the 'utils' template tags to the shared app 2020-06-29 20:47:35 +02:00
Martin Pépin
f6458074b2
Better documentation for show_toobar 2020-06-29 20:45:52 +02:00
Martin Pépin
eadfd1d3cd
Use cof.settings.local for migration checks 2020-06-29 20:45:52 +02:00
Martin Pépin
3a34ab4462
Make events tests independent of LOGIN_URL 2020-06-29 20:45:52 +02:00
Martin Pépin
25b603d667
only run relevant tests in cof/bds CI 2020-06-29 20:45:52 +02:00
Martin Pépin
f26d330973
Fix settings.local.ALLOWED_HOSTS 2020-06-29 20:45:52 +02:00
Martin Pépin
7a52e841e6
Use the new settings in gitlab-ci 2020-06-29 20:45:52 +02:00
Martin Pépin
9a3914ece6
Add wsgi file 2020-06-29 20:45:52 +02:00
Martin Pépin
6a32a72c15
One url file to rule them all,
one url file to find them
One url file to bring them all,
and in the darkness bind them.
2020-06-29 20:45:52 +02:00
Martin Pépin
d464b69b2e
Split settings between COF / BDS / Local 2020-06-29 20:45:52 +02:00
Martin Pépin
d16bf5e6b0
Merge local and dev settings 2020-06-29 20:45:52 +02:00
Ludovic Stephan
1ba6b5753f Merge branch 'kerl/fix_kfet_autocomplete' into 'master'
Passe à `shared.views.autocomplete` pour l'autocomplétion de la K-Fêt

See merge request klub-dev-ens/gestioCOF!425
2020-06-25 17:16:59 +02:00
Ludovic Stephan
21fcb5daa9 Merge branch 'kerl/fix_ldap' into 'master'
Switch to python-ldap (instead of ldap3)

Closes #264

See merge request klub-dev-ens/gestioCOF!424
2020-06-25 01:20:40 +02:00
Martin Pépin
c5adc6b7d8
Use the new shared autocomplete framework in kfet/ 2020-06-20 19:28:48 +02:00
Martin Pépin
b9ba0a3829
Add missing ldap system dependencies to CI config 2020-06-20 19:08:20 +02:00
Martin Pépin
028b6f6cb7
Switch to python-ldap (instead of ldap3) 2020-06-16 17:21:59 +02:00
Ludovic Stephan
3ca8b45014 Migration for events app 2020-05-20 17:41:25 +02:00
Ludovic Stephan
90fc6aa3e7 Merge branch 'Aufinal/simplify_tests' into 'master'
Utilitaire de tests simplifié

See merge request klub-dev-ens/gestioCOF!421
2020-05-15 16:12:47 +02:00
Martin Pépin
707b7b76db Make events tests deterministic 2020-05-14 21:23:25 +02:00
Ludovic Stephan
6fff995ccd Expand CSVResponseMixin functionality 2020-05-12 01:12:19 +02:00
Ludovic Stephan
9b0440429c Fix ical tests 2020-05-12 00:47:48 +02:00
Ludovic Stephan
50266f2466 Fix tests for python3.7 (?) 2020-05-11 13:03:13 +02:00
Ludovic Stephan
65171d1276 Fix event tests 2020-05-11 01:16:58 +02:00
Ludovic Stephan
3b43ad84b5 Renomme testcases.py -> mixins.py 2020-05-11 00:19:43 +02:00
Ludovic Stephan
bb72a16b64 Lisibilité: t_urls -> reversed_urls 2020-05-10 23:58:46 +02:00
Ludovic Stephan
b1c69eddb5 Meilleure doc (j'espère !) 2020-05-10 23:58:13 +02:00
Ludovic Stephan
88c9187e2e MegaHelpers devient un mixin 2020-05-10 23:56:45 +02:00
Ludovic Stephan
bbe831a226 Sépare un gros fourre-tout en plus petits mixins 2020-05-10 23:54:21 +02:00
Ludovic Stephan
f642b218d0 Consistance dans les noms de fichiers 2020-05-10 23:44:02 +02:00
Ludovic Stephan
cc72f47f00 Merge branch 'kerl/event_options_and_extra_fields' into 'master'
Les événements du nouveau module `events` récupèrent les même fonctionnalités que les événements de `gestioncof`

See merge request klub-dev-ens/gestioCOF!398
2020-05-10 00:53:27 +02:00
Martin Pépin
24180e747e Events: one more validation check 2020-05-08 16:40:18 +02:00
Martin Pépin
5a0cf58d8a Events: more validation & uniqueness constraints 2020-05-08 16:34:35 +02:00
Martin Pépin
d7d4d73af3 typos 2020-05-08 16:34:19 +02:00
Martin Pépin
c2f6622a9f Update changelog 2020-05-08 16:16:37 +02:00
Martin Pépin
8778695e95 Add some more documentation in events.models 2020-05-08 16:14:04 +02:00
Martin Pépin
e0fd3db638 Make events tests deterministic 2020-05-08 16:14:04 +02:00
Martin Pépin
d5e9d09044 Events are configurable
This commit mostly reproduces the structure of gestioncof's events,
renames some stuff and adds a generic export view.
2020-05-08 16:14:04 +02:00
Martin Pepin
6e9dc03bc7 Merge branch 'Evarin/sitecof-improvements' into 'master'
Améliorations site du COF

See merge request klub-dev-ens/gestioCOF!415
2020-05-08 16:13:18 +02:00
Martin Pépin
6384cfc701 Update changelog 2020-05-08 16:04:05 +02:00
Martin Pépin
67d7dafc14 Merge branch 'master' into Evarin/sitecof-improvements 2020-05-08 15:56:42 +02:00
Martin Pépin
1ada8645b8 Black 2020-05-08 15:52:13 +02:00
Ludovic Stephan
d4a9e96e38 Merge branch 'kerl/ci' into 'master'
Bump python and postrgres in CI

See merge request klub-dev-ens/gestioCOF!419
2020-05-08 13:06:29 +02:00
Martin Pépin
abb8cc5a2d Bump python and postrgres in CI 2020-05-08 12:47:03 +02:00
Martin Pepin
5a9ea4234e Merge branch 'Aufinal/simplify_stats' into 'master'
Simplifie massivement les statistiques K-Fêt + étend la période de stats

Closes #257 and #244

See merge request klub-dev-ens/gestioCOF!411
2020-05-08 12:41:18 +02:00
Ludovic Stephan
c9136dbcfa CHANGELOG 2020-05-08 11:15:12 +02:00
Ludovic Stephan
61e4ad9741 Better docstring 2020-05-08 11:14:32 +02:00
Ludovic Stephan
c9dad9465a Fix tests 2020-05-08 11:14:32 +02:00
Ludovic Stephan
f10d6d1a71 Bugfix
Quand un article n'a pas de conso, il a été créé il y a 1s
2020-05-08 11:14:32 +02:00
Ludovic Stephan
97cb9d1f3b Rework stats_manifest
On change la façon dont les vues gèrent l'interface avec `Scale`.
Side effect : on peut avoir l'historique sur tout le temps
2020-05-08 11:14:32 +02:00
Ludovic Stephan
c66fb7eb6f Simplify statistic.js
On supprime des fonctions inutiles, on lint, et on simplifie 2-3 options
inutilisées.
2020-05-08 11:14:32 +02:00
Ludovic Stephan
48ad5cd1c7 Misc cleanup
On utilise SingleObjectMixin partout, et on simplifie 2-3 trucs
2020-05-08 11:14:32 +02:00
Ludovic Stephan
ef35f45ad2 Fusionne deux fonctions chunkify
On rajoute de l'agrégation optionnelle dans la fonction.
2020-05-08 11:14:32 +02:00
Ludovic Stephan
26bcd729bb Supprime le code mort ou redondant 2020-05-08 11:14:32 +02:00
Ludovic Stephan
78ad4402b0 Plus de timezones 2020-05-08 11:14:32 +02:00
Ludovic Stephan
6767ba8e8c Rajoute de la doc partout 2020-05-08 11:14:32 +02:00
Ludovic Stephan
4f15bb9624 CHANGELOG 2020-05-07 18:40:07 +02:00
Martin Pepin
3b2251a1d6 Merge branch 'Aufinal/editable_accounts' into 'master'
Harmonise les comptes non-lisibles ou éditables

Closes #234

See merge request klub-dev-ens/gestioCOF!412
2020-05-07 18:07:07 +02:00
Ludovic Stephan
64ceb813c6 Merge branch 'kerl/autocomplete' into 'master'
L'autocomplétion est isolée et réutilisable par d'autres apps

See merge request klub-dev-ens/gestioCOF!390
2020-05-07 16:28:46 +02:00
Martin Pépin
3b0d4ba58f lstephan's suggestions 2020-05-07 15:44:37 +02:00
Ludovic Stephan
5298a19667 Merge branch 'kerl/merge_shared_utils' into 'master'
Préparation de la vue d'autocompletion pour l'intégration du BDS

See merge request klub-dev-ens/gestioCOF!401
2020-05-07 14:54:50 +02:00
Martin Pépin
b1d8bb04c4 Generic auto-completion mechanism 2020-05-07 14:48:37 +02:00
Martin Pépin
b8cd5f1da5
Drop type hints in shared.views.autocomplete 2020-05-05 22:30:17 +02:00
Martin Pépin
a259b04d9c
Explicative comment about the Type[M] annotation 2020-05-05 22:30:17 +02:00
Martin Pépin
e45ee3fb40
More documentation for ModelSearch 2020-05-05 22:30:17 +02:00
Martin Pépin
d2c6c9da7a
Type hints in shared.views.autocomplete 2020-05-05 22:30:16 +02:00
Martin Pépin
914888d18a
Merge the utils and shared apps 2020-05-05 22:30:16 +02:00
Ludovic Stephan
c8b8c90580 CHANGELOG 2020-04-24 21:03:16 +02:00
Antonin Reitz
922190d20f Merge branch 'Aufinal/transferts_historique' into 'master'
Rajoute les transferts dans l'historique

Closes #77 and #233

See merge request klub-dev-ens/gestioCOF!399
2020-04-23 18:46:30 +02:00
Ludovic Stephan
6362740a77 Fix: history.html marche (à peu près) correctement 2020-04-23 18:11:23 +02:00
Ludovic Stephan
9eebc7fb22 Fix: les transferts apparaissent dans l'historique perso 2020-04-23 18:11:23 +02:00
Ludovic Stephan
2aa06d2954 Simplify transfer view 2020-04-23 18:11:23 +02:00
Ludovic Stephan
931b2c4e1f Refactor js code
Harmonize history denominations
* opegroups/transfergroups -> groups
* opes/transfers -> entries
* snake/camel case -> snake case
2020-04-23 18:11:23 +02:00
Ludovic Stephan
b450cb09e6 Petit refactor 2020-04-23 18:11:23 +02:00
Ludovic Stephan
8d11044610 Fix: pas d'erreur quand pas de compte K-Fêt 2020-04-23 18:11:23 +02:00
Ludovic Stephan
786c8f132f Fix: tests cassés par commit précédent 2020-04-23 18:11:23 +02:00
Ludovic Stephan
677ba5b92e Fix : le ws K-Psul remarche 2020-04-23 18:11:23 +02:00
Ludovic Stephan
fb4455af39 Fix tests 3 2020-04-23 18:11:23 +02:00
Ludovic Stephan
7438445110 Last tweaks 2020-04-23 18:11:23 +02:00
Ludovic Stephan
f7ce2edd87 Plug new history in templates 2020-04-23 18:11:23 +02:00
Ludovic Stephan
0221221d53 On renvoie les promesses 2020-04-23 18:11:23 +02:00
Ludovic Stephan
49ef8b3c15 Pas besoin de ws pour les suppressions 2020-04-23 18:11:23 +02:00
Ludovic Stephan
550a073d51 Fix tests again 2020-04-23 18:11:23 +02:00
Ludovic Stephan
af0de33d4c Suppression des opérations et des transferts 2020-04-23 18:11:23 +02:00
Ludovic Stephan
c95e1818b2 Fix ws tests 2020-04-23 18:11:23 +02:00
Ludovic Stephan
41ad2a15ac Update websocket data 2020-04-23 18:11:23 +02:00
Ludovic Stephan
36d6a4a1cd Déplace la logique de l'historique dans history.js
On change le lock en `window.lock` pour y avoir accès partout
2020-04-23 18:11:23 +02:00
Ludovic Stephan
9b2c4c1f98 Change l'affichage de la date dans l'historique
Fixes #233
2020-04-23 18:11:23 +02:00
Ludovic Stephan
c3b5de336a Gère l'affichage des transferts dans l'historique 2020-04-23 18:11:23 +02:00
Ludovic Stephan
bf117ec070 Renvoie les transferts dans l'historique 2020-04-23 18:11:23 +02:00
Ludovic Stephan
a3b0ea9b8d Fetch transfers in history_json 2020-04-23 18:11:23 +02:00
Evarin
9dabab51db I18n 2020-03-29 16:11:02 +02:00
Evarin
2ad400c5e7 Fixes interface cofcms 2020-03-29 15:36:47 +02:00
Evarin
8a27f70e89 Limite à 4 news sur la page d'accueil 2020-03-29 15:36:19 +02:00
Robin Champenois
fcf29fe6df Merge branch 'sakarah/webfonts-sitecof' into 'master'
Servir les polices de sitecof en local

See merge request klub-dev-ens/gestioCOF!413
2020-03-29 11:50:28 +02:00
Robin Champenois
31e4658766 Merge branch 'sakarah/patch-jquery-path' into 'master'
Corrige les chemins vers jquery pour sitecof

See merge request klub-dev-ens/gestioCOF!414
2020-03-29 11:50:14 +02:00
Guillaume Bertholon
7b554e4778 Corrige les chemins vers jquery pour sitecof 2020-03-28 14:10:24 +01:00
Guillaume Bertholon
fe2f8aaa5a Servir les polices de sitecof en local
Le nouveau site du COF réintroduisait des fontes hostées chez Google.
On s'en débarasse en utilisant des webfontes locales.
2020-03-28 13:59:07 +01:00
Ludovic Stephan
137dd655d1 Harmonise les comptes non-lisibles ou éditables 2020-03-11 22:30:47 +01:00
Martin Pepin
494cd5ddc1 Merge branch 'kerl/sitecof_directory_entry_template' into 'master'
Template pour les entrées d'annuaire (sitecof)

See merge request klub-dev-ens/gestioCOF!394
2020-02-12 18:36:05 +01:00
Martin Pépin
80188fa88d
CMS club page: redirection to parent page 2020-02-12 18:20:33 +01:00
Martin Pépin
4580f8bf0f
Update changelog 2020-02-12 18:20:33 +01:00
Martin Pépin
03e6fe3ef6
Default template for cof directory entries 2020-02-12 18:18:56 +01:00
Martin Pepin
8c75189ce1 Merge branch 'Aufinal/article_charts' into 'master'
Fix: les articles ont de nouveau leur graphe d'usage

Closes #260

See merge request klub-dev-ens/gestioCOF!410
2020-02-08 11:19:50 +01:00
Martin Pépin
68b7219cf5
Update CHANGELOG 2020-02-08 11:06:34 +01:00
Ludovic Stephan
7a828760b3 Répercute les changements en prod 2020-02-08 10:47:55 +01:00
Martin Pépin
5280ec2d18
Update CHANGELOG 2020-01-27 21:17:00 +01:00
Martin Pepin
b0d8b0b7f8 Merge branch 'Aufinal/ukf-display' into 'master'
Fix l'affichage des UKF dans K-Psul

Closes #259

See merge request klub-dev-ens/gestioCOF!409
2020-01-27 21:13:05 +01:00
Ludovic Stephan
bc90de76b6 Fix l'affichage des UKF 2020-01-18 17:01:07 +01:00
Ludovic Stephan
ed97ff466d Merge branch 'kerl/fix-bda-participant-email-list' into 'master'
Les boutons "afficher/cacher" les mails et noms des participant⋅e⋅s d'un spectable BdA fonctionnent à nouveau

See merge request klub-dev-ens/gestioCOF!408
2020-01-18 16:40:57 +01:00
Martin Pépin
6cce9779fa
participants.html: s/participants/participant⋅e⋅s/ 2020-01-18 12:23:45 +01:00
Martin Pépin
2c2872275a
Update CHANGELOG 2020-01-18 12:22:32 +01:00
Martin Pépin
fb3f6b9073
Add missing <script> tag in bda/participants.html 2020-01-18 12:20:39 +01:00
Martin Pépin
28cb35e0b0
Version 0.4.1 2020-01-17 21:54:00 +01:00
Antonin Reitz
79ad1346d3 Merge branch 'Aufinal/hashtag_42' into 'master'
On supporte à nouveau les caractères d'urls dans les trigrammes

See merge request klub-dev-ens/gestioCOF!407
2020-01-17 00:42:25 +01:00
Ludovic Stephan
bb05edfd6b CHANGELOG 2020-01-16 23:24:07 +01:00
Ludovic Stephan
4d3531c2cb Fix special chars in trigramme 2020-01-16 23:20:18 +01:00
Martin Pépin
ff968b68b2
Version 0.4 2020-01-15 22:42:24 +01:00
Ludovic Stephan
84c36b9903 CHANGELOG 2020-01-09 10:43:07 +01:00
Ludovic Stephan
3088098a0a Merge branch 'master' into 'master'
Fixed images not showing up in petitscours

See merge request klub-dev-ens/gestioCOF!406
2020-01-09 10:40:14 +01:00
Julien Malka
f9feff4b24 Wrong use of src -> replaced by vendor 2020-01-07 23:01:19 +01:00
Julien Malka
08d7e12c38 Fixed images not showing up in petitscours 2020-01-07 22:37:37 +01:00
Ludovic Stephan
bd74f4098c Merge branch 'kerl/ci_python_37' into 'master'
CI : les tests tournent sous python 3.5 et python 3.7

See merge request klub-dev-ens/gestioCOF!402
2020-01-07 19:26:56 +01:00
Martin Pepin
ee79281f53 Merge branch 'Aufinal/transfer_formset' into 'master'
Fix : nouveaux formulaires de transfert si le formset est plein

Closes #250

See merge request klub-dev-ens/gestioCOF!404
2020-01-04 16:49:42 +01:00
Martin Pépin
ee4d2d7f0e
CI: run tests on python:3.5 and python:3.7 2020-01-04 16:35:13 +01:00
Martin Pépin
f19b257afd
Update changelog 2020-01-04 16:33:32 +01:00
Ludovic Stephan
87e3795c76 Ajout d'un nouveau transfert si formulaire rempli 2020-01-04 15:31:14 +01:00
Ludovic Stephan
f5d6d91e51 Merge branch 'kerl/happy_new_year' into 'master'
Happy new year!

See merge request klub-dev-ens/gestioCOF!403
2020-01-03 23:41:33 +01:00
Martin Pépin
a1a2aac1f3
K-Fêt: new year, no valid promo… 2020-01-03 17:33:27 +01:00
Ludovic Stephan
c1449d50ce Merge branch 'kerl/bds-buro' into 'master'
petite mise à jour de BDSProfile

See merge request klub-dev-ens/gestioCOF!396
2019-12-28 10:17:20 +01:00
Martin Pepin
e13a5b0e60 Merge branch 'kerl/sitecof_clubs_optional_urls' into 'master'
Dans la description d'un club (ou d'un partenaire du COF), le link est optionel.

See merge request klub-dev-ens/gestioCOF!393
2019-12-26 23:27:20 +01:00
Martin Pépin
858759865e
BDSProfile: s/membre/adhérent⋅e/ 2019-12-26 23:19:41 +01:00
Martin Pépin
8bae013152
BDSProfile: add is_member & cotisation_type fields 2019-12-26 13:11:37 +01:00
Martin Pépin
4d5419fdbc
Use permissions to authenticate bds buro members
I prefer using a permission (namely `bds.is_team`) to determine if a
user is member of the BDS staff rather that using a `is_buro` boolean
field.

We already use this approach is the kfet app
2019-12-26 13:09:38 +01:00
Martin Pépin
2e4d7101ce
Update changelog 2019-12-26 01:03:46 +01:00
Martin Pépin
229b6e55f5
cofsite: make club links optional 2019-12-26 01:02:45 +01:00
Ludovic Stephan
d2ba9471da Merge branch 'kerl/permission_disambiguation' into 'master'
Disambiguation in kfet's permission handling

See merge request klub-dev-ens/gestioCOF!397
2019-12-25 17:45:03 +01:00
Martin Pépin
1f945d1af3
Avoid using get_by_natural_key 2019-12-24 17:14:45 +01:00
Martin Pépin
64c792b11f
Disambiguation in kfet's permission handling
In some places we used to refer to permissions based on their codename
only (the part after the dot "." in the following examples) which can be
ambiguous. Typically, we might define permissions like "bds.is_team" or
"cof.is_team" in the near future ;)
2019-12-24 17:14:45 +01:00
Ludovic Stephan
67e28c704f Merge branch 'kerl/kfet_calendar_links' into 'master'
Met à jour l'url du calendrier de la K-Fêt sur la page d'accueil de GestioCOF

See merge request klub-dev-ens/gestioCOF!392
2019-12-23 11:32:23 +01:00
Martin Pépin
ac901e5b77
Update changelog 2019-12-22 23:49:52 +01:00
Ludovic Stephan
21fc91c3a4 Merge branch 'kerl/rm_todo_prod' into 'master'
Remove the obsolete TODO_PROD file

See merge request klub-dev-ens/gestioCOF!395
2019-12-22 23:45:46 +01:00
Martin Pépin
00bad52570
Remove the obsolete TODO_PROD file 2019-12-20 17:49:55 +01:00
Martin Pépin
59d93900a3
Update the k-fet calendar url on the home page 2019-12-20 17:08:58 +01:00
Ludovic Stephan
2df4e931d4 Remove log 2019-12-18 21:15:40 +01:00
Ludovic Stephan
36e802082e Merge branch 'kerl/changelog' into 'master'
Petite mise à jour du CHANGELOG et changement de format

See merge request klub-dev-ens/gestioCOF!391
2019-12-13 00:38:05 +01:00
Martin Pépin
d7e1583a8e
Nicer format for the CHANGELOG(.md) file 2019-12-12 22:02:57 +01:00
Martin Pépin
2c848a564c
Some changes were missing in CHANGELOG 2019-12-12 21:58:05 +01:00
Antonin Reitz
e97c873b4f Merge branch 'Aufinal/backbone' into 'master'
Refactor le JS de K-Psul via Backbone : 1ère étape

See merge request klub-dev-ens/gestioCOF!388
2019-12-11 23:19:44 +01:00
Antonin Reitz
f151ad75c6 For the sake of clarity 2019-12-11 23:05:39 +01:00
Antonin Reitz
83ce873e25 Remove unnecessary caching 2019-12-11 22:36:40 +01:00
Martin Pepin
71e3c210f2 Merge branch 'Aufinal/forgotten_decorators' into 'master'
Rajoute les décorateurs oubliés pour l'auth par mdp

See merge request klub-dev-ens/gestioCOF!389
2019-12-11 19:10:19 +01:00
Ludovic Stephan
a4fdb578bc Add forgotten kfet_password decorators 2019-12-02 20:44:25 +01:00
Ludovic Stephan
0498db1140 Merge branch 'Aufinal/fix_created_paid' into 'master'
Fix: les participants nouvellement créés ont payé leurs places BdA

Closes #231

See merge request klub-dev-ens/gestioCOF!379
2019-12-02 09:59:15 +01:00
Martin Pépin
77ceae37ef
Update CHANGELOG 2019-12-01 11:37:43 +01:00
Martin Pépin
085013b256
Add some explanations about !379 2019-12-01 11:35:38 +01:00
Ludovic Stephan
381b52f46c
Fix: les participants nouvellement créés ont payé leurs places BdA
Si un participanti est créé avec `get_or_create`, son champ `paid`
n'était pas créé... C'est difficile à insérer dans la logique du
Manager, donc on fix ça dans la vue concernée.
2019-12-01 11:35:38 +01:00
Martin Pépin
0bd3bd63aa
Update changelog wrt last MR (!382) 2019-12-01 11:24:21 +01:00
Martin Pepin
c6c4814519 Merge branch 'Aufinal/fix-stats-escape' into 'master'
Fix la page de stats pour certains comptes avec des caractères spéciaux

See merge request klub-dev-ens/gestioCOF!382
2019-12-01 11:22:36 +01:00
Martin Pépin
b1747f61fe
Version 0.3.3 2019-11-30 19:04:56 +01:00
Ludovic Stephan
85aa56d030 Fix tests 2019-11-29 15:33:03 +01:00
Ludovic Stephan
361ad46be4 First steps in Account logic 2019-11-29 14:51:54 +01:00
Ludovic Stephan
4e15ab8041 Install django-js-reverse 2019-11-29 14:50:44 +01:00
Ludovic Stephan
091208b66c Make kfet.account.read.json accessible with GET 2019-11-29 14:47:12 +01:00
Ludovic Stephan
7df8a9ef6b Add vendor library and their sources 2019-11-28 18:26:39 +01:00
Martin Pépin
4c7993f48f
Forgot CHANGELOG for !385 2019-11-28 16:09:47 +01:00
Martin Pepin
94d5e0f0ac Merge branch 'Aufinal/fix_cas_redirect' into 'master'
Fix la redirection lors d'un logout CAS

See merge request klub-dev-ens/gestioCOF!385
2019-11-28 16:08:50 +01:00
Martin Pépin
a521caba8d
Update changelog wrt the lastest merged patches. 2019-11-28 14:53:44 +01:00
Martin Pepin
797f0356f6 Merge branch 'Aufinal/no_reduction_category' into 'master'
Permet d'exclure des catégories de la réduction COF

See merge request klub-dev-ens/gestioCOF!386
2019-11-28 14:30:54 +01:00
Martin Pépin
8dcc1f012a
Update CHANGELOG 2019-11-28 14:17:59 +01:00
Ludovic Stephan
1115960107 Add unit test 2019-11-27 16:57:48 +01:00
Ludovic Stephan
727b3042a1 Merge branch 'kerl/fix-multiple-select-urls' into 'master'
Mise à jour de certaines urls (multiple-select.{css,js})

See merge request klub-dev-ens/gestioCOF!387
2019-11-27 16:09:13 +01:00
Martin Pépin
61efded673
Remove unused references to multiple-select.* 2019-11-27 15:46:50 +01:00
Ludovic Stephan
38aecdd741 Typo 2019-11-27 14:41:20 +01:00
Martin Pépin
e0ffee295d
Fix static urls for multiple-select 2019-11-27 14:30:24 +01:00
Ludovic Stephan
e62756ed29 Fix tests 2019-11-27 14:20:24 +01:00
Ludovic Stephan
ac3bfbe368 Display in kfet js 2019-11-27 14:14:42 +01:00
Ludovic Stephan
affdf43e0b Add logic in views and templates 2019-11-27 14:14:33 +01:00
Ludovic Stephan
20ceec0e64 Add has_reduction property 2019-11-27 14:11:53 +01:00
Ludovic Stephan
4c9ee8a57d Merge branch 'fix-cash-transaction-cancel' into 'master'
Fix typo and hence cash transaction cancel

Closes #239

See merge request klub-dev-ens/gestioCOF!384
2019-11-27 13:32:23 +01:00
Ludovic Stephan
5c581d8984 Cleanup + no msg on CAS logout 2019-11-27 13:14:20 +01:00
Ludovic Stephan
ac4d5cf7d5 Patch CAS redirect parameter in logout view 2019-11-27 13:03:28 +01:00
Antonin Reitz
b90e749a7f Fix typo and hence cash transaction cancel 2019-11-27 10:50:27 +01:00
Ludovic Stephan
d04b79bcb5 Disable autoescape in js code 2019-11-25 10:48:43 +01:00
Ludovic Stephan
14164ec4a5 Merge branch 'kerl/fix-wagtail-deps' into 'master'
Règle un problème de dépendances de wagtailmenus avec python 3.8

See merge request klub-dev-ens/gestioCOF!381
2019-11-25 10:26:06 +01:00
Martin Pépin
f9b461a08d
Bump django-redis-cache to version 2.1.* 2019-11-22 22:45:27 +08:00
Martin Pépin
8c5d09dbee
Bump wagtail to version 2.7 (LTS) 2019-11-22 22:35:23 +08:00
Martin Pépin
e2af45929e
Use the production requirements in CI 2019-11-22 22:22:47 +08:00
Martin Pépin
481cb5e478
Move production deps out of requirements.txt 2019-11-22 22:18:04 +08:00
Martin Pépin
a3ca2e66bf
Fix some dependency issue with wagtail 2019-11-22 22:18:04 +08:00
Martin Pepin
82746f1492 Merge branch 'Aufinal/fix_privilege_escalation' into 'master'
Fix le problème d'auth par mdp K-Fêt

Closes #240

See merge request klub-dev-ens/gestioCOF!380
2019-11-22 14:37:13 +01:00
Ludovic Stephan
ea45eb1f55 Fix tests 2019-11-21 01:21:26 +01:00
Ludovic Stephan
a60df91b04 Add decorator to needed views 2019-11-21 01:21:26 +01:00
Ludovic Stephan
c1a99453d5 Add password auth decorator 2019-11-21 01:21:26 +01:00
Ludovic Stephan
be5218f7e1 Remove pesky middleware 2019-11-21 01:21:26 +01:00
Ludovic Stephan
dd5fe36ee1 Fix requirements problem 2019-11-21 01:21:26 +01:00
Ludovic Stephan
4a4dae9951 Merge branch 'kerl/clubs' into 'master'
Nouvelle app: clubs

See merge request klub-dev-ens/gestioCOF!372
2019-11-06 19:22:58 +01:00
Martin Pépin
5d87d7f249
Update CHANGELOG; version 0.3.2 2019-11-04 15:41:40 +01:00
Martin Pepin
f9cde30e08 Merge branch 'Aufinal/fix_missing_names' into 'master'
Fix le problème des prénoms manquants

See merge request klub-dev-ens/gestioCOF!378
2019-11-04 15:39:35 +01:00
Ludovic Stephan
b376114bee Fix tests 2019-11-03 00:36:57 +01:00
Ludovic Stephan
57088cda03 Fix le problème des prénoms manquants
Depuis !360, quand on modifie son propre compte K-Fêt, cela supprime les
noms associés sur gestioCOF... Le problème est réglé, normalement.
2019-11-03 00:02:34 +01:00
Ludovic Stephan
b542f805f0 Merge branch 'kerl/empty_banner' into 'master'
Pour supprimer, la bannière "d'annonces" en haut de GestioCOF…

See merge request klub-dev-ens/gestioCOF!377
2019-10-21 16:28:20 +02:00
Martin Pépin
28a129f69c
Allows empty announcement banners 2019-10-19 21:17:13 +02:00
Martin Pépin
c4f5e168f2
Update CHANGELOG for v0.3.1 2019-10-19 21:00:44 +02:00
Martin Pepin
5b2dad6fff Merge branch 'Aufinal/fix-accounts' into 'master'
Fix account history

See merge request klub-dev-ens/gestioCOF!376
2019-10-19 20:59:39 +02:00
Ludovic Stephan
b22a77e603 Fix account history 2019-10-19 10:33:15 +02:00
Martin Pepin
4d9c66cb51 Merge branch 'Aufinal/fix-reventes' into 'master'
Fix: Souscription aux reventes

See merge request klub-dev-ens/gestioCOF!375
2019-10-18 09:31:56 +02:00
Ludovic Stephan
9254e3f8f7 Fix: Souscription aux reventes
Il me semblait que c'était déjà fait...
2019-10-17 10:50:54 +02:00
Martin Pepin
635c14ff8f Merge branch 'Aufinal/staticfiles' into 'master'
Réorganise les fichiers statiques de GestioCOF

See merge request klub-dev-ens/gestioCOF!352
2019-10-16 21:24:31 +02:00
Ludovic Stephan
898abd15c6 Ignore /src directories 2019-10-16 20:51:10 +02:00
Ludovic Stephan
337453c6c6 Add source for bootstrap-datetimepicker 2019-10-16 20:50:59 +02:00
Ludovic Stephan
bdb8f06e1d Déplace bda.css et supprime une police
On met le static de `bda` dans `static/bda`, comme tout le monde.
2019-10-16 20:27:57 +02:00
Ludovic Stephan
64b4c2c08a Revert "Ignore src/ directories"
On ignorera ça proprement en Django 2.2...
2019-10-16 20:27:57 +02:00
Ludovic Stephan
8a6a3d0994 Ignore src/ directories 2019-10-16 20:27:57 +02:00
Ludovic Stephan
8ea0cb84d1 Move source files (not minified) to src/ directory 2019-10-16 20:27:57 +02:00
Ludovic Stephan
099857e226 Supprime une police inutilisée 2019-10-16 20:27:57 +02:00
Ludovic Stephan
f8e954ff79 Range les fichiers statiques K-Fêt
Les fichiers JS et CSS externes sont dans `static/kfet/vendor`, minifiés ; on bump la version de `reconnecting-websocket`.
2019-10-16 20:27:57 +02:00
Ludovic Stephan
435bb392ea Déplace une fonction js 2019-10-16 20:27:57 +02:00
Ludovic Stephan
de10392a7f Supprime des dossiers inutiles
Pas besoin de 12 sous-dossiers pour `autocomplete-light`.
2019-10-16 20:27:57 +02:00
Ludovic Stephan
e421792906 Déplace les fichiers statiques de gestioncof
On met tous les fichiers de `gestioncof/static` dans `gestioncof/static/gestioncof`, comme pour les templates. On en profite pour virer pas mal de fichiers inutiles de `font-awesome`.
2019-10-16 20:27:57 +02:00
Ludovic Stephan
abb3823a8b Interaction Moment.js + Chart.js
On avait pas besoin de servir `Chart.bundle.js` puisqu'on avait déjà `moment.js` servi à part. Aussi, on déplace tout et on sert les fichiers minifiés.
2019-10-16 20:27:57 +02:00
Ludovic Stephan
b343c6c6e0 Déplace (et modifie) jquery-ui
On déplace les deux versions de `jquery-ui` dans `shared/static/vendor/`, et on en récupère une version avec seulement les fonctionnalités requises.
2019-10-16 20:27:57 +02:00
Ludovic Stephan
22cfaf9b44 Idem pour jquery
On met `jquery` dans `shared/static/vendor/`, et on bump un chouïa la version.
2019-10-16 20:27:57 +02:00
Ludovic Stephan
a9dce881bd Supprime le CDN Bootstrap
On sert les fichiers nécessaires à `bootstrap` en local, dans `shared/static/vendor`.
2019-10-16 20:27:57 +02:00
Ludovic Stephan
0100a9a62e Move stupidtable import to base.html
Aussi, on déplace les fichiers JS associés dans `static/gestioncof/vendor/`
2019-10-16 20:27:57 +02:00
Martin Pépin
6fba63846a
Version 0.3 2019-10-16 20:12:07 +02:00
Martin Pépin
2a06cc5806
Update changelog 2019-10-16 19:58:12 +02:00
Martin Pépin
380e38519b
New app: clubs
- Clubs will be used both by the cof and the bds app.
- For now, they are only visible in development.
2019-10-16 19:58:12 +02:00
Ludovic Stephan
8ccaf8beaf Merge branch 'kerl/ci_missing_migrations' into 'master'
La CI regarde s'il manque des migrations

Closes #214

See merge request klub-dev-ens/gestioCOF!373
2019-10-16 19:55:29 +02:00
Ludovic Stephan
7892f42e3e Merge branch 'kerl/event_subscriptions' into 'master'
[Événements] Export des inscrits en csv

See merge request klub-dev-ens/gestioCOF!374
2019-10-16 19:48:36 +02:00
Martin Pépin
2964d3a4aa
K-FêT: new year = new promo = new migration 2019-10-16 19:43:20 +02:00
Martin Pépin
46da197507
CI: track missing migrations 2019-10-16 19:43:20 +02:00
Ludovic Stephan
b005e772ea Merge branch 'kerl/bds' into 'master'
Début de l'app BDS (2)

See merge request klub-dev-ens/gestioCOF!371
2019-10-16 19:19:52 +02:00
Ludovic Stephan
f83eeb7a5f Merge branch 'kerl/noncof_profile_and_passwd_change' into 'master'
Les utilisateurs non-COF peuvent changer leur mot de passe et éditer leur profil

Closes #178 and #177

See merge request klub-dev-ens/gestioCOF!368
2019-10-16 19:17:56 +02:00
Martin Pépin
e94015a142
Update changelog 2019-10-15 21:56:48 +02:00
Martin Pépin
98fe68d0be
Translation fixes in bds.models
- the 'u' in ugettext_lazy in a legacy of python2, we can drop it now
- translate all verbose names
- start field verbose names with a lowercase letter
2019-10-15 21:54:52 +02:00
Martin Pépin
f9aee86a1c
Only enable the bds app in development 2019-10-15 21:54:52 +02:00
Martin Pépin
e2a7e1f6de
BDSProfile: enable the default admin 2019-10-15 21:53:04 +02:00
Martin Pépin
53efb4b542
Enable bds checks in CI 2019-10-15 21:53:04 +02:00
Ludovic Stephan
53ea6f24ee
Isort setup 2019-10-15 21:52:19 +02:00
Ludovic Stephan
b3e7b59903
Migrations
Une migration pour les modèles, et une pour créer le groupe du Burô du
BDS
2019-10-15 21:51:40 +02:00
Ludovic Stephan
bc7c30e2ee
Init app + models
Le modèle de profil BDS est le seul utile pour l'instant ; c'est un mix
entre `CofProfile` et les modèles de Sport@Ulm.
2019-10-15 21:51:40 +02:00
Ludovic Stephan
4da5add25a
Move choices_length to shared folder 2019-10-15 21:51:23 +02:00
Martin Pépin
f5766e9207
events: make isort happy 2019-10-08 23:33:46 +02:00
Martin Pépin
a8fd04e4c0
test events.views.participants_csv 2019-10-08 22:26:31 +02:00
Martin Pépin
33bc3c5882
Events: simple csv participants export 2019-10-08 22:26:30 +02:00
Martin Pépin
41a3c4c161
add event subscriptions (models only) 2019-10-08 22:21:37 +02:00
Martin Pépin
83c83d791b
Update changelog 2019-10-07 18:45:02 +02:00
Martin Pépin
d5f0060e2e
Fix profile test: non-cof users can access /profile 2019-10-07 18:45:02 +02:00
Martin Pépin
41256154ad
Make profile editable for non-COF user
Non-COF users can now edit their own profile
Contrary to COF users they cannot change their mailing list settings
2019-10-07 18:45:02 +02:00
Martin Pépin
0814cfe1ef
home templates: add links for non-COF users
Add links to
- change password page
- profile page
2019-10-07 18:45:02 +02:00
Martin Pépin
730611039b
isort events.admin 2019-10-07 18:44:36 +02:00
Martin Pépin
9b355d5b56
linter config: add events to known_first_party 2019-10-07 18:32:51 +02:00
Martin Pépin
6781122fc1
Add the events app to the CI checks 2019-10-07 18:32:06 +02:00
Ludovic Stephan
e9ca8eb8dd Merge branch 'kerl/refactor_events' into 'master'
Nouvelle app pour gérer les événements

See merge request klub-dev-ens/gestioCOF!365
2019-10-07 14:39:51 +02:00
Martin Pépin
97f682dfcd
Update changelog 2019-10-06 19:25:26 +02:00
Martin Pépin
9f2004bb54
Add events in the coverage report 2019-10-06 19:24:32 +02:00
Martin Pépin
8119591c62
enable the "events" app in CI 2019-10-06 19:24:32 +02:00
Martin Pépin
34e552f760
New 'events' app, first model
The objective is to move (at some point) all the management logic in
this app. Before that time: as long as the events app does not have all
the features necessary to be used in production it is only available in
dev mode and coexists with the old event system. When it's ready we'll
move the old events in the new app (data migration) and remove the old
system.
2019-10-06 19:24:32 +02:00
Ludovic Stephan
ef97afd86c Merge branch 'kerl/pub-kde' into 'master'
Un peu de pub pour KDEns

See merge request klub-dev-ens/gestioCOF!367
2019-10-06 19:18:38 +02:00
Martin Pépin
9a7a447246
Update changelog 2019-10-06 17:54:12 +02:00
Martin Pépin
f85f014bc9
Un peu de pub pour KDEns 2019-10-06 17:53:30 +02:00
Ludovic Stephan
fb1519cece Merge branch 'kerl/unused-deps' into 'master'
Remove useless / unused dependencies

See merge request klub-dev-ens/gestioCOF!366
2019-10-06 13:50:43 +02:00
Ludovic Stephan
51e8058f97 Merge branch 'kerl/home_template_view' into 'master'
Rewrite home as a class-based view

See merge request klub-dev-ens/gestioCOF!369
2019-10-06 13:47:07 +02:00
Ludovic Stephan
fba6b592f5 Merge branch 'kerl/fix_revente_crash' into 'master'
Fix crash on /bda/revente/<id>/manage

Closes #228

See merge request klub-dev-ens/gestioCOF!370
2019-10-06 12:01:53 +02:00
Martin Pépin
db158ad312
Update changelog 2019-10-06 11:52:32 +02:00
Martin Pépin
8c9de4303b
Add a testcase for issue #228 2019-10-06 10:57:15 +02:00
Martin Pépin
9661751df2
Fix crash on /bda/revente/<id>/manage
`annotate_paid` method is a method of the Participant object manager,
not the Participant class itself
2019-10-06 10:32:18 +02:00
Martin Pépin
d1c9d27a65
Rewrite home as a class-based view 2019-10-06 00:28:32 +02:00
Martin Pépin
838bf325ba Remove useless / unused dependencies
- unicodecsv is useless in py3
- autoslug is not used anywhere
- wheels comes with any correctly configured virtualenv
2019-10-05 17:38:31 +02:00
Ludovic Stephan
b99fd03df2 Merge branch 'kerl/403_vs_404' into 'master'
Replace some 403 by 404 to avoid trigramme leaking

Closes #224

See merge request klub-dev-ens/gestioCOF!364
2019-10-05 16:01:46 +02:00
Martin Pépin
d37c41e99f kfet/test_views: more eloquent test names 2019-10-05 13:48:29 +02:00
Martin Pépin
a4ecd344d0 Update CHANGELOG 2019-10-05 11:28:59 +02:00
Martin Pépin
e0285607a0
Fix tests according to issue #224 2019-10-05 02:25:05 +02:00
Martin Pépin
96adadce5e
Replace some 403 by 404 to avoid trigramme leaking
Fixes #224
2019-10-05 01:25:36 +02:00
Robin Champenois
e8a9e808f5 Merge branch 'Aufinal/charte_bda' into 'master'
Ajoute un popup de charte BdA à l'inscription aux tirages

Closes #225

See merge request klub-dev-ens/gestioCOF!363
2019-09-26 21:00:33 +02:00
Ludovic Stephan
966cf6ce15 On hook le popup à form.submit() 2019-09-26 20:30:04 +02:00
Ludovic Stephan
6406b493a2 Add background opacity 2019-09-26 20:04:07 +02:00
Ludovic Stephan
0701213225 Copy jconfirm to shared 2019-09-18 20:44:35 +02:00
Ludovic Stephan
411e66b13c Style charte popup 2019-09-18 19:36:14 +02:00
Ludovic Stephan
5db7eef1d7 Add charte popup and functionality 2019-09-18 19:36:02 +02:00
Ludovic Stephan
0a1b20dd4e Add accepte_charte field to Participant model 2019-09-18 19:34:56 +02:00
Ludovic Stephan
92ebf0d233 Merge branch 'Kerl/registration_less_email_errors' into 'master'
Erreurs de mails lors de l'inscription d'un nouveau membre

Closes #173

See merge request klub-dev-ens/gestioCOF!348
2019-06-17 22:31:43 +02:00
Basile Clement
405f95a43b Early return if there is no email 2019-06-17 22:17:34 +02:00
Martin Pépin
ab89002cfc Clearer error message 2019-06-17 22:17:34 +02:00
Martin Pépin
c319780ab5 CHANGELOG: less email errors during registration 2019-06-17 22:17:34 +02:00
Martin Pépin
9f23f85b87 Handle errors when sending welcome emails during member registraton 2019-06-17 22:17:02 +02:00
Ludovic Stephan
1cf333f0fc Merge branch 'Aufinal/readonly_user' into 'master'
Désactive la modification des comptes COF sur l'interface K-Fêt

See merge request klub-dev-ens/gestioCOF!360
2019-06-17 22:15:57 +02:00
Ludovic Stephan
bf372a1ce2 CHANGELOG 2019-06-17 22:03:11 +02:00
Ludovic Stephan
96430d852c Do not repeat default argument 2019-06-17 22:02:12 +02:00
Ludovic Stephan
fc8c8fdf29 Montre les infos à tout le monde 2019-06-17 22:02:11 +02:00
Ludovic Stephan
8d30c5c7e5 Fix tests 2019-06-17 22:02:11 +02:00
Ludovic Stephan
fb56293273 Supprime un formulaire inutilisé 2019-06-17 22:02:11 +02:00
Ludovic Stephan
baa3826a42 Change le formulaire de account_update
On fait un formulaire d'info non-éditable pour pas que les gens mettent des noms troll
2019-06-17 22:02:11 +02:00
Ludovic Stephan
4598abc721 Merge branch 'Aufinal/paid_attributions' into 'master'
Déplace le champ `paid` des participants aux attributions

See merge request klub-dev-ens/gestioCOF!361
2019-06-17 21:59:01 +02:00
Ludovic Stephan
d7d0daea0d Commentaire dans la fonction 2019-06-17 21:40:32 +02:00
Ludovic Stephan
46e7305953 Meilleur décorateur 2019-06-17 21:38:49 +02:00
Ludovic Stephan
4f15b820a5 Use manager from queryset 2019-06-17 21:36:09 +02:00
Ludovic Stephan
edd92beadf Add logging call 2019-06-17 21:21:12 +02:00
Ludovic Stephan
20bb9fe54b Remove debug log 2019-06-17 21:13:12 +02:00
Ludovic Stephan
ba5aa6da5f Remove useless local variable 2019-06-17 21:12:03 +02:00
Ludovic Stephan
b11e35616c Changelog 2019-06-08 15:33:47 +02:00
Ludovic Stephan
fa98bb34bd Adapte l'interface admin 2019-06-08 15:33:09 +02:00
Ludovic Stephan
a67446048e Réécrit des vues pour la nouvelle fonctionnalité
On en profite pour rajouter des Mixins pour les perms buro/cof
2019-06-08 15:33:09 +02:00
Ludovic Stephan
b37e7c4c41 Migrations 2019-06-08 15:33:09 +02:00
Ludovic Stephan
29111059f9 Rajoute un manager à Participant
On rajoute un manager qui annote les querysets avec si le participant a payé ou non
2019-06-08 15:33:09 +02:00
Ludovic Stephan
9776a18e4c Déplace les champs paid et paymenttype 2019-06-08 15:33:09 +02:00
Martin Pepin
7f1adf7c4e Merge branch 'Aufinal/can-delete-stuff' into 'master'
Délétions d'objets K-Fêt

See merge request klub-dev-ens/gestioCOF!359
2019-06-03 23:06:06 +02:00
Ludovic Stephan
56bc281b30 Utilise >= gnagnagna 2019-06-03 23:00:10 +02:00
Ludovic Stephan
c4948be1f7 Use http_methods_allowed attribute 2019-06-03 22:59:43 +02:00
Ludovic Stephan
f3dbb72f69 Consistency for on_delete attributes 2019-06-03 22:43:47 +02:00
Ludovic Stephan
173affd8eb Fix another 2.2 deprecation 2019-06-03 20:42:21 +02:00
Ludovic Stephan
51fe9cc9f8 Changelog 2019-05-29 18:31:03 +02:00
Ludovic Stephan
d4be8b426e Tests pour la suppression d'articles 2019-05-29 18:29:15 +02:00
Ludovic Stephan
65dd7e5fa3 Suppression d'article
On fait pareil que précédemment pour les articles, en rajoutant une vie
de délétion + de quoi afficher qu'un article a été supprimé.
N.B. : le formatage automatique de VSCode fait plein de changements,
donc pourquoi pas les garder.
2019-05-29 18:29:15 +02:00
Ludovic Stephan
123e2b84df Rename view to fit conventions 2019-05-29 18:29:15 +02:00
Ludovic Stephan
f12370a6cd Tests (!!) 2019-05-29 18:29:15 +02:00
Ludovic Stephan
52521e89a6 Add some restrictions on deletion 2019-05-29 18:29:15 +02:00
Ludovic Stephan
08ac0ac890 Vues de suppression
On rajoute un bouton de suppression d'un compte utilisable avec la perm
`kfet.delete_account`, avec message de vérif. On en profite pour
cleanup un peu le css de `jconfirm`.
2019-05-29 18:29:15 +02:00
Ludovic Stephan
63fff6ca7c Setup deleted account
Pour pouvoir supprimer un compte, on crée un compte dummy qui a pour but
de recevoir les objets non supprimables (caisses, transferts/opérations
pour statistiques, etc.). Lors de la délétion d'un compte, tout est
transféré sur le dummy, qui est créé via migration.
2019-05-29 18:29:15 +02:00
Ludovic Stephan
85b1e974ff Change deletion behaviour
Tous les `on_delete` étaient mis à PROTECT, ce qui faisait qu'on ne
pouvait rien supprimer... On les met à CASCADE pour tous les modèles
secondaires (`AccountNegative`, `CheckoutStatement`, `InventoryArticle`,
`SupplierArticle`, `Order` et `OrderArticle`) et pour les inventaires
créés à partir d'une commande.

Pour les modèles qui demandent une validation, et pour les `Operation`s,
on met à NULL le compte ou l'article associé (cela ne change pas le
total d'une opération, qui est la partie importante à garder).
2019-05-29 18:29:15 +02:00
Ludovic Stephan
3a5eceba83 Delete unused models
Certains modèles n'étaient pas utilisés dans le code, on en profite pour
les virer.
2019-05-29 18:29:15 +02:00
Ludovic Stephan
018865967d Merge branch 'Aufinal/django2-urls' into 'master'
Passage à Django2

See merge request klub-dev-ens/gestioCOF!358
2019-05-29 17:13:25 +02:00
Ludovic Stephan
8dd003f81f Changelog 2019-05-24 09:36:14 +02:00
Ludovic Stephan
f03e708280 Tiens, une migration Wagtail 2019-05-23 15:21:40 +02:00
Ludovic Stephan
198658f5f9 Misc fixes
- on vire un commentaire obsolète, et on en remet un à jour
- un peu de doc sur les converters
2019-05-21 15:30:51 +02:00
Ludovic Stephan
03c74a7940 Misc fixes 2019-04-17 20:50:49 +02:00
Ludovic Stephan
7717d1ed34 Backwards-incompatible changes : queryset in filter 2019-04-17 18:33:43 +02:00
Ludovic Stephan
72560397a2 Backwards-incompatible changes : renderer argument 2019-04-17 18:27:14 +02:00
Ludovic Stephan
413a9cddb1 Backwards-incompatible changes : manytomany set 2019-04-17 18:21:59 +02:00
Ludovic Stephan
4064218010 Forgot one import 2019-04-17 18:21:15 +02:00
Ludovic Stephan
a2fcc05672 Test fix : freeze psycopg2 version 2019-04-12 18:30:03 +02:00
Ludovic Stephan
8fc6f96324 Misc urlconf files 2019-04-12 17:07:03 +02:00
Ludovic Stephan
271732f40d K-Fêt urlconf file + converter 2019-04-12 17:06:53 +02:00
Ludovic Stephan
019acb90ac Global urlconf file 2019-04-12 17:06:43 +02:00
Ludovic Stephan
759b6d9489 Update settings ; remove debug_panel 2019-04-12 17:04:33 +02:00
Ludovic Stephan
f32e4a9b0d Fix error 2019-04-12 17:03:42 +02:00
Ludovic Stephan
209cb1fbe5 Update requirements to Django 2.2 2019-04-12 17:03:20 +02:00
Ludovic Stephan
ceff3ed6c9 Merge branch 'Aufinal/django2-login' into 'master'
Préparation Django2 : vues de login/logout

See merge request klub-dev-ens/gestioCOF!357
2019-04-01 22:25:07 +02:00
Ludovic Stephan
2c49b25d59 Cleaner error code management 2019-03-25 23:30:55 +01:00
Ludovic Stephan
5f963d5451 Use get_user_model 2019-03-25 23:22:06 +01:00
Ludovic Stephan
a1ead1bfc8 Préparation Django2 : vues de login/logout
À partir de Django 2.1, les vues de login et logout sont class-based
uniquement. On passe donc à django-cas-ng 2.6 pour harmoniser.
On cleanup un peu le processus de login avec une classe un peu propre +
un vrai formulaire/des vrais templates.
2019-03-25 23:05:47 +01:00
Basile Clement
cef75e56d7 Merge branch 'Aufinal/django2-reverse-import' into 'master'
Préparation Django2 :  fix des imports

See merge request klub-dev-ens/gestioCOF!356
2019-03-25 20:19:51 +01:00
Ludovic Stephan
8bfb8029b2 Changelog 2019-03-19 18:00:33 +01:00
Ludovic Stephan
fd0f387dbc Merge branch 'Kerl/DJANGO_NO_DDT' into 'master'
Une variable d'environement pour désactiver la django debug toolbar

See merge request klub-dev-ens/gestioCOF!353
2019-03-19 17:59:39 +01:00
Ludovic Stephan
676239ad24 Remove urlresolvers mentions in packages
On bump quelques versions, et on vire `django_debug_panel`
2019-03-19 17:16:57 +01:00
Ludovic Stephan
5fd4cb5c78 Change django.core.urlresolvers imports
-- compatible with 1.11 --
2019-03-19 10:18:56 +01:00
Evarin
2b3a8760ff Mise à jour du Changelog 2019-02-18 22:50:35 +01:00
Robin Champenois
0eccfcf886 Merge branch 'Aufinal/webfonts' into 'master'
Sert les polices en local

See merge request klub-dev-ens/gestioCOF!354
2019-02-18 22:40:10 +01:00
Ludovic Stephan
f90663bf97 Merge branch 'Evarin/Wagtail2' into 'master'
Migration vers Wagtail 2.3 et Wagtail-modeltranslation 0.9

See merge request klub-dev-ens/gestioCOF!349
2019-02-18 22:16:45 +01:00
Evarin
1043e5725a Fix content-type fixtures K-Fêt 2019-02-18 21:54:26 +01:00
Ludovic Stephan
3bf0906697 Supprime une police inutilisée 2019-02-13 17:05:31 +01:00
Ludovic Stephan
85642d00d8 Sert les polices en local 2019-02-13 16:54:42 +01:00
Martin Pépin
fabb30cec2 add a DJANGO_NO_DDT env variable to disable ddt 2019-02-12 17:55:23 +01:00
Evarin
641bdd9464 Plus besoin de ça 2019-02-11 21:26:16 +01:00
Evarin
4f6579c3d1 Fixtures à jour pour Wagtail2 et wagtail-translation 0.9 2019-02-11 21:10:11 +01:00
Ludovic Stephan
1c45dd833d Black + isort 2019-02-09 15:16:40 +01:00
Ludovic Stephan
f3117c9e69 Merge branch 'Elarnon/petitscours_edit' into 'master'
Quelques améliorations d'ergonomie sur les petits cours

See merge request klub-dev-ens/gestioCOF!350
2019-02-09 13:58:29 +01:00
Basile Clement
fc72425c05 Add note to changelog 2019-02-09 13:47:18 +01:00
Basile Clement
f74277af66 [petitscours] Ajoute un lien vers la liste des demandes
Ce patch ajoute un lien permettant de retourner sur la liste des
demandes à traiter depuis les pages de détail et de traitement d'une
demande.  Idéalement, on voudrait plutôt une espèce de fil d'ariane.
2019-02-09 13:46:42 +01:00
Basile Clement
f64c7a6e69 [petitcours] Ajoute un lien pour modifier une demande
Ce patch ajoute un lien bidirectionnel entre la page d'affichage d'un
petit cours pour le Burô et l'administration générale.  Plus
précisément,

 - Un lien est ajouté sur la page du petit cours, ainsi que sur la page
   de traitement, vers l'administration générale

 - La fonctionalité "Voir sur le site" de Django est utilisée pour
   renvoyer sur la page de la demande.  Si des modifications sont
   apportées, il faut choisir "Enregistrer et continuer les
   modifications", puis cliquer sur "Voir sur le site".

Le workflow n'est pas forcément optimal, mais permet au COF d'accéder
facilement à la demande si un traitement manuel ou complexe est
nécessaire - et de facilement revenir à la vue de traitement.
2019-02-09 13:46:42 +01:00
Ludovic Stephan
73508c0251 Merge branch 'Kerl/localhost8000' into 'master'
Le vrai nom du site en dev c'est `localhost:8000` et pas `localhost`

See merge request klub-dev-ens/gestioCOF!351
2019-02-09 13:45:42 +01:00
Martin Pépin
2c4ba3258d the actual (dev) domain name is localhost:8000 2019-02-09 13:39:46 +01:00
Evarin
0f1e05acdd Migration vers Wagtail 2.3 et Wagtail-modeltranslation 0.9
Toutes les pages Wagtail doivent désormais être traduites
Suppression du modèle COFUtilPage devenu inutile
Réinitialisation des migrations de Wagtail à cause des changements de ModelTranslation
2019-02-04 22:56:48 +01:00
Ludovic Stephan
86dbdbd2b6 Merge branch 'Kerl/del_old_view' into 'master'
Supprime la vue bda.views.descriptions_spectacles

Closes #154

See merge request klub-dev-ens/gestioCOF!347
2019-02-04 21:43:14 +01:00
Martin Pépin
c134e1ae0f remove unused template 2019-02-04 21:37:45 +01:00
Martin Pépin
abf05131d5 CHANGELOG: remove old bda view 2019-02-04 21:06:24 +01:00
Martin Pépin
869e634adb remove bda.views.descriptions_spectacles
This view has been unused for a long time
It has been replace by bda.views.catalogue
2019-02-04 20:58:53 +01:00
Aurélien Delobelle
be155f2f2d Merge branch 'Kerl/unique_login_clipper' into 'master'
Force l'unicité des clippers

See merge request klub-dev-ens/gestioCOF!346
2019-01-15 20:18:33 +01:00
Martin Pépin
68cead600f CHANGELOG: clipper uniqueness 2019-01-14 23:12:29 +01:00
Martin Pépin
d85eeb5801 Enforce clipper uniqueness 2019-01-14 22:46:16 +01:00
Martin Pépin
2140a59777 add missing entries in the CHANGELOG file 2019-01-14 21:56:17 +01:00
Martin Pepin
512868ee14 Merge branch 'evarin/site-cof' into 'master'
Nouveau site du COF

See merge request klub-dev-ens/gestioCOF!247
2019-01-14 21:23:10 +01:00
Martin Pepin
d7d819dde0 Merge branch 'Aufinal/revente-cof-only' into 'master'
BdA-Revente n'est accessible qu'aux adhérents du COF

See merge request klub-dev-ens/gestioCOF!342
2019-01-14 20:30:33 +01:00
Martin Pepin
eb83c58f05 Merge branch 'Aufinal/prettify-revente' into 'master'
Rend BdA-Revente un peu plus joli

See merge request klub-dev-ens/gestioCOF!338
2019-01-13 14:29:48 +01:00
Martin Pepin
f883082814 Merge branch 'aureplop/lint-migrations' into 'master'
style: black

See merge request klub-dev-ens/gestioCOF!343
2019-01-13 14:05:32 +01:00
Aurélien Delobelle
b65d37b141 style: black 2019-01-13 13:56:03 +01:00
Ludovic Stephan
aa498e0261 BdA-Revente n'est accessible qu'au COF 2019-01-10 10:31:58 +01:00
Martin Pépin
670fda3c9c migrations nécessaires en prod ?!? wtf 2019-01-07 23:30:56 +01:00
Martin Pépin
dd5d773405 add CHANGELOG 2019-01-07 23:11:57 +01:00
Ludovic Stephan
d08cec06d3 Merge branch 'master' into Aufinal/prettify-revente 2019-01-07 22:55:48 +01:00
Ludovic Stephan
1f3e65fa68 Fix javascript code 2019-01-07 22:52:18 +01:00
Ludovic Stephan
55c1d7f02c Refactor templates 2019-01-07 22:51:02 +01:00
Ludovic Stephan
71cae7f5ca Remove dead code 2019-01-07 22:50:30 +01:00
Ludovic Stephan
445745ee15 Merge branch 'master' into Aufinal/prettify-revente
Merge remote-tracking branch 'origin/master' into Aufinal/prettify-revente
2019-01-07 22:34:28 +01:00
Aurélien Delobelle
6e51ca749d Merge branch 'Kerl/syncmails' into 'master'
On oublie l'argument de syncmail dans `prepare_django.sh`

See merge request klub-dev-ens/gestioCOF!340
2019-01-07 22:33:58 +01:00
Martin Pépin
babb458aa4 fix syncmail invocation in prepare_django.sh 2019-01-07 22:10:58 +01:00
Martin Pepin
288e3f15b6 Merge branch 'Aufinal/djdt_admin' into 'master'
Remove Django-debug-toolbar in admin interface

See merge request klub-dev-ens/gestioCOF!339
2019-01-07 20:58:55 +01:00
Ludovic Stephan
bb23c45fad Remove Django-debug-toolbar in admin interface
La présence de DJDT sur l'interface admin multiplie par 100 environ
(sans exagération) les temps de chargement des pages, cause des 503, et
a une utilité au plus limitée. Cette MR vire donc l'addon de l'interface
admin.
2019-01-07 17:38:55 +01:00
Ludovic Stephan
47c02d72af Réorganisation de bda/forms
Suppression de code mort, tri des formulaires
Remove bootstrap forms loading
2019-01-07 16:43:46 +01:00
Ludovic Stephan
ae0abb5cb3 Better JS for tables 2019-01-07 16:28:52 +01:00
Ludovic Stephan
f66a54bb73 Prettify revente/manage 2019-01-07 16:24:30 +01:00
Ludovic Stephan
010ce0df3e Bugfixes : add staticfiles and typo 2019-01-07 15:27:41 +01:00
Ludovic Stephan
519ef9dc20 Fix concurrency issues
Creating form fields in the class and modifiying them dynamically can
cause concurrency issues because the form class is shared between tabs.
2019-01-07 14:59:20 +01:00
Ludovic Stephan
a30955fb75 HTML corrections ; stupidtable injection 2019-01-07 14:58:31 +01:00
Ludovic Stephan
31223aaed9 Merge branch 'aureplop/kfet-tests_deterministic' into 'master'
kfet.tests -- Deterministic responses for cancel_operation

See merge request klub-dev-ens/gestioCOF!337
2019-01-07 14:12:41 +01:00
Aurélien Delobelle
5d14fef032 kfet.tests -- More isolated tests for kfet.open 2019-01-06 13:49:07 +01:00
Aurélien Delobelle
7ca0144004 kfet.tests -- Deterministic responses for cancel_operation 2019-01-06 13:49:07 +01:00
Ludovic Stephan
7c1d1df1a9 Merge branch 'aureplop/bda-tests_misc-views' into 'master'
bda.tests -- Add some tests for non-reventes views

See merge request klub-dev-ens/gestioCOF!326
2019-01-06 13:12:09 +01:00
Robin Champenois
a6bf1fc16a Merge branch 'aureplop/site-cof' into 'evarin/site-cof'
evarin/site-cof: style -- black + isort

See merge request klub-dev-ens/gestioCOF!336
2019-01-06 12:02:31 +01:00
Aurélien Delobelle
84c88dfd5e Merge branch 'master' into aureplop/site-cof 2019-01-06 00:56:21 +01:00
Aurélien Delobelle
39eaf4b109 style -- black + isort 2019-01-06 00:37:08 +01:00
Evarin
376cc96343 Clean, lint and fix little things 2019-01-06 00:17:57 +01:00
Martin Pepin
e0e75b53bb Merge branch 'aureplop/ci_parallel' into 'master'
core.ci -- Run tests in parallel

See merge request klub-dev-ens/gestioCOF!327
2019-01-05 19:36:20 +01:00
Aurélien Delobelle
aba0be7960 kfet.test -- Isolate kfet_open in testcases to avoid cache collisions 2019-01-05 19:19:58 +01:00
Martin Pepin
a057776e1f Merge branch 'aureplop/linters-for-petitscours' into 'master'
style -- Linters for petitscours, fix isort

See merge request klub-dev-ens/gestioCOF!335
2019-01-05 19:16:28 +01:00
Martin Pepin
e21154e869 Merge branch 'aureplop/kfet-tests_cancel_operations' into 'master'
kfet.tests -- Add tests for cancel_operations view + small things

See merge request klub-dev-ens/gestioCOF!315
2019-01-05 19:15:49 +01:00
Evarin
f105225abf Commentaires dans le code 2019-01-05 18:50:53 +01:00
Aurélien Delobelle
debbf265c4 style -- Linters for petitscours, fix isort 2019-01-05 18:19:26 +01:00
Aurélien Delobelle
8db55d792c core.ci -- Run tests in parallel
tblib displays traceback correctly with --parallel
2019-01-05 17:41:41 +01:00
Aurélien Delobelle
09e99ee3a3 bda.tests -- Add tests for descriptions_spectacles view 2019-01-05 15:28:11 +01:00
Aurélien Delobelle
3e38e48d7a bda.tests -- Add tests for tirage inscription view 2019-01-05 15:28:11 +01:00
Aurélien Delobelle
1664554083 bda.tests -- Add Spectacle factories 2019-01-05 15:28:11 +01:00
Aurélien Delobelle
f8610d4ff1 bda.tests -- Split view tests and use shared test helpers 2019-01-05 15:28:11 +01:00
Aurélien Delobelle
a71fbb0ed3 tests -- Ignore url entries without name 2019-01-05 15:28:05 +01:00
Aurélien Delobelle
57a2af285a bda -- Add name to bda url 2019-01-05 15:27:05 +01:00
Robin Champenois
e6e4a13440 Merge branch 'Elarnon/master' into 'master'
Ajoute une option "Master" pour les petits cours

See merge request klub-dev-ens/gestioCOF!334
2018-12-21 11:12:08 +01:00
Basile Clement
f9ddee60ed Ajoute une option "Master" pour les petits cours
À la demande du COF, car il y a des parents qui demandent et illes se
retrouvent à changer les demande "Autres" en "Licence 3" via l'admin
Django.  En pratique, il y aura sans doute très peu de profs qui
proposent des cours de Master (aussi appelé "le problème des gens qui
remplissent leurs compétences une seule fois en conscritude");  il
faudra donc tout de même laisser la possibilité au COF de changer
manuellement pour matcher avec "Licence 3", mais faisons une chose à la
fois.  On pourrait aussi harceler les gens pour qu'illes mettent à jour
leurs compétences en début d'année (c'est-à-dire mettre un bandeau
temporaire pour leur rappeler que si illes mettent à jour leurs
compétences ça augmente leur chance d'obtenir des cours).
2018-12-10 20:54:39 +01:00
Ludovic Stephan
66104e1137 Black 2018-12-08 10:41:46 +01:00
Ludovic Stephan
15ab316909 Merge branch 'master' into Aufinal/prettify-revente 2018-12-08 10:40:10 +01:00
Ludovic Stephan
6be42d57ca Prettify revente/shotgun 2018-12-07 17:35:53 +01:00
Ludovic Stephan
5c8164dd3b Prettify revente/tirages 2018-12-07 17:35:40 +01:00
Ludovic Stephan
625825cf3f Améliore TemplateLabelField
- Rajouter une option pour `option_template_name` et `context_object_name` dans la classe, et documente mieux. Répercute ces changements dans `InscriptionReventeForm`.
2018-12-07 17:33:17 +01:00
Ludovic Stephan
dee2f4badc Merge branch 'Elarnon/petitscours_proposals_cleanup' into 'master'
[petitscours] Extrait la proposition de profs dans une méthode

See merge request klub-dev-ens/gestioCOF!332
2018-12-03 21:15:17 +01:00
Martin Pepin
633cd49094 Merge branch 'Elarnon/cofburo_required' into 'master'
Améliore l'ergonomie de `cof_required` et `buro_required`

See merge request klub-dev-ens/gestioCOF!333
2018-11-27 10:13:32 +01:00
Martin Pepin
d58d08a4d4 Merge branch 'Elarnon/petitscours_app' into 'master'
Extrait les petits cours dans une application séparée

See merge request klub-dev-ens/gestioCOF!331
2018-11-26 23:00:56 +01:00
Basile Clement
5f9695ef8e isort 2018-11-25 18:32:04 +01:00
Basile Clement
2e08951d44 Améliore l'ergonomie de cof_required et buro_required
Ce patch rend les décorateurs `cof_required` et `buro_required` plus
agréables pour les utilisateurs; en particulier, ils ne font plus une
redirection sur la page de connexion si la condition n'est pas remplie.

Dans les deux cas :

 - Si l'utilisateur n'est pas connecté, il est renvoyé sur la page de
   connexion

 - Si l'utilisateur est connecté mais pas membre du COF/du Burô, une
   page d'erreur "403 Forbidden" est affichée.  Dans le cas de
   `cof_required` cette page demande à l'utilisateur de s'inscrire au
   COF; dans le cas `buro_required` elle indique simplement que la page
   est réservée au Burô.

gestioncof/
 * gestioncof/templates/buro-denied.html:  Ajouté.
 * decorators.py:

bda/
 * tests/test_views.py:
       Modifié pour correctement gérer le nouveau fonctionnement des
       décorateurs.
2018-11-25 18:11:23 +01:00
Basile Clement
2b8f81c94b [petitscours] Extrait la proposition de profs dans une méthode
Ce patch simplifie le code (dupliqué) de calcul des proposition de profs
pour une demande dans une méthode du modèle`Demande`, et l'utilise.  Il
s'agit d'un préparatif pour #208; ce code devra être réutilisé dans le
nouveau système.

J'en ai également profité pour nettoyer deux vues de `petitscours`,
`retraitement` et `demande_raw`, qui dupliquaient les vues `traitement`
et `demande`, en utilisant des arguments nommés.

petitscours/
 * models.py:
    Définition de `get_proposals` pour calculer les propositions de
    profs pour une demande.
 * views.py:
    Utilise `get_proposals` à la place du code copié-collé.  La fonction
    `_finalize_traitement` est maintenant responsable du calcul des
    `proposed_for` et `attribdata` à fournir aux templates.
 * urls.py:
    Passe directement les arguments aux vues plutôt que de faire deux
    fonctions séparées.
2018-11-25 17:05:55 +01:00
Basile Clement
c960d97b67 Extrait les petits cours dans une application séparée
L'application `petitscours` reste assez fortement couplée à
`gestioncof`, et n'est pas (encore ?) faite pour être utilisée
séparément.

De façon similaire, et afin de minimiser de potentiels problèmes dûs à
des migrations, les modèles de l'application `petitscours` utilisent
`app_label = "gestioncof"` pour que Django les considère comme faisant
partie de l'application `"gestioncof"`.  Ils pourront être migrés dans
un second temps si cela s'avère nécessaire.

Les changements sont nombreux, mais assez simples: il s'agit
principalement de déplacer des fichiers et changer des imports.  J'ai
également profité de l'occasion pour réorganiser les templates afin de
les placer dans l'espace de nom "petitscours/".

cof/
 * settings/common.py: Add `petitscours` app
 * urls.py: Use `petitscours.urls`

petitscours/
 * __init__.py: Added.
 * tests/__init__.py: Added.
 * tests/utils.py: Added.
 * urls.py: Added.

gestioncof/
 * admin.py:
 * management/commands/loaddevdata.py:
 * models.py:
 * signals.py: Typo.
 * urls.py:
       Moved petitscours_patterns to petitscours.urls
 * petits_cours_forms.py:
       Moved to petitscours/forms.py
 * petits_cours_models.py:
       Moved to petitscours/models.py
 * petits_cours_views.py:
       Moved to petitscours/views.py
 * tests/utils.py:
 * tests/test_petitscours_views.py:
       Moved to petitscours/tests/test_petitscours_views.py
 * templates/base_title_petitscours.html:
       Moved to petitscours/templates/petitscours/base_title.html
 * templates/demande-petit-cours.html:
       Moved topetitscours/templates/petitscours/demande.html
 * templates/gestioncof/details_demande_petit_cours.html:
       Moved to petitscours/templates/petitscours/demande_detail.html
 * templates/petits_cours_demandes_list.html:
       Moved to petitscours/templates/petitscours/demande_list.html
 * templates/demande-petit-cours-raw.html:
       Moved to petitscours/templates/petitscours/demande_raw.html
 * templates/details_demande_petit_cours_infos.html:
       Moved to petitscours/templates/petitscours/details_demande_infos.html
 * templates/inscription-petit-cours.html:
       Moved to petitscours/templates/petitscours/inscription.html
 * templates/inscription-petit-cours-formset.html:
       Moved to petitscours/templates/petitscours/inscription_formset.html
 * templates/gestioncof/traitement_demande_petit_cours.html:
       Moved to petitscours/templates/petitscours/traitement_demande.html
 * templates/gestioncof/traitement_demande_petit_cours_autre_niveau.html:
       Moved to petitscours/templates/petitscours/traitement_demande_autre_niveau.html
 * templates/gestioncof/traitement_demande_petit_cours_success.html:
       Moved to petitscours/templates/petitscours/traitement_demande_success.html
2018-11-25 13:25:16 +01:00
Ludovic Stephan
d82c9baf20 Bump django-redis-cache version to 1.8.1
The `django-redis` package does not work with redis 3.0, and previous
versions of this package did not hardcode the version number.
2018-11-25 00:48:57 +01:00
Ludovic Stephan
4ae0b3c5f0 Merge branch 'aureplop/cof-tests_petitcours' into 'master'
petitcours.tests -- Add tests for some views

See merge request klub-dev-ens/gestioCOF!325
2018-11-25 00:41:51 +01:00
Basile Clement
4e34583e3f black 2018-11-25 00:23:43 +01:00
Basile Clement
a2116bf290 Merge branch 'master' into aureplop/cof-tests_petitcours 2018-11-25 00:22:16 +01:00
Basile Clement
d48cb3aaed petitcours.tests -- Deplace les tests dans leur propre fichier 2018-11-25 00:22:12 +01:00
Ludovic Stephan
dbd017f680 Prettify revente/subscribe 2018-11-21 19:47:20 +01:00
Martin Pépin
712588af7d Merge branch 'master' into evarin/site-cof 2018-11-19 23:30:33 +01:00
Robin Champenois
6524f89ebd Merge branch 'Elarnon/bda_tirage_message_d_erreur_quand_il_y_a_une_erreur' into 'master'
Affiche un message d'erreur lors de l'enregistrement des voeux BDA

See merge request klub-dev-ens/gestioCOF!330
2018-11-12 23:22:38 +01:00
Basile Clement
7f2f25cb71 Isort 2018-11-12 23:04:37 +01:00
Basile Clement
042ce80b78 Run black 2018-11-12 22:52:20 +01:00
Basile Clement
d7f4d32c92 Oh mon dieu! 2018-11-12 22:46:02 +01:00
Basile Clement
b80927efa3 Message d'erreur qui ne parle pas de object Voeu 2018-11-12 22:44:09 +01:00
Basile Clement
511981e762 Simplifie la Logique 2018-11-12 22:22:49 +01:00
Basile Clement
e09fa2b847 Affiche un message d'erreur lors de l'enregistrement des voeux BDA
Voir #203
2018-11-12 22:16:43 +01:00
Robin Champenois
39d82a573f Merge branch 'Elarnon/autoriser_la_suppression_dun_voeud_bda_qui_nexiste_pas' into 'master'
Permet la suppression d'un voeu ajouté mais non enregistré

See merge request klub-dev-ens/gestioCOF!329
2018-11-12 22:03:07 +01:00
Basile Clement
7124821f7c Permet la suppression d'un voeu ajouté mais non enregistré
Voir #203.  Cette solution est horrible, tout comme le code dans
lequel elle se trouve.  Déso pas déso.
2018-11-12 21:56:40 +01:00
Ludovic Stephan
ba21de683b Merge branch 'Elarnon/cas_v3_v2' into 'master'
Fix CAS support in python-cas 1.3+

See merge request klub-dev-ens/gestioCOF!328
2018-11-12 21:09:14 +01:00
Basile Clement
00a1e79af6 Fix CAS support in python-cas 1.3+
cas.eleves.ens.fr has /serviceValidate, not /p3/serviceValidate, and is
thus *probably* a V2 CAS server.  python-cas was broken and using
/serviceValidate for V3 while it should have been /p3/serviceValidate,
see
c3ac4b6c76
2018-11-12 00:54:44 +01:00
Ludovic Stephan
95ba7798d7 Ignore VSCode files 2018-11-04 23:07:57 +01:00
Aurélien Delobelle
0fe63d3eae petitcours.tests -- Add tests for demande (raw) views 2018-10-27 22:29:55 +02:00
Aurélien Delobelle
3d27dc9a41 petitcours.tests -- Add tests for inscription and (re)traitement views 2018-10-27 19:18:58 +02:00
Aurélien Delobelle
1a5bbf32a4 petitcours.tests -- Add tests for demandes list and details views 2018-10-27 19:18:58 +02:00
Aurélien Delobelle
25dfe2f496 petitcours.tests -- Add PCAbility, PCDemande and PCSubject factories 2018-10-27 19:18:58 +02:00
Aurélien Delobelle
8be913cbf9 style -- black 2018-10-27 13:37:39 +02:00
Aurélien Delobelle
b69f1b6dbc kfet.tests -- Add tests for cancel_operations view 2018-10-21 13:07:44 +02:00
Aurélien Delobelle
d7ca072af3 kfet.tests -- Add factories for many kfet models
- Article
- ArticleCategory
- Checkout
- CheckoutStatement
- Inventory
- InventoryArticle
- Operation
- OperationGroup
2018-10-21 12:50:09 +02:00
Aurélien Delobelle
928abc5a06 core -- Bump version django-djconfig to 0.8.0
Bump djcondig to last version.

Previously used version was failing on some updates, e.g:
kfet_config.set(cancel_duration=timedelta(minutes=15))
2018-10-21 12:50:09 +02:00
Evarin
128a9e32c0 I18n des menus 2018-10-14 16:29:26 +02:00
Evarin
1e3850bb6b Nettoyage dates et calendrier 2018-10-14 15:50:55 +02:00
Evarin
954a6fdb53 Wagtail requirement update 2018-06-30 15:52:58 +02:00
Evarin
6d6ba70bd7 CSS++ 2018-06-30 15:38:12 +02:00
Evarin
6d72644ee3 Clean code up 2018-04-28 15:59:49 +02:00
Evarin
3d091f50b5 Suppr captcha page, ajout block iframe 2018-03-21 21:53:48 +01:00
Evarin
347497602c Revert urls prefixing 2018-02-20 17:21:26 +01:00
Evarin
6d6c995563 Fixtures fonctionnelles 2018-02-20 17:13:21 +01:00
Evarin
63ce694b4d Fix dependency 2018-02-03 22:39:50 +01:00
Evarin
59116f2d46 International wagtail urls 2018-02-03 22:34:37 +01:00
Evarin
88e911ff9d Fixtures mises à jour 2018-01-28 23:45:46 +01:00
Evarin
ba87044638 Calendrier dynamique + sympa + jolies dates 2018-01-28 23:44:48 +01:00
Evarin
f8952225d6 Apparence et Responsiveness 2018-01-28 19:10:14 +01:00
Evarin
c11ccf2ecc Tri des annuaires 2018-01-28 19:09:35 +01:00
Evarin
8488beeb4e Un seul modèle pour les actus 2018-01-22 21:24:20 +01:00
Evarin
8551ffcfd3 Merge branch 'master' into evarin/site-cof 2018-01-20 19:37:12 +01:00
Evarin
ea495e8f29 Archives beta 2018-01-20 19:33:50 +01:00
Evarin
adf43889e1 Fixtures site cof 2017-10-23 11:05:49 +02:00
Evarin
5a22b1cd37 Affichage des actus 2017-10-10 11:22:02 +02:00
Evarin
0e19abb51a Cleaner homepage 2017-09-27 23:58:50 +02:00
Evarin
38af50a866 Nouvelles couleurs 2017-08-29 17:58:44 +02:00
Evarin
7853987ebb Plus de templates, plus joli 2017-08-26 18:05:20 +02:00
Evarin
09e63bf00c Actus et listes de clubs plus jolies et fonctionnelles, calendriers (beta) 2017-08-22 00:58:18 +02:00
Evarin
53658589f8 Nouvelles couleurs, Plus de templates, Calendrier (sommaire) 2017-08-20 00:39:19 +02:00
Evarin
f5778fed2a Modèles plus cleans et templates principaux 2017-08-19 01:32:26 +02:00
Evarin
66fc364739 Ignore sass cache 2017-08-19 01:29:45 +02:00
Evarin
6023211ab0 Models des pages et traductions 2017-08-09 00:07:56 +02:00
Evarin
65d7a66eb8 Début nouveau site cof 2017-08-07 23:31:27 +02:00
717 changed files with 74585 additions and 49617 deletions

1
.envrc Normal file
View file

@ -0,0 +1 @@
use nix

6
.gitignore vendored
View file

@ -5,13 +5,19 @@ cof/settings.py
settings.py
*~
venv/
.venv/
.vagrant
/src
media/
*.log
.sass-cache/
*.sqlite3
.coverage
# PyCharm
.idea
.cache
# VSCode
.vscode/
.direnv

View file

@ -1,8 +1,7 @@
image: "python:3.5"
image: "python:3.7"
variables:
# GestioCOF settings
DJANGO_SETTINGS_MODULE: "cof.settings.prod"
DBHOST: "postgres"
REDIS_HOST: "redis"
REDIS_PASSWD: "dummy"
@ -18,23 +17,23 @@ variables:
# psql password authentication
PGPASSWORD: $POSTGRES_PASSWORD
test:
stage: test
# apps to check migrations for
MIGRATION_APPS: "bda bds cofcms clubs events gestioncof kfet kfetauth kfetcms open petitscours shared"
.test_template:
before_script:
- mkdir -p vendor/{pip,apt}
- apt-get update -q && apt-get -o dir::cache::archives="vendor/apt" install -yqq postgresql-client
- sed -E 's/^REDIS_HOST.*/REDIS_HOST = "redis"/' cof/settings/secret_example.py > cof/settings/secret.py
- sed -i.bak -E 's;^REDIS_PASSWD = .*$;REDIS_PASSWD = "";' cof/settings/secret.py
- apt-get update -q && apt-get -o dir::cache::archives="vendor/apt" install -yqq postgresql-client libldap2-dev libsasl2-dev
- sed -E 's/^REDIS_HOST.*/REDIS_HOST = "redis"/' gestioasso/settings/secret_example.py > gestioasso/settings/secret.py
- sed -i.bak -E 's;^REDIS_PASSWD = .*$;REDIS_PASSWD = "";' gestioasso/settings/secret.py
# Remove the old test database if it has not been done yet
- psql --username=$POSTGRES_USER --host=$DBHOST -c "DROP DATABASE IF EXISTS test_$POSTGRES_DB"
- pip install --upgrade -r requirements.txt coverage
- pip install --upgrade -r requirements-prod.txt coverage tblib
- python --version
script:
- coverage run manage.py test
after_script:
- coverage report
services:
- postgres:9.6
- postgres:11.7
- redis:latest
cache:
key: test
@ -44,18 +43,61 @@ test:
# Keep this disabled for now, as it may kill GitLab...
# 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:
stage: test
extends: .test_template
variables:
DJANGO_SETTINGS_MODULE: "gestioasso.settings.cof_prod"
script:
- coverage run manage.py test gestioncof bda petitscours shared --parallel
bdstest:
stage: test
extends: .test_template
variables:
DJANGO_SETTINGS_MODULE: "gestioasso.settings.bds_prod"
script:
- coverage run manage.py test bds clubs events --parallel
linters:
image: python:3.6
stage: test
before_script:
- mkdir -p vendor/pip
- pip install --upgrade black isort flake8
script:
- black --check .
- isort --recursive --check-only --diff bda cof gestioncof kfet provisioning shared utils
- isort --check --diff .
# Print errors only
- flake8 --exit-zero bda cof gestioncof kfet provisioning shared utils
- flake8 --exit-zero bda bds clubs gestioasso events gestioncof kfet petitscours provisioning shared
cache:
key: linters
paths:
- vendor/
# Check whether there are some missing migrations.
migration_checks:
stage: test
variables:
DJANGO_SETTINGS_MODULE: "gestioasso.settings.local"
before_script:
- mkdir -p vendor/{pip,apt}
- apt-get update -q && apt-get -o dir::cache::archives="vendor/apt" install -yqq postgresql-client libldap2-dev libsasl2-dev
- cp gestioasso/settings/secret_example.py gestioasso/settings/secret.py
- pip install --upgrade -r requirements-devel.txt
- python --version
script: python manage.py makemigrations --dry-run --check $MIGRATION_APPS
services:
# this should not be necessary…
- postgres:11.7
cache:
key: migration_checks
paths:
- vendor/

View file

@ -48,7 +48,7 @@ if type isort &>/dev/null; then
ISORT_OUTPUT="/tmp/gc-isort-output.log"
touch $ISORT_OUTPUT
if ! echo "$STAGED_PYTHON_FILES" | xargs -d'\n' isort --check-only &>$ISORT_OUTPUT; then
if ! echo "$STAGED_PYTHON_FILES" | xargs -d'\n' isort --check &>$ISORT_OUTPUT; then
echo "$STAGED_PYTHON_FILES" | xargs -d'\n' isort &>$ISORT_OUTPUT
printf "Reformatted.\n"
formatter_updated=1

303
CHANGELOG.md Normal file
View file

@ -0,0 +1,303 @@
# Changelog
Liste des changements notables dans GestioCOF depuis la version 0.1 (septembre
2018).
## Le FUTUR ! (pas prêt pour la prod)
### Nouveau module de gestion des événements
- Désormais complet niveau modèles
- Export des participants implémenté
#### TODO
- Vue de création d'événements ergonomique
- Vue d'inscription à un événement **ou** intégration propre dans la vue
"inscription d'un nouveau membre"
### Nouveau module de gestion des clubs
Uniquement un modèle simple de clubs avec des respos. Aucune gestion des
adhérents ni des cotisations.
## 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
## 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
### COF
- Répare un problème de rendu sur le wagtail du COF
### K-Fêt
- Ajoute de mails de rappels pour les comptes en négatif
- La recherche de comptes sur K-Psul remarche normalement
- Le pointeur de la souris change de forme quand on survole un item d'autocomplétion
- Modification du gel de compte:
- on ne peut plus geler/dégeler son compte soi-même (il faut la permission "Gérer les permissions K-Fêt")
- on ne peut rien compter sur un compte gelé (aucune override possible), et les K-Fêteux·ses dont le compte est gelé perdent tout accès à K-Psul
- les comptes actuellement gelés (sur l'ancien système) sont dégelés automatiquement
- Modification du fonctionnement des négatifs
- impossible d'avoir des négatifs inférieurs à `kfet_config.overdraft_amount`
- il n'y a plus de limite de temps sur les négatifs
- supression des autorisations de négatif
- il n'est plus possible de réinitialiser la durée d'un négatif en faisant puis en annulant une charge
- La gestion des erreurs passe du client au serveur, ce qui permet d'avoir des messages plus explicites
- La supression d'opérations anciennes est réparée
## Version 0.10 - 18/04/2021
### K-Fêt
- On fait sauter la limite qui empêchait de vendre plus de 24 unités d'un item à
la fois.
- L'interface indique plus clairement quand on fait une erreur en modifiant un
compte.
- On supprime la fonction "décalage de balance".
- L'accès à l'historique est maintenant limité à 7 jours pour raison de
confidentialité. Les chefs/trez peuvent disposer d'une permission
supplémentaire pour accéder à jusqu'à 30 jours en cas de problème de compta.
L'accès à son historique personnel n'est pas limité. Les durées sont
configurables dans `settings/cof_prod.py`.
### COF
- Le Captcha sur la page de demande de petits cours utilise maintenant hCaptcha
au lieu de ReCaptcha, pour mieux respecter la vie privée des utilisateur·ices
## Version 0.9 - 06/02/2020
### COF / BdA
- Le COF peut remettre à zéro la liste de ses adhérents en août (sans passer par
KDE).
- La page d'accueil affiche la date de fermeture des tirages BdA.
- On peut revendre une place dès qu'on l'a payée, plus besoin de payer toutes
ses places pour pouvoir revendre.
- On s'assure que l'email fourni lors d'une demande de petit cours est valide.
### BDS
- Le burô peut maintenant accorder ou révoquer le statut de membre du Burô
en modifiant le profil d'un membre du BDS.
- Le burô peut exporter la liste de ses membres avec email au format CSV depuis
la page d'accueil.
### K-Fêt
- On affiche les articles actuellement en vente en premier lors des inventaires
et des commandes.
- On peut supprimer un inventaire. Seuls les articles dont c'est le dernier
inventaire sont affectés.
## Version 0.8 - 03/12/2020
### COF
- La page "Mes places" dans la section BdA indique quelles places sont sur
listing.
- ergonomie de l'interface admin du BdA : moins d'options inutiles lors de
la sélection de participants.
- les tirages sont maintenant archivables pour éviter d'avoir encore d'autres
options inutiles.
- l'autocomplétion dans l'admin BdA est réparée.
- Les icones de la page de gestion des petits cours sont (à nouveau) réparées.
- On a supprimé la possibilité de modifier les mails automatiques depuis
l'interface admin car trop problématique. Faute de mieux, envoyer un mail à
KDE pour modifier ces mails.
- corrige un crash sporadique sur la page d'inscription au système de petits
cours
### K-Fêt
- (fix partiel) Empêche la K-Fêt de modifier des données COF (e.g. nom, prénom,
username) lors de la création d'un nouveau compte.
- Les statistiques de conso globales montrent deux courbes COF / non-COF au
lieu de LIQ / sur compte.
- Un bug empêchait de fermer manuellement la K-Fêt depuis un compte non
privilégié en tapant un mot de passe. C'est corrigé.
## Version 0.7.2 - 08/09/2020
- Nouvelle page 404
- Correction de bug en K-Fêt : le lien pour créer un nouveau compte exté apparaît
à nouveau dans l'autocomplétion
## Version 0.7.1 - 05/09/2020
Petits ajustements sur le site du COF :
- Possibilité d'ajouter des champs d'infos supplémentaires en plus de l'email et
de la page web dans les annuaires (clubs et partenaires).
- Corrige un bug d'affichage des adresses emails de clubs
## Version 0.7 - 29/08/2020
### GestioBDS
- Ajout d'un bouton pour supprimer un compte
- Le nombre d'adhérent⋅es est affiché sur la page d'accueil
- le groupe BDS a les bonnes permissions
### Site du COF
- Captcha fonctionnel pour les mailing-listes
### K-Fêt
- L'autocomplétion pour la création de compte K-Fêt se lance à 3 caractères seulement,
donc est plus rapide.
## Version 0.6 - 27/07/2020
Arrivée du BDS !
GestioCOF et GestioBDS ont du code en commun mais tournent de façon séparée, les
deux bases de données sont distinctes.
## Version 0.5 - 11/07/2020
### Problèmes corrigés
- La recherche d'utilisateurices (COF + K-Fêt) fonctionne de nouveau
- Bug d'affichage quand on a beaucoup de clubs dans le cadre "Accès rapide" sur
la page des clubs (nouveau site du COF)
- Version mobile plus ergonimique sur le nouveau site du COF
- Cliquer sur "visualiser" sur les pages de clubs dans wagtail ne provoque plus
d'erreurs 500 (nouveau site du COF)
- L'historique des ventes des articles K-Fêt fonctionne à nouveau
- Les montants en K-Fêt sont à nouveau affichés en UKF (et non en €).
- Les boutons "afficher/cacher" des mails et noms des participant⋅e⋅s à un
spectacle BdA fonctionnent à nouveau.
- on ne peut plus compter de consos sur ☠☠☠, ni éditer les comptes spéciaux
(LIQ, GNR, ☠☠☠, #13).
### Nouvelles fonctionnalités
- On n'affiche que 4 articles sur la pages "nouveautés" (nouveau site du COF)
- Plus de traductions sur le nouveau site du COF
- Les transferts apparaissent maintenant dans l'historique K-Fêt et l'historique
personnel.
- les statistiques K-Fêt remontent à plus d'un an (et le code est simplifié)
## Version 0.4.1 - 17/01/2020
- Corrige un bug sur K-Psul lorsqu'un trigramme contient des caractères réservés
aux urls (\#, /...)
## Version 0.4 - 15/01/2020
- Corrige un bug d'affichage d'images sur l'interface des petits cours
- La page des transferts permet de créer un nombre illimité de transferts en
une fois.
- Nouveau site du COF : les liens sont optionnels dans les descriptions de clubs
- Mise à jour du lien vers le calendire de la K-Fêt sur la page d'accueil
- Certaines opérations sont à nouveau accessibles depuis la session partagée
K-Fêt.
- Le bouton "déconnexion" déconnecte vraiment du CAS pour les comptes clipper
- Corrige un crash sur la page des reventes pour les nouveaux participants.
- Corrige un bug d'affichage pour les trigrammes avec caractères spéciaux
## Version 0.3.3 - 30/11/2019
- Corrige un problème de redirection lors de la déconnexion (CAS seulement)
- Les catégories d'articles K-Fêt peuvent être exemptées de subvention COF
- Corrige un bug d'affichage dans K-Psul quand on annule une transaction sur LIQ
- Corrige une privilege escalation liée aux sessions partagées en K-Fêt
https://git.eleves.ens.fr/klub-dev-ens/gestioCOF/issues/240
## Version 0.3.2 - 04/11/2019
- Bugfix: modifier un compte K-Fêt ne supprime plus nom/prénom
## Version 0.3.1 - 19/10/2019
- Bugfix: l'historique des utilisateurices s'affiche à nouveau
## Version 0.3 - 16/10/2019
- Comptes extés: lien pour changer son mot de passe sur la page d'accueil
- Les utilisateurices non-COF peuvent éditer leur profil
- Un peu de pub pour KDEns sur la page d'accueil
- Fix erreur 500 sur /bda/revente/<tirage_id>/manage
- Si on essaie d'accéder au compte que qqn d'autre on a une 404 (et plus une 403)
- On ne peut plus modifier des comptes COF depuis l'interface K-Fêt
- Le champ de paiement BdA se fait au niveau des attributions
- Affiche un message d'erreur plutôt que de crasher si échec de l'envoi du mail
de bienvenue aux nouveaux membres
- On peut supprimer des comptes et des articles K-Fêt
- Passage à Django2
- Dev : on peut désactiver la barre de debug avec une variable shell
- Remplace les CSS de Google par des polices de proximité
- Passage du site du COF et de la K-Fêt en Wagtail 2.3 et Wagtail-modeltranslation 0.9
- Ajoute un lien vers l'administration générale depuis les petits cours
- Abandon de l'ancien catalogue BdA (déjà plus utilisé depuis longtemps)
- Force l'unicité des logins clipper
- Nouveau site du COF en wagtail
- Meilleurs affichage des longues listes de spectacles à cocher dans BdA-Revente
- Bugfix : les pages de la revente ne sont plus accessibles qu'aux membres du
COF
## Version 0.2 - 07/11/2018
- Corrections de bugs d'interface dans l'inscription aux tirages BdA
- On peut annuler une revente à tout moment
- Pleiiiiin de tests
## Version 0.1 - 09/09/2018
Début de la numérotation des versions, début du changelog

View file

@ -1,4 +1,4 @@
# GestioCOF
# GestioCOF / GestioBDS
[![pipeline status](https://git.eleves.ens.fr/cof-geek/gestioCOF/badges/master/pipeline.svg)](https://git.eleves.ens.fr/cof-geek/gestioCOF/commits/master)
[![coverage report](https://git.eleves.ens.fr/cof-geek/gestioCOF/badges/master/coverage.svg)](https://git.eleves.ens.fr/cof-geek/gestioCOF/commits/master)
@ -38,11 +38,11 @@ Vous pouvez maintenant installer les dépendances Python depuis le fichier
pip install -U pip # parfois nécessaire la première fois
pip install -r requirements-devel.txt
Pour terminer, copier le fichier `cof/settings/secret_example.py` vers
`cof/settings/secret.py`. Sous Linux ou Mac, préférez plutôt un lien symbolique
Pour terminer, copier le fichier `gestioasso/settings/secret_example.py` vers
`gestioasso/settings/secret.py`. Sous Linux ou Mac, préférez plutôt un lien symbolique
pour profiter de façon transparente des mises à jour du fichier:
ln -s secret_example.py cof/settings/secret.py
ln -s secret_example.py gestioasso/settings/secret.py
Nous avons un git hook de pre-commit pour formatter et vérifier que votre code
vérifie nos conventions. Pour bénéficier des mises à jour du hook, préférez
@ -186,6 +186,18 @@ Pour lancer les tests :
python manage.py test
```
### Astuces
- En développement on utilise la django debug toolbar parce que c'est utile pour
débuguer les templates ou les requêtes SQL mais des fois c'est pénible parce
ça fait ramer GestioCOF (surtout dans wagtail).
Vous pouvez la désactiver temporairement en définissant la variable
d'environnement `DJANGO_NO_DDT` dans votre shell : par exemple dans
bash/zsh/…:
```
$ export DJANGO_NO_DDT=1
```
## Documentation utilisateur

View file

@ -1 +0,0 @@
- Changer les urls dans les mails "bda-revente" et "bda-shotgun"

42
Vagrantfile vendored
View file

@ -1,47 +1,19 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
# Configuration de base pour GestioCOF.
# Voir https://docs.vagrantup.com pour plus d'informations.
Vagrant.configure(2) do |config|
# The most common configuration options are documented and commented below.
# For a complete reference, please see the online documentation at
# https://docs.vagrantup.com.
config.vm.box = "ubuntu/xenial64"
# On se base sur Debian 10 (Buster) pour avoir le même environnement qu'en
# production.
config.vm.box = "debian/contrib-buster64"
# On associe le port 80 dans la machine virtuelle avec le port 8080 de notre
# ordinateur, et le port 8000 avec le port 8000.
config.vm.network :forwarded_port, guest: 80, host: 8080
config.vm.network :forwarded_port, guest: 8000, host: 8000
# Create a private network, which allows host-only access to the machine
# using a specific IP.
# config.vm.network "private_network", ip: "192.168.33.10"
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
# Example for VirtualBox:
#
# config.vm.provider "virtualbox" do |vb|
# # Display the VirtualBox GUI when booting the machine
# vb.gui = true
#
# # Customize the amount of memory on the VM:
# vb.memory = "1024"
# end
#
# View the documentation for the provider you are using for more
# information on available options.
# Enable provisioning with a shell script. Additional provisioners such as
# Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
# documentation for more information about their specific syntax and use.
# config.vm.provision "shell", inline: <<-SHELL
# sudo apt-get update
# sudo apt-get install -y apache2
# SHELL
# Le restes de la configuration (installation de paquets, etc) est géré un
# script shell.
config.vm.provision :shell, path: "provisioning/bootstrap.sh"
end

View file

@ -1,10 +1,11 @@
from datetime import timedelta
from custommail.shortcuts import send_mass_custom_mail
from dal.autocomplete import ModelSelect2
from django import forms
from django.contrib import admin
from django.db.models import Count, Sum
from django.core.mail import send_mass_mail
from django.db.models import Count, Q, Sum
from django.template import loader
from django.template.defaultfilters import pluralize
from django.utils import timezone
@ -32,20 +33,6 @@ class ReadOnlyMixin(object):
return readonly_fields + self.readonly_fields_update
class ChoixSpectacleAdminForm(forms.ModelForm):
class Meta:
widgets = {
"participant": ModelSelect2(url="bda-participant-autocomplete"),
"spectacle": ModelSelect2(url="bda-spectacle-autocomplete"),
}
class ChoixSpectacleInline(admin.TabularInline):
model = ChoixSpectacle
form = ChoixSpectacleAdminForm
sortable_field_name = "priority"
class AttributionTabularAdminForm(forms.ModelForm):
listing = None
@ -81,27 +68,51 @@ class WithListingAttributionInline(AttributionInline):
exclude = ("given",)
form = WithListingAttributionTabularAdminForm
listing = True
verbose_name_plural = "Attributions sur listing"
class WithoutListingAttributionInline(AttributionInline):
form = WithoutListingAttributionTabularAdminForm
listing = False
verbose_name_plural = "Attributions hors listing"
class ParticipantAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["choicesrevente"].queryset = Spectacle.objects.select_related(
"location"
)
queryset = Spectacle.objects.select_related("location")
if self.instance.pk is not None:
queryset = queryset.filter(tirage=self.instance.tirage)
self.fields["choicesrevente"].queryset = queryset
class ParticipantPaidFilter(admin.SimpleListFilter):
"""
Permet de filtrer les participants sur s'ils ont payé leurs places ou pas
"""
title = "A payé"
parameter_name = "paid"
def lookups(self, request, model_admin):
return ((True, "Oui"), (False, "Non"))
def queryset(self, request, queryset):
return queryset.filter(paid=self.value())
class ParticipantAdmin(ReadOnlyMixin, admin.ModelAdmin):
inlines = [WithListingAttributionInline, WithoutListingAttributionInline]
def get_queryset(self, request):
return Participant.objects.annotate(
nb_places=Count("attributions"), total=Sum("attributions__price")
return self.model.objects.annotate_paid().annotate(
nb_places=Count("attributions"),
remain=Sum(
"attribution__spectacle__price", filter=Q(attribution__paid=False)
),
total=Sum("attributions__price"),
)
def nb_places(self, obj):
@ -110,6 +121,13 @@ class ParticipantAdmin(ReadOnlyMixin, admin.ModelAdmin):
nb_places.admin_order_field = "nb_places"
nb_places.short_description = "Nombre de places"
def paid(self, obj):
return obj.paid
paid.short_description = "A payé"
paid.boolean = True
paid.admin_order_field = "paid"
def total(self, obj):
tot = obj.total
if tot:
@ -118,31 +136,46 @@ class ParticipantAdmin(ReadOnlyMixin, admin.ModelAdmin):
return "0 €"
total.admin_order_field = "total"
total.short_description = "Total à payer"
list_display = ("user", "nb_places", "total", "paid", "paymenttype", "tirage")
list_filter = ("paid", "tirage")
total.short_description = "Total des places"
def remain(self, obj):
rem = obj.remain
if rem:
return "%.02f" % rem
else:
return "0 €"
remain.admin_order_field = "remain"
remain.short_description = "Reste à payer"
list_display = ("user", "nb_places", "total", "paid", "remain", "tirage")
list_filter = (ParticipantPaidFilter, "tirage")
search_fields = ("user__username", "user__first_name", "user__last_name")
actions = ["send_attribs"]
actions_on_bottom = True
list_per_page = 400
readonly_fields = ("total",)
readonly_fields = ("total", "paid")
readonly_fields_update = ("user", "tirage")
form = ParticipantAdminForm
def send_attribs(self, request, queryset):
datatuple = []
emails = []
for member in queryset.all():
subject = "Résultats du tirage au sort"
attribs = member.attributions.all()
context = {"member": member.user}
shortname = ""
template_name = ""
if len(attribs) == 0:
shortname = "bda-attributions-decus"
template_name = "bda/mails/attributions-decus.txt"
else:
shortname = "bda-attributions"
template_name = "bda/mails/attributions.txt"
context["places"] = attribs
print(context)
datatuple.append((shortname, context, "bda@ens.fr", [member.user.email]))
send_mass_custom_mail(datatuple)
message = loader.render_to_string(template_name, context)
emails.append((subject, message, "bda@ens.fr", [member.user.email]))
send_mass_mail(emails)
count = len(queryset.all())
if count == 1:
message_bit = "1 membre a"
@ -158,17 +191,6 @@ class ParticipantAdmin(ReadOnlyMixin, admin.ModelAdmin):
class AttributionAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if "spectacle" in self.fields:
self.fields["spectacle"].queryset = Spectacle.objects.select_related(
"location"
)
if "participant" in self.fields:
self.fields["participant"].queryset = Participant.objects.select_related(
"user", "tirage"
)
def clean(self):
cleaned_data = super().clean()
participant = cleaned_data.get("participant")
@ -181,13 +203,14 @@ class AttributionAdminForm(forms.ModelForm):
)
return cleaned_data
class Meta:
widgets = {
"participant": ModelSelect2(url="bda-participant-autocomplete"),
"spectacle": ModelSelect2(url="bda-spectacle-autocomplete"),
}
class AttributionAdmin(ReadOnlyMixin, admin.ModelAdmin):
def paid(self, obj):
return obj.participant.paid
paid.short_description = "A payé"
paid.boolean = True
list_display = ("id", "spectacle", "participant", "given", "paid")
search_fields = (
"spectacle__title",
@ -200,7 +223,7 @@ class AttributionAdmin(ReadOnlyMixin, admin.ModelAdmin):
class ChoixSpectacleAdmin(admin.ModelAdmin):
form = ChoixSpectacleAdminForm
autocomplete_fields = ["participant", "spectacle"]
def tirage(self, obj):
return obj.participant.tirage
@ -244,15 +267,14 @@ class SalleAdmin(admin.ModelAdmin):
class SpectacleReventeAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["confirmed_entry"].queryset = Participant.objects.select_related(
"user", "tirage"
)
self.fields["seller"].queryset = Participant.objects.select_related(
"user", "tirage"
)
self.fields["soldTo"].queryset = Participant.objects.select_related(
"user", "tirage"
)
qset = Participant.objects.select_related("user", "tirage")
if self.instance.pk is not None:
qset = qset.filter(tirage=self.instance.seller.tirage)
self.fields["confirmed_entry"].queryset = qset
self.fields["seller"].queryset = qset
self.fields["soldTo"].queryset = qset
class SpectacleReventeAdmin(admin.ModelAdmin):

View file

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

View file

@ -1,8 +1,9 @@
from django import forms
from django.forms.models import BaseInlineFormSet
from django.template import loader
from django.utils import timezone
from bda.models import Attribution, Spectacle, SpectacleRevente
from bda.models import SpectacleRevente
class InscriptionInlineFormSet(BaseInlineFormSet):
@ -38,142 +39,146 @@ class TokenForm(forms.Form):
token = forms.CharField(widget=forms.widgets.Textarea())
class AttributionModelMultipleChoiceField(forms.ModelMultipleChoiceField):
def label_from_instance(self, obj):
return str(obj.spectacle)
class TemplateLabelField(forms.ModelMultipleChoiceField):
"""
Extends ModelMultipleChoiceField to offer two more customization options :
- `label_from_instance` can be used with a template file
- the widget rendering template can be specified with `option_template_name`
"""
class ReventeModelMultipleChoiceField(forms.ModelMultipleChoiceField):
def __init__(self, *args, own=True, **kwargs):
def __init__(
self,
label_template_name=None,
context_object_name="obj",
option_template_name=None,
*args,
**kwargs
):
super().__init__(*args, **kwargs)
self.own = own
self.label_template_name = label_template_name
self.context_object_name = context_object_name
if option_template_name is not None:
self.widget.option_template_name = option_template_name
def label_from_instance(self, obj):
label = "{show}{suffix}"
suffix = ""
if self.own:
# C'est notre propre revente : informations sur le statut
if obj.soldTo is not None:
suffix = " -- Vendue à {firstname} {lastname}".format(
firstname=obj.soldTo.user.first_name,
lastname=obj.soldTo.user.last_name,
)
elif obj.shotgun:
suffix = " -- Tirage infructueux"
elif obj.notif_sent:
suffix = " -- Inscriptions au tirage en cours"
if self.label_template_name is None:
return super().label_from_instance(obj)
else:
# Ce n'est pas à nous : on ne voit jamais l'acheteur
suffix = " -- Vendue par {firstname} {lastname}".format(
firstname=obj.seller.user.first_name, lastname=obj.seller.user.last_name
return loader.render_to_string(
self.label_template_name, context={self.context_object_name: obj}
)
return label.format(show=str(obj.attribution.spectacle), suffix=suffix)
# Formulaires pour revente_manage
class ResellForm(forms.Form):
attributions = AttributionModelMultipleChoiceField(
label="",
queryset=Attribution.objects.none(),
widget=forms.CheckboxSelectMultiple,
required=False,
)
def __init__(self, participant, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["attributions"].queryset = (
participant.attribution_set.filter(spectacle__date__gte=timezone.now())
self.fields["attributions"] = TemplateLabelField(
queryset=participant.attribution_set.filter(
spectacle__date__gte=timezone.now(), paid=True
)
.exclude(revente__seller=participant)
.select_related("spectacle", "spectacle__location", "participant__user")
.select_related("spectacle", "spectacle__location", "participant__user"),
widget=forms.CheckboxSelectMultiple,
required=False,
label_template_name="bda/forms/attribution_label_table.html",
option_template_name="bda/forms/checkbox_table.html",
context_object_name="attribution",
)
class AnnulForm(forms.Form):
reventes = ReventeModelMultipleChoiceField(
own=True,
label="",
queryset=Attribution.objects.none(),
widget=forms.CheckboxSelectMultiple,
required=False,
)
def __init__(self, participant, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["reventes"].queryset = (
participant.original_shows.filter(
self.fields["reventes"] = TemplateLabelField(
label="",
queryset=participant.original_shows.filter(
attribution__spectacle__date__gte=timezone.now(), soldTo__isnull=True
)
.select_related(
"attribution__spectacle", "attribution__spectacle__location"
)
.order_by("-date")
)
class InscriptionReventeForm(forms.Form):
spectacles = forms.ModelMultipleChoiceField(
queryset=Spectacle.objects.none(),
.order_by("-date"),
widget=forms.CheckboxSelectMultiple,
required=False,
)
def __init__(self, tirage, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["spectacles"].queryset = tirage.spectacle_set.select_related(
"location"
).filter(date__gte=timezone.now())
class ReventeTirageAnnulForm(forms.Form):
reventes = ReventeModelMultipleChoiceField(
own=False,
label="",
queryset=SpectacleRevente.objects.none(),
widget=forms.CheckboxSelectMultiple,
required=False,
)
def __init__(self, participant, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["reventes"].queryset = participant.entered.filter(
soldTo__isnull=True
).select_related("attribution__spectacle", "seller__user")
class ReventeTirageForm(forms.Form):
reventes = ReventeModelMultipleChoiceField(
own=False,
label="",
queryset=SpectacleRevente.objects.none(),
widget=forms.CheckboxSelectMultiple,
required=False,
)
def __init__(self, participant, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["reventes"].queryset = (
SpectacleRevente.objects.filter(
notif_sent=True, shotgun=False, tirage_done=False
)
.exclude(confirmed_entry=participant)
.select_related("attribution__spectacle")
label_template_name="bda/forms/revente_self_label_table.html",
option_template_name="bda/forms/checkbox_table.html",
context_object_name="revente",
)
class SoldForm(forms.Form):
reventes = ReventeModelMultipleChoiceField(
own=True,
label="",
queryset=Attribution.objects.none(),
widget=forms.CheckboxSelectMultiple,
)
def __init__(self, participant, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["reventes"].queryset = (
participant.original_shows.filter(soldTo__isnull=False)
self.fields["reventes"] = TemplateLabelField(
queryset=participant.original_shows.filter(soldTo__isnull=False)
.exclude(soldTo=participant)
.select_related(
"attribution__spectacle", "attribution__spectacle__location"
),
widget=forms.CheckboxSelectMultiple,
label_template_name="bda/forms/revente_sold_label_table.html",
option_template_name="bda/forms/checkbox_table.html",
context_object_name="revente",
)
# Formulaire pour revente_subscribe
class InscriptionReventeForm(forms.Form):
def __init__(self, tirage, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["spectacles"] = TemplateLabelField(
queryset=tirage.spectacle_set.select_related("location").filter(
date__gte=timezone.now()
),
widget=forms.CheckboxSelectMultiple,
required=False,
label_template_name="bda/forms/spectacle_label_table.html",
option_template_name="bda/forms/checkbox_table.html",
context_object_name="spectacle",
)
# Formulaires pour revente_tirages
class ReventeTirageAnnulForm(forms.Form):
def __init__(self, participant, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["reventes"] = TemplateLabelField(
queryset=participant.entered.filter(soldTo__isnull=True).select_related(
"attribution__spectacle", "seller__user"
),
widget=forms.CheckboxSelectMultiple,
required=False,
label_template_name="bda/forms/revente_other_label_table.html",
option_template_name="bda/forms/checkbox_table.html",
context_object_name="revente",
)
class ReventeTirageForm(forms.Form):
def __init__(self, participant, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["reventes"] = TemplateLabelField(
queryset=(
SpectacleRevente.objects.filter(
notif_sent=True,
shotgun=False,
tirage_done=False,
attribution__spectacle__tirage=participant.tirage,
)
.exclude(confirmed_entry=participant)
.select_related("attribution__spectacle")
),
widget=forms.CheckboxSelectMultiple,
required=False,
label_template_name="bda/forms/revente_other_label_table.html",
option_template_name="bda/forms/checkbox_table.html",
context_object_name="revente",
)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -12,15 +12,15 @@ def forwards_func(apps, schema_editor):
for revente in SpectacleRevente.objects.all():
is_expired = timezone.now() > revente.date_tirage()
is_direct = revente.attribution.spectacle.date >= revente.date and timezone.now() > revente.date + timedelta(
minutes=15
is_direct = (
revente.attribution.spectacle.date >= revente.date
and timezone.now() > revente.date + timedelta(minutes=15)
)
revente.shotgun = is_expired or is_direct
revente.save()
class Migration(migrations.Migration):
dependencies = [("bda", "0009_revente")]
operations = [

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,30 @@
# Generated by Django 2.2 on 2019-06-03 19:13
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [("bda", "0013_merge_20180524_2123")]
operations = [
migrations.AddField(
model_name="attribution",
name="paid",
field=models.BooleanField(default=False, verbose_name="Payée"),
),
migrations.AddField(
model_name="attribution",
name="paymenttype",
field=models.CharField(
blank=True,
choices=[
("cash", "Cash"),
("cb", "CB"),
("cheque", "Chèque"),
("autre", "Autre"),
],
max_length=6,
verbose_name="Moyen de paiement",
),
),
]

View file

@ -0,0 +1,36 @@
# Generated by Django 2.2 on 2019-06-03 19:30
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
from django.db import migrations
def set_attr_payment(apps, schema_editor):
Attribution = apps.get_model("bda", "Attribution")
for attr in Attribution.objects.all():
attr.paid = attr.participant.paid
attr.paymenttype = attr.participant.paymenttype
attr.save()
def set_participant_payment(apps, schema_editor):
Participant = apps.get_model("bda", "Participant")
for part in Participant.objects.all():
attr_set = part.attribution_set
part.paid = attr_set.exists() and not attr_set.filter(paid=False).exists()
try:
# S'il n'y a qu'un seul type de paiement, on le set
part.paymenttype = (
attr_set.values_list("paymenttype", flat=True).distinct().get()
)
# Sinon, whatever
except (ObjectDoesNotExist, MultipleObjectsReturned):
pass
part.save()
class Migration(migrations.Migration):
dependencies = [("bda", "0014_attribution_paid_field")]
operations = [
migrations.RunPython(set_attr_payment, set_participant_payment, atomic=True)
]

View file

@ -0,0 +1,12 @@
# Generated by Django 2.2 on 2019-06-03 19:30
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [("bda", "0015_move_bda_payment")]
operations = [
migrations.RemoveField(model_name="participant", name="paid"),
migrations.RemoveField(model_name="participant", name="paymenttype"),
]

View file

@ -0,0 +1,17 @@
# Generated by Django 2.2 on 2019-09-18 16:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [("bda", "0016_delete_participant_paid")]
operations = [
migrations.AddField(
model_name="participant",
name="accepte_charte",
field=models.BooleanField(
default=False, verbose_name="A accepté la charte BdA"
),
)
]

View file

@ -0,0 +1,37 @@
# Generated by Django 2.2.12 on 2020-10-21 16:18
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bda", "0017_participant_accepte_charte"),
]
operations = [
migrations.AlterModelOptions(
name="participant",
options={"ordering": ("-tirage", "user__last_name", "user__first_name")},
),
migrations.AddField(
model_name="tirage",
name="archived",
field=models.BooleanField(default=False, verbose_name="Archivé"),
),
migrations.AlterField(
model_name="participant",
name="tirage",
field=models.ForeignKey(
limit_choices_to={"archived": False},
on_delete=django.db.models.deletion.CASCADE,
to="bda.Tirage",
),
),
migrations.AddConstraint(
model_name="participant",
constraint=models.UniqueConstraint(
fields=("tirage", "user"), name="unique_tirage"
),
),
]

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

@ -2,14 +2,14 @@ import calendar
import random
from datetime import timedelta
from custommail.models import CustomMail
from custommail.shortcuts import send_mass_custom_mail
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.sites.models import Site
from django.core import mail
from django.core.mail import EmailMessage, send_mass_mail
from django.db import models
from django.db.models import Count
from django.db.models import Count, Exists
from django.template import loader
from django.utils import formats, timezone
@ -31,6 +31,7 @@ class Tirage(models.Model):
"Tirage à afficher dans le catalogue", default=False
)
enable_do_tirage = models.BooleanField("Le tirage peut être lancé", default=False)
archived = models.BooleanField("Archivé", default=False)
def __str__(self):
return "%s - %s" % (
@ -116,16 +117,19 @@ class Spectacle(models.Model):
bda_generic.nb_attr = 1
members.append(bda_generic)
# On écrit un mail personnalisé à chaque participant
datatuple = [
mails = [
(
"bda-rappel",
{"member": member, "nb_attr": member.nb_attr, "show": self},
str(self),
loader.render_to_string(
"bda/mails/rappel.txt",
context={"member": member, "nb_attr": member.nb_attr, "show": self},
),
settings.MAIL_DATA["rappels"]["FROM"],
[member.email],
)
for member in members
]
send_mass_custom_mail(datatuple)
send_mass_mail(mails)
# On enregistre le fait que l'envoi a bien eu lieu
self.rappel_sent = timezone.now()
self.save()
@ -151,6 +155,41 @@ PAYMENT_TYPES = (
)
class Attribution(models.Model):
participant = models.ForeignKey("Participant", on_delete=models.CASCADE)
spectacle = models.ForeignKey(
Spectacle, on_delete=models.CASCADE, related_name="attribues"
)
given = models.BooleanField("Donnée", default=False)
paid = models.BooleanField("Payée", default=False)
paymenttype = models.CharField(
"Moyen de paiement", max_length=6, choices=PAYMENT_TYPES, blank=True
)
def __str__(self):
return "%s -- %s, %s" % (
self.participant.user,
self.spectacle.title,
self.spectacle.date,
)
class ParticipantPaidQueryset(models.QuerySet):
"""
Un manager qui annote le queryset avec un champ `paid`,
indiquant si un participant a payé toutes ses attributions.
"""
def annotate_paid(self):
# OuterRef permet de se référer à un champ d'un modèle non encore fixé
# Voir:
# https://docs.djangoproject.com/en/2.2/ref/models/expressions/#django.db.models.OuterRef
unpaid = Attribution.objects.filter(
participant=models.OuterRef("pk"), paid=False
)
return self.annotate(paid=~Exists(unpaid))
class Participant(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
choices = models.ManyToManyField(
@ -159,18 +198,25 @@ class Participant(models.Model):
attributions = models.ManyToManyField(
Spectacle, through="Attribution", related_name="attributed_to"
)
paid = models.BooleanField("A payé", default=False)
paymenttype = models.CharField(
"Moyen de paiement", max_length=6, choices=PAYMENT_TYPES, blank=True
tirage = models.ForeignKey(
Tirage, on_delete=models.CASCADE, limit_choices_to={"archived": False}
)
tirage = models.ForeignKey(Tirage, on_delete=models.CASCADE)
accepte_charte = models.BooleanField("A accepté la charte BdA", default=False)
choicesrevente = models.ManyToManyField(
Spectacle, related_name="subscribed", blank=True
)
objects = ParticipantPaidQueryset.as_manager()
def __str__(self):
return "%s - %s" % (self.user, self.tirage.title)
class Meta:
ordering = ("-tirage", "user__last_name", "user__first_name")
constraints = [
models.UniqueConstraint(fields=("tirage", "user"), name="unique_tirage"),
]
DOUBLE_CHOICES = (
("1", "1 place"),
@ -207,26 +253,15 @@ class ChoixSpectacle(models.Model):
class Meta:
ordering = ("priority",)
unique_together = (("participant", "spectacle"),)
constraints = [
models.UniqueConstraint(
fields=["participant", "spectacle"], name="unique_participation"
)
]
verbose_name = "voeu"
verbose_name_plural = "voeux"
class Attribution(models.Model):
participant = models.ForeignKey(Participant, on_delete=models.CASCADE)
spectacle = models.ForeignKey(
Spectacle, on_delete=models.CASCADE, related_name="attribues"
)
given = models.BooleanField("Donnée", default=False)
def __str__(self):
return "%s -- %s, %s" % (
self.participant.user,
self.spectacle.title,
self.spectacle.date,
)
class SpectacleRevente(models.Model):
attribution = models.OneToOneField(
Attribution, on_delete=models.CASCADE, related_name="revente"
@ -329,21 +364,24 @@ class SpectacleRevente(models.Model):
BdA-Revente à tous les intéressés.
"""
inscrits = self.attribution.spectacle.subscribed.select_related("user")
datatuple = [
mails = [
(
"bda-revente",
{
"BdA-Revente : {}".format(self.attribution.spectacle.title),
loader.render_to_string(
"bda/mails/revente-new.txt",
context={
"member": participant.user,
"show": self.attribution.spectacle,
"revente": self,
"site": Site.objects.get_current(),
},
),
settings.MAIL_DATA["revente"]["FROM"],
[participant.user.email],
)
for participant in inscrits
]
send_mass_custom_mail(datatuple)
send_mass_mail(mails)
self.notif_sent = True
self.notif_time = timezone.now()
self.save()
@ -354,20 +392,23 @@ class SpectacleRevente(models.Model):
leur indiquer qu'il est désormais disponible au shotgun.
"""
inscrits = self.attribution.spectacle.subscribed.select_related("user")
datatuple = [
mails = [
(
"bda-shotgun",
{
"BdA-Revente : {}".format(self.attribution.spectacle.title),
loader.render_to_string(
"bda/mails/revente-shotgun.txt",
context={
"member": participant.user,
"show": self.attribution.spectacle,
"site": Site.objects.get_current(),
},
),
settings.MAIL_DATA["revente"]["FROM"],
[participant.user.email],
)
for participant in inscrits
]
send_mass_custom_mail(datatuple)
send_mass_mail(mails)
self.notif_sent = True
self.notif_time = timezone.now()
# Flag inutile, sauf si l'horloge interne merde
@ -399,31 +440,30 @@ class SpectacleRevente(models.Model):
"show": spectacle,
}
c_mails_qs = CustomMail.objects.filter(
shortname__in=[
"bda-revente-winner",
"bda-revente-loser",
"bda-revente-seller",
]
)
c_mails = {cm.shortname: cm for cm in c_mails_qs}
subject = "BdA-Revente : {}".format(spectacle.title)
mails.append(
c_mails["bda-revente-winner"].get_message(
context,
EmailMessage(
subject=subject,
body=loader.render_to_string(
"bda/mails/revente-tirage-winner.txt",
context=context,
),
from_email=settings.MAIL_DATA["revente"]["FROM"],
to=[winner.user.email],
)
)
mails.append(
c_mails["bda-revente-seller"].get_message(
context,
EmailMessage(
subject=subject,
body=loader.render_to_string(
"bda/mails/revente-tirage-seller.txt",
context=context,
),
from_email=settings.MAIL_DATA["revente"]["FROM"],
to=[seller.user.email],
reply_to=[winner.user.email],
)
),
)
# Envoie un mail aux perdants
@ -433,11 +473,15 @@ class SpectacleRevente(models.Model):
new_context["acheteur"] = inscrit.user
mails.append(
c_mails["bda-revente-loser"].get_message(
new_context,
EmailMessage(
subject=subject,
body=loader.render_to_string(
"bda/mails/revente-tirage-loser.txt",
context=new_context,
),
from_email=settings.MAIL_DATA["revente"]["FROM"],
to=[inscrit.user.email],
)
),
)
mail_conn = mail.get_connection()

125
bda/static/bda/css/bda.css Normal file
View file

@ -0,0 +1,125 @@
form#tokenform {
text-align: center;
font-size: 2em;
}
label {
margin-right: 10px;
vertical-align: top;
}
form#tokenform textarea {
font-size: 2em;
width: 350px;
height: 200px;
font-family: 'Droif Serif', serif;
}
/* wft ?
input {
width: 400px;
font-size: 2em;
}*/
ul.losers {
display: inline;
margin: 0;
padding: 0;
}
ul.losers li {
display: inline;
}
span.details {
font-size: 0.7em;
}
td {
border: 0px solid black;
padding: 2px;
}
.attribresult {
margin: 10px 0px;
}
.spectacle-passe {
opacity:0.5;
}
/** JQuery-Confirm box **/
.jconfirm .jconfirm-bg {
background-color: rgb(0,0,0,0.6) !important;
}
.jconfirm .jconfirm-box {
padding:0;
border-radius:0 !important;
font-family:Roboto;
}
.jconfirm .jconfirm-box .content-pane {
border-bottom:1px solid #ddd;
margin: 0px !important;
}
.jconfirm .jconfirm-box .content {
padding: 5px;
}
.jconfirm .jconfirm-box .content-pane {
border-bottom:1px solid #ddd;
margin: 0px !important;
}
.jconfirm .jconfirm-box .content {
padding: 10px;
}
.jconfirm .jconfirm-box .content a,
.jconfirm .jconfirm-box .content a:hover {
color: #D81138;
font-weight: bold;
}
.jconfirm .jconfirm-box .buttons {
margin-top:-6px; /* j'arrive pas à voir pk y'a un espace au dessus sinon... */
padding:0;
height:40px;
}
.jconfirm .jconfirm-box .buttons button {
min-width:40px;
height:100%;
margin:0;
margin:0 !important;
border-radius: 0 !important;
}
.jconfirm .jconfirm-box .buttons button:first-child:focus,
.jconfirm .jconfirm-box .buttons button:first-child:hover {
color:#FFF !important;
background:forestgreen !important;
}
.jconfirm .jconfirm-box .buttons button:nth-child(2):focus,
.jconfirm .jconfirm-box .buttons button:nth-child(2):hover {
color:#FFF !important;
background:#D93A32 !important;
}
.jconfirm .jconfirm-box div.title-c .title {
display: block;
padding:0 15px;
height:40px;
line-height:40px;
font-family:Dosis;
font-size:20px;
font-weight:bold;
color:#FFF;
background-color:rgb(222, 130, 107);
}

View file

@ -1,48 +0,0 @@
form#tokenform {
text-align: center;
font-size: 2em;
}
label {
margin-right: 10px;
vertical-align: top;
}
form#tokenform textarea {
font-size: 2em;
width: 350px;
height: 200px;
font-family: 'Droif Serif', serif;
}
/* wft ?
input {
width: 400px;
font-size: 2em;
}*/
ul.losers {
display: inline;
margin: 0;
padding: 0;
}
ul.losers li {
display: inline;
}
span.details {
font-size: 0.7em;
}
td {
border: 0px solid black;
padding: 2px;
}
.attribresult {
margin: 10px 0px;
}
.spectacle-passe {
opacity:0.5;
}

Binary file not shown.

View file

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

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %}
{% load staticfiles %}
{% load static %}
{% block realcontent %}
<h2>État des inscriptions BdA</h2>
@ -42,9 +42,6 @@
Total&nbsp;: {{ total }} place{{ total|pluralize }} demandée{{ total|pluralize }}
sur {{ proposed }} place{{ proposed|pluralize }} proposée{{ proposed|pluralize }}
</span>
<script type="text/javascript"
src="{% static "js/joequery-Stupid-Table-Plugin/stupidtable.js" %}">
</script>
<script type="text/javascript">
$(function(){
$("table.etat-bda").stupidtable();

View file

@ -0,0 +1 @@
{% include 'bda/forms/spectacle_label_table.html' with spectacle=attribution.spectacle %}

View file

@ -0,0 +1,4 @@
<tr>
<td><input type="{{ widget.type }}" name="{{ widget.name }}" {% if widget.value != None %} value="{{ widget.value|stringformat:'s' }}"{% endif %}{% include "django/forms/widgets/attrs.html" %}></td>
{{ widget.label }}
</tr>

View file

@ -0,0 +1 @@
<td data-sort-value="{{ revente.date_tirage | date:"U" }}">{{ revente.date_tirage }}</td>

View file

@ -0,0 +1,3 @@
{% include 'bda/forms/spectacle_label_table.html' with spectacle=revente.attribution.spectacle %}
{% with user=revente.seller.user %} <td>{{user.first_name}} {{user.last_name}}</td> {% endwith%}
{% include 'bda/forms/date_tirage.html' %}

View file

@ -0,0 +1,2 @@
{% include 'bda/forms/spectacle_label_table.html' with spectacle=revente.attribution.spectacle %}
{% include 'bda/forms/date_tirage.html' %}

View file

@ -0,0 +1,4 @@
{% include 'bda/forms/spectacle_label_table.html' with spectacle=revente.attribution.spectacle %}
{% with user=revente.soldTo.user %}
<td><a href="mailto:{{ user.email }}">{{user.first_name}} {{user.last_name}}</a></td>
{% endwith %}

View file

@ -0,0 +1,4 @@
<td>{{ spectacle.title }}</td>
<td data-sort-value="{{ spectacle.timestamp }}">{{ spectacle.date }}</td>
<td data-sort-value="{{ spectacle.location }}">{{ spectacle.location }}</td>
<td data-sort-value="{{ spectacle.price |stringformat:".3f" }}">{{ spectacle.price |floatformat }}€</td>

View file

@ -1,11 +1,13 @@
{% extends "base_title.html" %}
{% load staticfiles %}
{% load static %}
{% block extra_head %}
<script src="{% static 'js/jquery-ui.min.js' %}" type="text/javascript"></script>
<script src="{% static "js/jquery.ui.touch-punch.min.js" %}" type="text/javascript"></script>
<link type="text/css" rel="stylesheet" href="{% static "css/jquery-ui.min.css" %}" />
<link type="text/css" rel="stylesheet" href="{% static "css/bda.css" %}" />
<script type="text/javascript" src="{% static 'vendor/jquery/jquery-ui.min.js' %}" ></script>
<script type="text/javascript" src="{% static "vendor/jquery/jquery-confirm.js" %}"></script>
<script type="text/javascript" src="{% static 'gestioncof/vendor/jquery.ui.touch-punch.min.js' %}" ></script>
<link type="text/css" rel="stylesheet" href="{% static 'vendor/jquery/jquery-confirm.css' %}">
<link type="text/css" rel="stylesheet" href="{% static 'vendor/jquery/jquery-ui.min.css' %}" />
<link type="text/css" rel="stylesheet" href="{% static 'bda/css/bda.css' %}" />
{% endblock %}
{% block realcontent %}
@ -52,6 +54,11 @@ var django = {
} else {
deleteInput.attr("checked", true);
}
} else {
// Reset the default values
var selects = $(form).find("select");
$(selects[0]).val("");
$(selects[1]).val("1");
}
// callback
});
@ -113,11 +120,50 @@ var django = {
});
</script>
<input type="hidden" name="dbstate" value="{{ dbstate }}" />
<input type="submit" class="btn btn-primary" value="Enregistrer" />
<input type="submit" class="btn btn-primary" id="bda-inscr" value="Enregistrer" />
</div>
<p class="footnotes">
<sup>1</sup>: cette liste de v&oelig;ux est ordonnée (du plus important au moins important), pour ajuster la priorité vous pouvez déplacer chaque v&oelig;u.<br />
</p>
</div>
</form>
{% if not charte %}
<script>
(function ($) {
var charte_ok = false ;
function link_charte() {
$.confirm({
title: 'Charte du BdA',
columnClass: 'col-md-6 col-md-offset-3',
content: `
<div>
En vous inscrivant à ce tirage du Bureau des Arts, vous vous engagez à \
respecter la charte du BdA:</br> \
<a target="_blank" href='https://bda.ens.fr/lequipe/charte-bda/'>https://bda.ens.fr/lequipe/charte-bda/</a>
</div>`,
backgroundDismiss: true,
opacity: 1,
animation:'top',
closeAnimation:'bottom',
keyboardEnabled: true,
confirmButton: '<span class="glyphicon glyphicon-ok"></span>',
cancelButton: '<span class="glyphicon glyphicon-remove"></span>',
confirm: function() {
charte_ok = true ;
$("#bda_form").submit();
},
});
}
$(document).ready(function($) {
$("#bda_form").submit(function(e) {
if (!charte_ok) {
e.preventDefault();
link_charte();
}
})
})
})(django.jQuery);
</script>
{% endif %}
{% endblock %}

View file

@ -26,13 +26,6 @@
<hr \>
<p>
<em>Note :</em> le template de ce mail peut être modifié à
<a href="{% url 'admin:custommail_custommail_change' custommail.pk %}">cette adresse</a>
</p>
<hr \>
<h3>Forme des mails</h3>
<h4>Une seule place</h4>

View file

@ -0,0 +1,10 @@
Cher-e {{ member.first_name }},
Tu t'es inscrit-e pour le tirage au sort du BdA. Malheureusement, tu n'as
obtenu aucune place.
Nous proposons cependant de nombreuses offres hors-tirage tout au long de
l'année, et nous t'invitons à nous contacter si l'une d'entre elles
t'intéresse !
--
Le Bureau des Arts

View file

@ -0,0 +1,31 @@
Cher-e {{ member.first_name }},
Tu t'es inscrit-e pour le tirage au sort du BdA. Tu as été sélectionné-e
pour les spectacles suivants :
{% for place in places %}
- 1 place pour {{ place }}{% endfor %}
*Paiement*
L'intégralité de ces places de spectacles est à régler dès maintenant et AVANT
vendredi prochain, au bureau du COF pendant les heures de permanences (du lundi au vendredi
entre 12h et 14h, et entre 18h et 20h). Des facilités de paiement sont bien
évidemment possibles : nous pouvons ne pas encaisser le chèque immédiatement,
ou bien découper votre paiement en deux fois. Pour ceux qui ne pourraient pas
venir payer au bureau, merci de nous contacter par mail.
*Mode de retrait des places*
Au moment du paiement, certaines places vous seront remises directement,
d'autres seront à récupérer au cours de l'année, d'autres encore seront
nominatives et à retirer le soir même dans les théâtres correspondants.
Pour chaque spectacle, vous recevrez un mail quelques jours avant la
représentation vous indiquant le mode de retrait.
Nous vous rappelons que l'obtention de places du BdA vous engage à
respecter les règles de fonctionnement :
https://bda.ens.fr/lequipe/charte-bda/
Un système de revente des places via les mails BdA-revente est disponible
directement sur votre compte GestioCOF.
En vous souhaitant de très beaux spectacles tout au long de l'année,
--
Le Bureau des Arts

View file

@ -0,0 +1,23 @@
Bonjour {{ member.first_name }},
Nous te rappellons que tu as eu la chance d'obtenir {{ nb_attr|pluralize:"une place,deux places" }}
pour {{ show.title }}, le {{ show.date }} au {{ show.location }}. N'oublie pas de t'y rendre !
{% if nb_attr == 2 %}
Tu as obtenu deux places pour ce spectacle. Nous te rappelons que
ces places sont strictement réservées aux personnes de moins de 28 ans.
{% endif %}
{% if show.listing %}Pour ce spectacle, tu as reçu {{ nb_attr|pluralize:"une place,des places" }} sur
listing. Il te faudra donc te rendre 15 minutes en avance sur les lieux de la représentation
pour {{ nb_attr|pluralize:"la,les" }} retirer.
{% else %}Pour assister à ce spectacle, tu dois présenter les billets qui ont
été distribués au burô.
{% endif %}
Si tu ne peux plus assister à cette représentation, tu peux
revendre ta place via BdA-revente, accessible directement sur
GestioCOF (lien "revendre une place du premier tirage" sur la page
d'accueil https://www.cof.ens.fr/gestion/).
En te souhaitant un excellent spectacle,
--
Le Bureau des Arts

View file

@ -0,0 +1,12 @@
Bonjour {{ member.first_name }}
Une place pour le spectacle {{ show.title }} ({{ show.date }})
a été postée sur BdA-Revente.
Si ce spectacle t'intéresse toujours, merci de nous le signaler en cliquant
sur ce lien : https://{{ site }}{% url "bda-revente-confirm" revente.id %}.
Dans le cas où plusieurs personnes seraient intéressées, nous procèderons à
un tirage au sort le {{ revente.date_tirage|date:"DATE_FORMAT" }}.
Chaleureusement,
Le BdA

View file

@ -0,0 +1,13 @@
Bonjour {{ vendeur.first_name }},
Tu tes bien inscrit·e pour revendre une place pour {{ show.title }}.
{% with revente.date_tirage as time %}
Le tirage au sort entre tout·e·s les racheteuse·eur·s potentiel·le·s aura lieu
le {{ time|date:"DATE_FORMAT" }} à {{ time|time:"TIME_FORMAT" }} (dans {{time|timeuntil }}).
Si personne ne sest inscrit pour racheter la place, celle-ci apparaîtra parmi
les « Places disponibles immédiatement à la revente » sur GestioCOF.
{% endwith %}
Bonne revente !
Le Bureau des Arts

View file

@ -0,0 +1,6 @@
Bonjour {{ vendeur.first_name }} !
Je souhaiterais racheter ta place pour {{ show.title }} le {{ show.date }} ({{ show.location }}) à {{ show.price|floatformat:2 }}€.
Contacte-moi si tu es toujours intéressé·e !
{{ acheteur.get_full_name }} ({{ acheteur.email }})

View file

@ -0,0 +1,11 @@
Bonjour {{ member.first_name }}
Une place pour le spectacle {{ show.title }} ({{ show.date }})
a été postée sur BdA-Revente.
Puisque ce spectacle a lieu dans moins de 24h, il n'y a pas de tirage au sort pour
cette place : elle est disponible immédiatement à l'adresse
https://{{ site }}{% url "bda-revente-buy" show.id %}, à la disposition de tous.
Chaleureusement,
Le BdA

View file

@ -0,0 +1,9 @@
Bonjour {{ acheteur.first_name }},
Tu t'étais inscrit·e pour la revente de la place de {{ vendeur.get_full_name }}
pour {{ show.title }}.
Malheureusement, une autre personne a été tirée au sort pour racheter la place.
Tu pourras certainement retenter ta chance pour une autre revente !
À très bientôt,
Le Bureau des Arts

View file

@ -0,0 +1,7 @@
Bonjour {{ vendeur.first_name }},
La personne tirée au sort pour racheter ta place pour {{ show.title }} est {{ acheteur.get_full_name }}.
Tu peux le/la contacter à l'adresse {{ acheteur.email }}, ou en répondant à ce mail.
Chaleureusement,
Le BdA

View file

@ -0,0 +1,7 @@
Bonjour {{ acheteur.first_name }},
Tu as été tiré·e au sort pour racheter une place pour {{ show.title }} le {{ show.date }} ({{ show.location }}) à {{ show.price|floatformat:2 }}€.
Tu peux contacter le/la vendeur·se à l'adresse {{ vendeur.email }}.
Chaleureusement,
Le BdA

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %}
{% load staticfiles %}
{% load static %}
{% block realcontent %}
<h2>{{ spectacle }}</h2>
@ -16,7 +16,7 @@
<tbody>
{% for participant in participants %}
<tr>
<td data-sort-value="{{ participan.name}}">{{participant.name}}</td>
<td data-sort-value="{{ participant.name}}">{{participant.name}}</td>
<td data-sort-value="{{participant.nb_places}}">{{participant.nb_places}} place{{participant.nb_places|pluralize}}</td>
<td data-sort-value="{{participant.email}}">{{participant.email}}</td>
<td data-sort-value="{{ participant.paid}}" class={%if participant.paid %}"greenratio"{%else%}"redratio"{%endif%}>
@ -38,7 +38,7 @@
<h3><a href="{% url "admin:bda_attribution_add" %}?spectacle={{spectacle.id}}"><span class="glyphicon glyphicon-plus-sign"></span> Ajouter une attribution</a></h3>
<div>
<div>
<button class="btn btn-default" type="button" onclick="toggle('export-mails')">Afficher/Cacher mails participants</button>
<button class="btn btn-default" type="button" onclick="toggle('export-mails')">Afficher/Cacher mails participant⋅e⋅s</button>
<pre id="export-mails" style="display:none">{% spaceless %}
{% for participant in participants %}{{ participant.email }}, {% endfor %}
{% endspaceless %}</pre>
@ -56,9 +56,7 @@
<a href="{% url 'bda-rappels' spectacle.id %}">Page d'envoi manuel des mails de rappel</a>
</div>
<script type="text/javascript"
src="{% static "js/joequery-Stupid-Table-Plugin/stupidtable.js" %}"></script>
<script>
<script type="text/javascript">
function toggle(id) {
var pre = document.getElementById(id) ;
pre.style.display = pre.style.display == "none" ? "block" : "none" ;

View file

@ -10,6 +10,7 @@
<td>{{place.spectacle.location}}</td>
<td>{{place.spectacle.date}}</td>
<td>{% if place.double %}deux places{%else%}une place{% endif %}</td>
<td>{% if place.spectacle.listing %}sur listing{% else %}place physique{% endif %}</td>
</tr>
{% endfor %}
</table>

View file

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

View file

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

View file

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

View file

@ -1,12 +1,11 @@
{% extends "base_title.html" %}
{% load bootstrap %}
{% load static %}
{% block realcontent %}
<h2>Gestion des places que je revends</h2>
{% with resell_attributions=resellform.attributions annul_reventes=annulform.reventes sold_reventes=soldform.reventes %}
{% if resell_attributions %}
{% if resell_exists %}
<br />
<h3>Places non revendues</h3>
@ -17,10 +16,21 @@
ensuite 1h pour changer d'avis avant que la revente soit confirmée et
que les notifications soient envoyées aux intéressé·e·s.
</div>
<div class="bootstrap-form-reduce">
{% csrf_token %}
{{ resellform|bootstrap }}
</div>
<table class="table table-striped stupidtable">
<thead>
<tr>
<th></th>
<th data-sort="string">Titre</th>
<th data-sort="string">Lieu</th>
<th data-sort="int">Date</th>
<th data-sort="int">Prix</th>
</tr>
</thead>
<tbody>
{% for checkbox in resellform.attributions %}{{ checkbox }}{% endfor %}
</tbody>
</table>
<div class="form-actions">
<input type="submit" class="btn btn-primary" name="resell" value="Revendre les places sélectionnées">
</div>
@ -29,7 +39,7 @@
<hr />
{% endif %}
{% if annul_reventes %}
{% if annul_exists %}
<h3>Places en cours de revente</h3>
<form action="" method="post">
<div class="bg-info text-info center-block">
@ -37,22 +47,28 @@
Vous pouvez annuler les reventes qui n'ont pas encore trouvé preneur·se.
</div>
{% csrf_token %}
<div class='form-group'>
<div class='multiple-checkbox'>
<ul>
{% for revente in annul_reventes %}
<li>{{ revente.tag }} {{ revente.choice_label }}</li>
{% endfor %}
</ul>
</div>
</div>
<table class="table table-striped stupidtable">
<thead>
<tr>
<th></th>
<th data-sort="string">Titre</th>
<th data-sort="int">Date</th>
<th data-sort="string">Lieu</th>
<th data-sort="int">Prix</th>
<th data-sort="int">Tirage le</th>
</tr>
</thead>
<tbody>
{% for checkbox in annulform.reventes %}{{ checkbox }}{% endfor %}
</tbody>
</table>
<input type="submit" class="btn btn-primary" name="annul" value="Annuler les reventes sélectionnées">
</form>
<hr />
{% endif %}
{% if sold_reventes %}
{% if sold_exists %}
<h3>Places revendues</h3>
<form action="" method="post">
<div class="bg-info text-info center-block">
@ -64,17 +80,42 @@
vous ne parvenez pas à entrer en contact avec la personne tirée au
sort.
</div>
<div class="bootstrap-form-reduce">
{% csrf_token %}
{{ soldform|bootstrap }}
</div>
<table class="table table-striped stupidtable">
<thead>
<tr>
<th></th>
<th data-sort="string">Titre</th>
<th data-sort="int">Date</th>
<th data-sort="string">Lieu</th>
<th data-sort="int">Prix</th>
<th>Vendue à</th>
</tr>
</thead>
<tbody>
{% for checkbox in soldform.reventes %}{{ checkbox }}{% endfor %}
</tbody>
</table>
<button type="submit" class="btn btn-primary" name="transfer">Transférer</button>
<button type="submit" class="btn btn-primary" name="reinit">Réinitialiser</button>
</form>
{% endif %}
{% if not resell_attributions and not annul_reventes and not sold_reventes %}
{% if not resell_exists and not annul_exists and not sold_exists %}
<p>Plus de reventes possibles !</p>
{% endif %}
{% endwith %}
<script language="JavaScript">
$(function(){
$("table.stupidtable").stupidtable();
});
$("tr").click(function() {
$(this).find("input[type=checkbox]").click()
});
$("input[type=checkbox]").click(function(e) {
e.stopPropagation();
});
</script>
{% endblock %}

View file

@ -1,6 +0,0 @@
{% extends "base_title.html" %}
{% block realcontent %}
<h2><strong>Nope</strong></h2>
<p>Avant de revendre des places, il faut aller les payer !</p>
{% endblock %}

View file

@ -2,11 +2,26 @@
{% block realcontent %}
<h2>Places disponibles immédiatement</h2>
{% if shotgun %}
<ul class="list-unstyled">
{% for spectacle in shotgun %}
<li><a href="{% url "bda-revente-buy" spectacle.id %}">{{spectacle}}</a></li>
{% if spectacles %}
<table class="table table-striped stupidtable" id="bda-shotgun">
<thead>
<tr>
<th data-sort="string">Titre</th>
<th data-sort="int">Date</th>
<th data-sort="string">Lieu</th>
<th data-sort="int">Prix</th>
<th></th>
</tr>
</thead>
<tbody>
{% for spectacle in spectacles %}
<tr>
{% include "bda/forms/spectacle_label_table.html" with spectacle=spectacle %}
<td class="button"><a role="button" class="btn btn-primary" href="{% url 'bda-revente-buy' spectacle.id %}">Racheter</a>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p> Pas de places disponibles immédiatement, désolé !</p>
{% endif %}

View file

@ -1,12 +1,12 @@
{% extends "base_title.html" %}
{% load bootstrap %}
{% load static %}
{% block realcontent %}
<h2>Inscriptions pour BdA-Revente</h2>
<form action="" class="form-horizontal" method="post">
<div class="bg-info text-info center-block">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
Cochez les spectacles pour lesquels vous souhaitez recevoir un
Cochez les spectacles pour lesquels vous souhaitez recevoir une
notification quand une place est disponible en revente. <br />
Lorsque vous validez vos choix, si un tirage au sort est en cours pour
un des spectacles que vous avez sélectionné, vous serez automatiquement
@ -21,14 +21,21 @@
<button type="button"
class="btn btn-primary"
onClick="select(false)">Tout désélectionner</button>
<table class="table table-striped stupidtable">
<thead>
<tr>
<th></th>
<th data-sort="string">Titre</th>
<th data-sort="int">Date</th>
<th data-sort="string">Lieu</th>
<th data-sort="int">Prix</th>
</tr>
</thead>
<tbody>
{% for checkbox in form.spectacles %}{{ checkbox }}{% endfor %}
</tbody>
</table>
<div class="multiple-checkbox">
<ul>
{% for checkbox in form.spectacles %}
<li>{{ checkbox }}</li>
{% endfor %}
</ul>
</div>
</div>
<input type="submit"
class="btn btn-primary"
@ -36,11 +43,22 @@
</form>
<script language="JavaScript">
function select(check) {
function select(check) {
checkboxes = document.getElementsByName("spectacles");
for(var i=0, n=checkboxes.length; i < n; i++) {
checkboxes[i].checked = check;
}
}
}
$(function(){
$("table.stupidtable").stupidtable();
});
$("tr").click(function() {
$(this).find("input[type=checkbox]").click()
});
$("input[type=checkbox]").click(function(e) {
e.stopPropagation();
});
</script>
{% endblock %}

View file

@ -1,45 +1,70 @@
{% extends "base_title.html" %}
{% load bootstrap %}
{% load static %}
{% block realcontent %}
<h2>Tirages au sort de reventes</h2>
{% if annulform.reventes %}
{% if annul_exists %}
<h3>Les reventes auxquelles vous êtes inscrit·e</h3>
<form class="form-horizontal" action="" method="post">
<div class="bg-info text-info center-block">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
Vous pouvez vous désinscrire des reventes suivantes tant que le tirage n'a
pas eu lieu.
Voici la liste des reventes auxquelles vous êtes inscrit·e ; si vous ne souhaitez plus participer au tirage au sort vous pouvez vous en désister.
</div>
<div class="bootstrap-form-reduce">
{% csrf_token %}
{{ annulform|bootstrap }}
</div>
<table class="table table-striped stupidtable">
<thead>
<tr>
<th></th>
<th data-sort="string">Titre</th>
<th data-sort="int">Date</th>
<th data-sort="string">Lieu</th>
<th data-sort="int">Prix</th>
<th>Vendue par</th>
<th data-sort="int">Tirage le</th>
</tr>
</thead>
<tbody>
{% for checkbox in annulform.reventes %}{{ checkbox }}{% endfor %}
</tbody>
</table>
<div class="form-actions">
<input type="submit"
class="btn btn-primary"
name="annul"
value="Se désinscrire des tirages sélectionnés">
value="Se désister des tirages sélectionnés">
</div>
</form>
<hr />
{% endif %}
{% if subform.reventes %}
<hr />
{% if sub_exists %}
<h3>Tirages en cours</h3>
<form class="form-horizontal" action="" method="post">
<div class="bg-info text-info center-block">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
Vous pouvez vous inscrire aux tirage en cours suivants.
Vous pouvez vous inscrire aux tirages en cours suivants.
</div>
<div class="bootstrap-form-reduce">
{% csrf_token %}
{{ subform|bootstrap }}
</div>
<table class="table table-striped stupidtable">
<thead>
<tr>
<th></th>
<th data-sort="string">Titre</th>
<th data-sort="int">Date</th>
<th data-sort="string">Lieu</th>
<th data-sort="int">Prix</th>
<th>Vendue par</th>
<th data-sort="int">Tirage le</th>
</tr>
</thead>
<tbody>
{% for checkbox in subform.reventes %}{{ checkbox }}{% endfor %}
</tbody>
</table>
<div class="form-actions">
<input type="submit"
class="btn btn-primary"
@ -49,4 +74,26 @@
</form>
{% endif %}
{% if not annul_exists and not sub_exists %}
<div class="bg-info text-info center-block">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
Aucune revente n'est active pour le moment !
</div>
{% endif %}
<script language="JavaScript">
$(function(){
$("table.stupidtable").stupidtable();
});
$("tr").click(function() {
$(this).find("input[type=checkbox]").click()
});
$("input[type=checkbox]").click(function(e) {
e.stopPropagation();
});
</script>
{% endblock %}

View file

@ -1,113 +0,0 @@
{% load staticfiles %}
<!doctype html>
<html>
<head>
<base target="_parent"/>
<style>
@font-face {
font-family: josefinsans;
src: url({% static "fonts/josefinsans.ttf" %});
}
*::-moz-selection {
background: #B0B0B0;
}
*::selection {
background: #B0B0B0;
}
.descTable{
width: 100%;
margin: 0 auto 1em;
border-bottom: 2px solid;
border-collapse: collapse;
border-spacing: 0;
font-size: 14px;
line-height: 2;
max-width: 100%;
background-color: transparent;
font-family: 'josefinsans', 'Arial';
font-weight: 700;
color: #5a5a5a;
}
img{
max-width: 100%;
}
</style>
<meta charset="utf8" />
</head>
<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
<body>
{% for show in shows %}
<table class="descTable">
<thead>
<tr>
<th colspan="2"><p style="text-align:center;font-size:22px;">{{ show.title }}</p></th>
</tr>
</thead>
<tbody>
<tr>
<td><p style="text-align: left;">{{ show.location }}</p></td><td class="column-2"><p style="text-align: right;">{{ show.category }}</p></td>
</tr>
<tr>
<td><p style="text-align: left;">{{ show.date|date:"l j F Y - H\hi" }}</p></td><td class="column-2"><p style="text-align: right;">{{ show.slots }} place{{ show.slots|pluralize}} {% if show.slots_description != "" %}({{ show.slots_description }}){% endif %} - {{ show.price }} euro{{ show.price|pluralize}}</p></td>
</tr>
{% if show.vips %}
<tr>
<td colspan="2"><p style="text-align: justify;">{{ show.vips }}</p></td>
</tr>
{% endif %}
<tr>
<td colspan="2">
<p style="text-align: justify;">{{ show.description }}</p>
{% for quote in show.quote_set.all %}
<p style="text-align:center; font-style: italic;">«{{ quote.text }}»{% if quote.author %} - {{ quote.author }}{% endif %}</p>
{% endfor %}
</td>
</tr>
{% if show.image %}
<tr>
<td colspan="2"><p style="text-align:center;"><a href="{{ show.ext_link }}"><img class="imgDesc" style="display: inline;" src="{{ MEDIA_URL }}{{ show.image }}" alt="{{ show.title }}"></a></p></td>
</tr>
{% endif %}
</tbody>
</table>
{% endfor %}
<script>
// Correction de la taille des images
/*$(document).ready(function() {
$(".descTable").each(function() {
$(this).width($("body").width());
});
$(".imgDesc").on("load", function() {
// Dimensions
origHeight = 500; // Hauteur souhaitée
w = $(this).width();
h = $(this).height();
r = w/h; // Ratio de l'image
maxWidth = $("body").width();
if (r * origHeight > maxWidth)
{
$(this).width(maxWidth);
$(this).height(maxWidth/r);
}
else
{
$(this).width(r * origHeight);
$(this).height(origHeight);
}
});
});*/
</script>
</body>
</html>

View file

@ -1,8 +1,8 @@
{% extends "base_title.html" %}
{% load staticfiles %}
{% load static %}
{% block extra_head %}
<link type="text/css" rel="stylesheet" href="{% static "css/bda.css" %}" />
<link type="text/css" rel="stylesheet" href="{% static "bda/css/bda.css" %}" />
{% endblock %}
{% block realcontent %}
@ -32,9 +32,7 @@
{% endfor %}
</tbody>
</table>
<script type="text/javascript"
src="{% static "js/joequery-Stupid-Table-Plugin/stupidtable.js" %}">
</script>
<script type="text/javascript">
$(function(){
$("table.etat-bda").stupidtable();
@ -51,6 +49,5 @@
<h3> Exports </h3>
<ul>
<li><a href="{% url 'bda-unpaid' tirage_id %}">Mailing list impayés</a>
<li><a href="{% url 'bda-descriptions' tirage_id %}">Lien vers les descriptions des spectacles, à utiliser dans une page wordpress</a>
</ul>
{% endblock %}

65
bda/tests/mixins.py Normal file
View file

@ -0,0 +1,65 @@
from django.utils import timezone
from shared.tests.mixins import ViewTestCaseMixin
from ..models import CategorieSpectacle, Salle, Spectacle, Tirage
from .utils import create_user
class BdAViewTestCaseMixin(ViewTestCaseMixin):
def get_users_base(self):
return {
"bda_other": create_user(username="bda_other"),
"bda_member": create_user(username="bda_member", is_cof=True),
"bda_staff": create_user(username="bda_staff", is_cof=True, is_buro=True),
}
class BdATestHelpers:
bda_testdata = False
def setUp(self):
super().setUp()
if self.bda_testdata:
self.load_bda_testdata()
def load_bda_testdata(self):
self.tirage = Tirage.objects.create(
title="Test tirage",
appear_catalogue=True,
ouverture=timezone.now(),
fermeture=timezone.now(),
)
self.category = CategorieSpectacle.objects.create(name="Category")
self.location = Salle.objects.create(name="here")
self.show1 = Spectacle.objects.create(
title="foo",
date=timezone.now(),
location=self.location,
price=0,
slots=42,
tirage=self.tirage,
listing=False,
category=self.category,
)
self.show2 = Spectacle.objects.create(
title="bar",
date=timezone.now(),
location=self.location,
price=1,
slots=142,
tirage=self.tirage,
listing=False,
category=self.category,
)
self.show3 = Spectacle.objects.create(
title="baz",
date=timezone.now(),
location=self.location,
price=2,
slots=242,
tirage=self.tirage,
listing=False,
category=self.category,
)

View file

@ -19,8 +19,6 @@ User = get_user_model()
class SpectacleReventeTests(TestCase):
fixtures = ["gestioncof/management/data/custommail.json"]
def setUp(self):
now = timezone.now()
@ -69,7 +67,7 @@ class SpectacleReventeTests(TestCase):
revente = self.rev
wanted_by = [self.p1, self.p2, self.p3]
revente.confirmed_entry = wanted_by
revente.confirmed_entry.set(wanted_by)
with mock.patch("bda.models.random.choice") as mc:
# Set winner to self.p1.

View file

@ -1,225 +1,306 @@
import json
import os
from datetime import timedelta
from unittest import mock
from urllib.parse import urlencode
from django.conf import settings
from django.contrib.auth.models import User
from django.core.management import call_command
from django.contrib.auth import get_user_model
from django.test import Client, TestCase
from django.utils import timezone
from django.urls import reverse
from django.utils import formats, timezone
from ..models import CategorieSpectacle, Salle, Spectacle, Tirage
from ..models import Participant, Tirage
from .mixins import BdATestHelpers, BdAViewTestCaseMixin
User = get_user_model()
def create_user(username, is_cof=False, is_buro=False):
user = User.objects.create_user(username=username, password=username)
user.profile.is_cof = is_cof
user.profile.is_buro = is_buro
user.profile.save()
return user
class InscriptionViewTestCase(BdATestHelpers, BdAViewTestCaseMixin, TestCase):
url_name = "bda-tirage-inscription"
http_methods = ["GET", "POST"]
def user_is_cof(user):
return (user is not None) and user.profile.is_cof
auth_user = "bda_member"
auth_forbidden = [None, "bda_other"]
bda_testdata = True
def user_is_staff(user):
return (user is not None) and user.profile.is_buro
@property
def url_kwargs(self):
return {"tirage_id": self.tirage.id}
@property
def url_expected(self):
return "/gestion/bda/inscription/{}".format(self.tirage.id)
class BdATestHelpers:
def setUp(self):
# Some user with different access privileges
staff = create_user(username="bda_staff", is_cof=True, is_buro=True)
staff_c = Client()
staff_c.force_login(staff)
def test_get_opened(self):
self.tirage.ouverture = timezone.now() - timedelta(days=1)
self.tirage.fermeture = timezone.now() + timedelta(days=1)
self.tirage.save()
member = create_user(username="bda_member", is_cof=True)
member_c = Client()
member_c.force_login(member)
resp = self.client.get(self.url)
other = create_user(username="bda_other")
other_c = Client()
other_c.force_login(other)
self.assertEqual(resp.status_code, 200)
self.assertFalse(resp.context["messages"])
self.client_matrix = [
(staff, staff_c),
(member, member_c),
(other, other_c),
(None, Client()),
]
def test_get_closed_future(self):
self.tirage.ouverture = timezone.now() + timedelta(days=1)
self.tirage.fermeture = timezone.now() + timedelta(days=2)
self.tirage.save()
def require_custommails(self):
data_file = os.path.join(
settings.BASE_DIR, "gestioncof", "management", "data", "custommail.json"
)
call_command("syncmails", data_file, verbosity=0)
resp = self.client.get(self.url)
def check_restricted_access(
self, url, validate_user=user_is_cof, redirect_url=None
):
def craft_redirect_url(user):
if redirect_url:
return redirect_url
elif user is None:
# client is not logged in
login_url = "/login"
if url:
login_url += "?{}".format(urlencode({"next": url}, safe="/"))
return login_url
else:
return "/"
for (user, client) in self.client_matrix:
resp = client.get(url, follow=True)
if validate_user(user):
self.assertEqual(200, resp.status_code)
else:
self.assertRedirects(resp, craft_redirect_url(user))
class TestBdAViews(BdATestHelpers, TestCase):
def setUp(self):
# Signals handlers on login/logout send messages.
# Due to the way the Django' test Client performs login, this raise an
# error. As workaround, we mock the Django' messages module.
patcher_messages = mock.patch("gestioncof.signals.messages")
patcher_messages.start()
self.addCleanup(patcher_messages.stop)
# Set up the helpers
super().setUp()
# Some BdA stuff
self.tirage = Tirage.objects.create(
title="Test tirage",
appear_catalogue=True,
ouverture=timezone.now(),
fermeture=timezone.now(),
)
self.category = CategorieSpectacle.objects.create(name="Category")
self.location = Salle.objects.create(name="here")
Spectacle.objects.bulk_create(
[
Spectacle(
title="foo",
date=timezone.now(),
location=self.location,
price=0,
slots=42,
tirage=self.tirage,
listing=False,
category=self.category,
self.assertEqual(resp.status_code, 200)
self.assertIn(
"Le tirage n'est pas encore ouvert : ouverture le {}".format(
formats.localize(timezone.template_localtime(self.tirage.ouverture))
),
Spectacle(
title="bar",
date=timezone.now(),
location=self.location,
price=1,
slots=142,
tirage=self.tirage,
listing=False,
category=self.category,
),
Spectacle(
title="baz",
date=timezone.now(),
location=self.location,
price=2,
slots=242,
tirage=self.tirage,
listing=False,
category=self.category,
),
]
[str(msg) for msg in resp.context["messages"]],
)
def test_bda_inscriptions(self):
# TODO: test the form
url = "/bda/inscription/{}".format(self.tirage.id)
self.check_restricted_access(url)
def test_get_closed_past(self):
self.tirage.ouverture = timezone.now() - timedelta(days=2)
self.tirage.fermeture = timezone.now() - timedelta(days=1)
self.tirage.save()
def test_bda_places(self):
url = "/bda/places/{}".format(self.tirage.id)
self.check_restricted_access(url)
resp = self.client.get(self.url)
def test_etat_places(self):
url = "/bda/etat-places/{}".format(self.tirage.id)
self.check_restricted_access(url)
self.assertEqual(resp.status_code, 200)
self.assertIn(
" C'est fini : tirage au sort dans la journée !",
[str(msg) for msg in resp.context["messages"]],
)
def test_perform_tirage(self):
# Only staff member can perform a tirage
url = "/bda/tirage/{}".format(self.tirage.id)
self.check_restricted_access(url, validate_user=user_is_staff)
def get_base_post_data(self):
return {
"choixspectacle_set-TOTAL_FORMS": "3",
"choixspectacle_set-INITIAL_FORMS": "0",
"choixspectacle_set-MIN_NUM_FORMS": "0",
"choixspectacle_set-MAX_NUM_FORMS": "1000",
}
_, staff_c = self.client_matrix[0]
base_post_data = property(get_base_post_data)
def test_post(self):
self.tirage.ouverture = timezone.now() - timedelta(days=1)
self.tirage.fermeture = timezone.now() + timedelta(days=1)
self.tirage.save()
data = dict(
self.base_post_data,
**{
"choixspectacle_set-TOTAL_FORMS": "2",
"choixspectacle_set-0-id": "",
"choixspectacle_set-0-participant": "",
"choixspectacle_set-0-spectacle": str(self.show1.pk),
"choixspectacle_set-0-double_choice": "1",
"choixspectacle_set-0-priority": "2",
"choixspectacle_set-1-id": "",
"choixspectacle_set-1-participant": "",
"choixspectacle_set-1-spectacle": str(self.show2.pk),
"choixspectacle_set-1-double_choice": "autoquit",
"choixspectacle_set-1-priority": "1",
}
)
resp = self.client.post(self.url, data)
self.assertEqual(resp.status_code, 200)
self.assertIn(
"Votre inscription a été mise à jour avec succès !",
[str(msg) for msg in resp.context["messages"]],
)
participant = Participant.objects.get(
user=self.users["bda_member"], tirage=self.tirage
)
self.assertSetEqual(
set(
participant.choixspectacle_set.values_list(
"priority", "spectacle_id", "double_choice"
)
),
{(1, self.show2.pk, "autoquit"), (2, self.show1.pk, "1")},
)
def test_post_state_changed(self):
self.tirage.ouverture = timezone.now() - timedelta(days=1)
self.tirage.fermeture = timezone.now() + timedelta(days=1)
self.tirage.save()
data = {"dbstate": "different"}
resp = self.client.post(self.url, data)
self.assertEqual(resp.status_code, 200)
self.assertIn(
"Impossible d'enregistrer vos modifications : vous avez apporté d'autres "
"modifications entre temps.",
[str(msg) for msg in resp.context["messages"]],
)
class PlacesViewTestCase(BdATestHelpers, BdAViewTestCaseMixin, TestCase):
url_name = "bda-places-attribuees"
auth_user = "bda_member"
auth_forbidden = [None, "bda_other"]
bda_testdata = True
@property
def url_kwargs(self):
return {"tirage_id": self.tirage.id}
@property
def url_expected(self):
return "/gestion/bda/places/{}".format(self.tirage.id)
class EtatPlacesViewTestCase(BdATestHelpers, BdAViewTestCaseMixin, TestCase):
url_name = "bda-etat-places"
auth_user = "bda_member"
auth_forbidden = [None, "bda_other"]
bda_testdata = True
@property
def url_kwargs(self):
return {"tirage_id": self.tirage.id}
@property
def url_expected(self):
return "/gestion/bda/etat-places/{}".format(self.tirage.id)
class TirageViewTestCase(BdATestHelpers, BdAViewTestCaseMixin, TestCase):
url_name = "bda-tirage"
http_methods = ["GET", "POST"]
auth_user = "bda_staff"
auth_forbidden = [None, "bda_other", "bda_member"]
bda_testdata = True
@property
def url_kwargs(self):
return {"tirage_id": self.tirage.id}
@property
def url_expected(self):
return "/gestion/bda/tirage/{}".format(self.tirage.id)
def test_perform_tirage_disabled(self):
# Cannot be performed if disabled
self.tirage.enable_do_tirage = False
self.tirage.save()
resp = staff_c.get(url)
resp = self.client.get(self.url)
self.assertTemplateUsed(resp, "tirage-failed.html")
def test_perform_tirage_opened_registrations(self):
# Cannot be performed if registrations are still open
self.tirage.enable_do_tirage = True
self.tirage.fermeture = timezone.now() + timedelta(seconds=3600)
self.tirage.save()
resp = staff_c.get(url)
resp = self.client.get(self.url)
self.assertTemplateUsed(resp, "tirage-failed.html")
def test_perform_tirage(self):
# Otherwise, perform the tirage
self.tirage.enable_do_tirage = True
self.tirage.fermeture = timezone.now()
self.tirage.save()
resp = staff_c.get(url)
resp = self.client.get(self.url)
self.assertTemplateNotUsed(resp, "tirage-failed.html")
def test_spectacles_list(self):
url = "/bda/spectacles/{}".format(self.tirage.id)
self.check_restricted_access(url, validate_user=user_is_staff)
def test_spectacle_detail(self):
show = self.tirage.spectacle_set.first()
url = "/bda/spectacles/{}/{}".format(self.tirage.id, show.id)
self.check_restricted_access(url, validate_user=user_is_staff)
class SpectacleListViewTestCase(BdATestHelpers, BdAViewTestCaseMixin, TestCase):
url_name = "bda-liste-spectacles"
def test_tirage_unpaid(self):
url = "/bda/spectacles/unpaid/{}".format(self.tirage.id)
self.check_restricted_access(url, validate_user=user_is_staff)
auth_user = "bda_staff"
auth_forbidden = [None, "bda_other", "bda_member"]
def test_send_reminders(self):
self.require_custommails()
# Just get the page
show = self.tirage.spectacle_set.first()
url = "/bda/mails-rappel/{}".format(show.id)
self.check_restricted_access(url, validate_user=user_is_staff)
# Actually send the reminder emails
_, staff_c = self.client_matrix[0]
resp = staff_c.post(url)
bda_testdata = True
@property
def url_kwargs(self):
return {"tirage_id": self.tirage.id}
@property
def url_expected(self):
return "/gestion/bda/spectacles/{}".format(self.tirage.id)
class SpectacleViewTestCase(BdATestHelpers, BdAViewTestCaseMixin, TestCase):
url_name = "bda-spectacle"
auth_user = "bda_staff"
auth_forbidden = [None, "bda_other", "bda_member"]
bda_testdata = True
@property
def url_kwargs(self):
return {"tirage_id": self.tirage.id, "spectacle_id": self.show1.id}
@property
def url_expected(self):
return "/gestion/bda/spectacles/{}/{}".format(self.tirage.id, self.show1.id)
class UnpaidViewTestCase(BdATestHelpers, BdAViewTestCaseMixin, TestCase):
url_name = "bda-unpaid"
auth_user = "bda_staff"
auth_forbidden = [None, "bda_other", "bda_member"]
bda_testdata = True
@property
def url_kwargs(self):
return {"tirage_id": self.tirage.id}
@property
def url_expected(self):
return "/gestion/bda/spectacles/unpaid/{}".format(self.tirage.id)
class SendRemindersViewTestCase(BdATestHelpers, BdAViewTestCaseMixin, TestCase):
url_name = "bda-rappels"
auth_user = "bda_staff"
auth_forbidden = [None, "bda_other", "bda_member"]
bda_testdata = True
@property
def url_kwargs(self):
return {"spectacle_id": self.show1.id}
@property
def url_expected(self):
return "/gestion/bda/mails-rappel/{}".format(self.show1.id)
def test_post(self):
resp = self.client.post(self.url)
self.assertEqual(200, resp.status_code)
# TODO: check that emails are sent
def test_catalogue_api(self):
url_list = "/bda/catalogue/list"
url_details = "/bda/catalogue/details?id={}".format(self.tirage.id)
url_descriptions = "/bda/catalogue/descriptions?id={}".format(self.tirage.id)
# Anyone can get
def anyone_can_get(url):
self.check_restricted_access(url, validate_user=lambda user: True)
class CatalogueViewTestCase(BdATestHelpers, BdAViewTestCaseMixin, TestCase):
auth_user = None
auth_forbidden = []
anyone_can_get(url_list)
anyone_can_get(url_details)
anyone_can_get(url_descriptions)
bda_testdata = True
# The resulting JSON contains the information
_, client = self.client_matrix[0]
# List
resp = client.get(url_list)
def test_api_list(self):
url_list = "/gestion/bda/catalogue/list"
resp = self.client.get(url_list)
self.assertJSONEqual(
resp.content.decode("utf-8"),
[{"id": self.tirage.id, "title": self.tirage.title}],
)
# Details
resp = client.get(url_details)
def test_api_details(self):
url_details = "/gestion/bda/catalogue/details?id={}".format(self.tirage.id)
resp = self.client.get(url_details)
self.assertJSONEqual(
resp.content.decode("utf-8"),
{
@ -228,8 +309,11 @@ class TestBdAViews(BdATestHelpers, TestCase):
},
)
# Descriptions
resp = client.get(url_descriptions)
def test_api_descriptions(self):
url_descriptions = "/gestion/bda/catalogue/descriptions?id={}".format(
self.tirage.id
)
resp = self.client.get(url_descriptions)
raw = resp.content.decode("utf-8")
try:
results = json.loads(raw)
@ -242,6 +326,43 @@ class TestBdAViews(BdATestHelpers, TestCase):
)
# ----- BdA Revente --------------------------------------- #
def make_participant(name: str, tirage: Tirage) -> User:
user = User.objects.create_user(username=name, password=name)
user.profile.is_cof = True
user.profile.save()
Participant.objects.create(user=user, tirage=tirage)
return user
class TestReventeManageTest(TestCase):
def setUp(self):
self.tirage = Tirage.objects.create(
title="tirage1",
ouverture=timezone.now(),
fermeture=timezone.now() + timedelta(days=90),
)
self.user = make_participant("toto", self.tirage)
self.url = reverse("bda-revente-manage", args=[self.tirage.id])
# Signals handlers on login/logout send messages.
# Due to the way the Django' test Client performs login, this raise an
# error. As workaround, we mock the Django' messages module.
patcher_messages = mock.patch("gestioncof.signals.messages")
patcher_messages.start()
self.addCleanup(patcher_messages.stop)
def test_can_get(self):
client = Client()
client.force_login(
self.user, backend="django.contrib.auth.backends.ModelBackend"
)
r = client.get(self.url)
self.assertEqual(r.status_code, 200)
class TestBdaRevente:
pass
# TODO

36
bda/tests/utils.py Normal file
View file

@ -0,0 +1,36 @@
from datetime import timedelta
from django.contrib.auth.models import User
from django.utils import timezone
from ..models import CategorieSpectacle, Salle, Spectacle, Tirage
def create_user(username, is_cof=False, is_buro=False):
user = User.objects.create_user(username=username, password=username)
user.profile.is_cof = is_cof
user.profile.is_buro = is_buro
user.profile.save()
return user
def user_is_cof(user):
return (user is not None) and user.profile.is_cof
def user_is_staff(user):
return (user is not None) and user.profile.is_buro
def create_spectacle(**kwargs):
defaults = {
"title": "Title",
"category": CategorieSpectacle.objects.first(),
"date": (timezone.now() + timedelta(days=7)).date(),
"location": Salle.objects.first(),
"price": 10.0,
"slots": 20,
"tirage": Tirage.objects.first(),
"listing": False,
}
return Spectacle.objects.create(**dict(defaults, **kwargs))

View file

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

View file

@ -4,19 +4,19 @@ import random
import time
from collections import defaultdict
from custommail.models import CustomMail
from custommail.shortcuts import send_custom_mail, send_mass_custom_mail
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.core import serializers
from django.core.urlresolvers import reverse
from django.core.exceptions import NON_FIELD_ERRORS
from django.core.mail import send_mail, send_mass_mail
from django.db import transaction
from django.db.models import Count, Prefetch
from django.forms.models import inlineformset_factory
from django.http import HttpResponseBadRequest, HttpResponseRedirect, JsonResponse
from django.shortcuts import get_object_or_404, render
from django.template import loader
from django.template.defaultfilters import pluralize
from django.urls import reverse
from django.utils import formats, timezone
from django.views.generic.list import ListView
@ -41,8 +41,8 @@ from bda.models import (
SpectacleRevente,
Tirage,
)
from gestioncof.decorators import buro_required, cof_required
from utils.views.autocomplete import Select2QuerySetView
from gestioncof.decorators import BuroRequiredMixin, buro_required, cof_required
from shared.views import Select2QuerySetView
@cof_required
@ -188,22 +188,40 @@ def inscription(request, tirage_id):
ChoixSpectacle,
fields=("spectacle", "double_choice", "priority"),
formset=InscriptionInlineFormSet,
error_messages={
NON_FIELD_ERRORS: {
"unique_together": "Vous avez déjà demandé ce voeu plus haut !"
}
},
)
success = False
stateerror = False
if request.method == "POST":
# use *this* queryset
dbstate = _hash_queryset(participant.choixspectacle_set.all())
if "dbstate" in request.POST and dbstate != request.POST["dbstate"]:
stateerror = True
formset = BdaFormSet(instance=participant)
messages.error(
request,
"Impossible d'enregistrer vos modifications "
": vous avez apporté d'autres modifications "
"entre temps.",
)
else:
formset = BdaFormSet(request.POST, instance=participant)
if formset.is_valid():
formset.save()
success = True
formset = BdaFormSet(instance=participant)
participant.accepte_charte = True
participant.save()
messages.success(
request, "Votre inscription a été mise à jour avec succès !"
)
else:
messages.error(
request,
"Une erreur s'est produite lors de l'enregistrement de vos vœux. "
"Avez-vous demandé plusieurs fois le même spectacle ?",
)
else:
formset = BdaFormSet(instance=participant)
# use *this* queryset
@ -214,18 +232,6 @@ def inscription(request, tirage_id):
total_price += choice.spectacle.price
if choice.double:
total_price += choice.spectacle.price
# Messages
if success:
messages.success(
request, "Votre inscription a été mise à jour avec " "succès !"
)
if stateerror:
messages.error(
request,
"Impossible d'enregistrer vos modifications "
": vous avez apporté d'autres modifications "
"entre temps.",
)
return render(
request,
"bda/inscription-tirage.html",
@ -234,6 +240,7 @@ def inscription(request, tirage_id):
"total_price": total_price,
"dbstate": dbstate,
"tirage": tirage,
"charte": participant.accepte_charte,
},
)
@ -267,13 +274,13 @@ def do_tirage(tirage_elt, token):
results = Algorithm(data["shows"], data["members"], choices)(token)
# 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_losers"] += len(losers)
# On calcule le déficit et les bénéfices pour le BdA
# 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
data["total_sold"] += show.slots * show.price
if deficit >= 0:
@ -286,8 +293,8 @@ def do_tirage(tirage_elt, token):
# so assign a single object for each Participant id
members_uniq = {}
members2 = {}
for (show, members, _) in results:
for (member, _, _, _) in members:
for show, members, _ in results:
for member, _, _, _ in members:
if member.id not in members_uniq:
members_uniq[member.id] = member
members2[member] = []
@ -363,7 +370,7 @@ def tirage(request, tirage_id):
return render(request, "bda-token.html", {"form": form})
@login_required
@cof_required
def revente_manage(request, tirage_id):
"""
Gestion de ses propres reventes :
@ -374,13 +381,10 @@ def revente_manage(request, tirage_id):
- Annulation d'une revente après que le tirage a eu lieu
"""
tirage = get_object_or_404(Tirage, id=tirage_id)
participant, created = Participant.objects.get_or_create(
participant, created = Participant.objects.annotate_paid().get_or_create(
user=request.user, tirage=tirage
)
if not participant.paid:
return render(request, "bda/revente/notpaid.html", {})
resellform = ResellForm(participant, prefix="resell")
annulform = AnnulForm(participant, prefix="annul")
soldform = SoldForm(participant, prefix="sold")
@ -390,7 +394,7 @@ def revente_manage(request, tirage_id):
if "resell" in request.POST:
resellform = ResellForm(participant, request.POST, prefix="resell")
if resellform.is_valid():
datatuple = []
mails = []
attributions = resellform.cleaned_data["attributions"]
with transaction.atomic():
for attribution in attributions:
@ -405,16 +409,17 @@ def revente_manage(request, tirage_id):
"show": attribution.spectacle,
"revente": revente,
}
datatuple.append(
mails.append(
(
"bda-revente-new",
context,
"BdA-Revente : {}".format(attribution.spectacle),
loader.render_to_string(
"bda/mails/revente-seller.txt", context=context
),
settings.MAIL_DATA["revente"]["FROM"],
[participant.user.email],
)
)
revente.save()
send_mass_custom_mail(datatuple)
send_mass_mail(mails)
# On annule une revente
elif "annul" in request.POST:
annulform = AnnulForm(participant, request.POST, prefix="annul")
@ -445,6 +450,10 @@ def revente_manage(request, tirage_id):
new_date = timezone.now() - SpectacleRevente.remorse_time
revente.reset(new_date=new_date)
sold_exists = soldform.fields["reventes"].queryset.exists()
annul_exists = annulform.fields["reventes"].queryset.exists()
resell_exists = resellform.fields["attributions"].queryset.exists()
return render(
request,
"bda/revente/manage.html",
@ -453,11 +462,14 @@ def revente_manage(request, tirage_id):
"soldform": soldform,
"annulform": annulform,
"resellform": resellform,
"sold_exists": sold_exists,
"annul_exists": annul_exists,
"resell_exists": resell_exists,
},
)
@login_required
@cof_required
def revente_tirages(request, tirage_id):
"""
Affiche à un participant la liste de toutes les reventes en cours (pour un
@ -500,14 +512,22 @@ def revente_tirages(request, tirage_id):
),
)
annul_exists = annulform.fields["reventes"].queryset.exists()
sub_exists = subform.fields["reventes"].queryset.exists()
return render(
request,
"bda/revente/tirages.html",
{"annulform": annulform, "subform": subform},
{
"annulform": annulform,
"subform": subform,
"annul_exists": annul_exists,
"sub_exists": sub_exists,
},
)
@login_required
@cof_required
def revente_confirm(request, revente_id):
revente = get_object_or_404(SpectacleRevente, id=revente_id)
participant, _ = Participant.objects.get_or_create(
@ -524,7 +544,7 @@ def revente_confirm(request, revente_id):
)
@login_required
@cof_required
def revente_subscribe(request, tirage_id):
"""
Permet à un participant de sélectionner ses préférences pour les reventes.
@ -541,7 +561,7 @@ def revente_subscribe(request, tirage_id):
form = InscriptionReventeForm(tirage, request.POST)
if form.is_valid():
choices = form.cleaned_data["spectacles"]
participant.choicesrevente = choices
participant.choicesrevente.set(choices)
participant.save()
for spectacle in choices:
qset = SpectacleRevente.objects.filter(attribution__spectacle=spectacle)
@ -569,18 +589,18 @@ def revente_subscribe(request, tirage_id):
)
# Messages
if success:
messages.success(request, "Ton inscription a bien été prise en compte")
messages.success(request, "Votre inscription a bien été prise en compte")
if deja_revente:
messages.info(
request,
"Des reventes existent déjà pour certains de "
"ces spectacles, vérifie les places "
"ces spectacles, vérifiez les places "
"disponibles sans tirage !",
)
if inscrit_revente:
shows = map("<li>{!s}</li>".format, inscrit_revente)
msg = (
"Tu as été inscrit à des reventes en cours pour les spectacles "
"Vous avez été inscrit·e à des reventes en cours pour les spectacles "
"<ul>{:s}</ul>".format("\n".join(shows))
)
messages.info(request, msg, extra_tags="safe")
@ -588,7 +608,7 @@ def revente_subscribe(request, tirage_id):
return render(request, "bda/revente/subscribe.html", {"form": form})
@login_required
@cof_required
def revente_buy(request, spectacle_id):
spectacle = get_object_or_404(Spectacle, id=spectacle_id)
tirage = spectacle.tirage
@ -618,12 +638,16 @@ def revente_buy(request, spectacle_id):
"acheteur": request.user,
"vendeur": revente.seller.user,
}
send_custom_mail(
"bda-buy-shotgun",
"bda@ens.fr",
send_mail(
"BdA-Revente : {}".format(spectacle.title),
loader.render_to_string(
"bda/mails/revente-shotgun-seller.txt", context=context
),
request.user.email,
[revente.seller.user.email],
context=context,
)
return render(
request,
"bda/revente/mail-success.html",
@ -637,7 +661,7 @@ def revente_buy(request, spectacle_id):
)
@login_required
@cof_required
def revente_shotgun(request, tirage_id):
tirage = get_object_or_404(Tirage, id=tirage_id)
spectacles = (
@ -657,7 +681,7 @@ def revente_shotgun(request, tirage_id):
)
shotgun = [sp for sp in spectacles if len(sp.shotguns) > 0]
return render(request, "bda/revente/shotgun.html", {"shotgun": shotgun})
return render(request, "bda/revente/shotgun.html", {"spectacles": shotgun})
@buro_required
@ -676,12 +700,13 @@ def spectacle(request, tirage_id, spectacle_id):
"username": participant.user.username,
"email": participant.user.email,
"given": int(attrib.given),
"paid": participant.paid,
"paid": attrib.paid,
"nb_places": 1,
}
if participant.id in participants:
participants[participant.id]["nb_places"] += 1
participants[participant.id]["given"] += attrib.given
participants[participant.id]["paid"] &= attrib.paid
else:
participants[participant.id] = participant_info
@ -709,34 +734,37 @@ class SpectacleListView(ListView):
return context
@buro_required
def unpaid(request, tirage_id):
tirage = get_object_or_404(Tirage, id=tirage_id)
unpaid = (
tirage.participant_set.annotate(nb_attributions=Count("attribution"))
.filter(paid=False, nb_attributions__gt=0)
class UnpaidParticipants(BuroRequiredMixin, ListView):
context_object_name = "unpaid"
template_name = "bda-unpaid.html"
def get_queryset(self):
return (
Participant.objects.annotate_paid()
.filter(tirage__id=self.kwargs["tirage_id"], paid=False)
.select_related("user")
)
return render(request, "bda-unpaid.html", {"unpaid": unpaid})
@buro_required
def send_rappel(request, spectacle_id):
show = get_object_or_404(Spectacle, id=spectacle_id)
# Mails d'exemples
custommail = CustomMail.objects.get(shortname="bda-rappel")
exemple_mail_1place = custommail.render(
{"member": request.user, "show": show, "nb_attr": 1}
subject = show.title
body_mail_1place = loader.render_to_string(
"bda/mails/rappel.txt",
context={"member": request.user, "show": show, "nb_attr": 1},
)
exemple_mail_2places = custommail.render(
{"member": request.user, "show": show, "nb_attr": 2}
body_mail_2places = loader.render_to_string(
"bda/mails/rappel.txt",
context={"member": request.user, "show": show, "nb_attr": 2},
)
# Contexte
ctxt = {
"show": show,
"exemple_mail_1place": exemple_mail_1place,
"exemple_mail_2places": exemple_mail_2places,
"custommail": custommail,
"exemple_mail_1place": (subject, body_mail_1place),
"exemple_mail_2places": (subject, body_mail_2places),
}
# Envoi confirmé
if request.method == "POST":
@ -757,25 +785,6 @@ def send_rappel(request, spectacle_id):
return render(request, "bda/mails-rappel.html", ctxt)
def descriptions_spectacles(request, tirage_id):
tirage = get_object_or_404(Tirage, id=tirage_id)
shows_qs = tirage.spectacle_set.select_related("location").prefetch_related(
"quote_set"
)
category_name = request.GET.get("category", "")
location_id = request.GET.get("location", "")
if category_name:
shows_qs = shows_qs.filter(category__name=category_name)
if location_id:
try:
shows_qs = shows_qs.filter(location__id=int(location_id))
except ValueError:
return HttpResponseBadRequest(
"La variable GET 'location' doit contenir un entier"
)
return render(request, "descriptions.html", {"shows": shows_qs})
def catalogue(request, request_type):
"""
Vue destinée à communiquer avec un client AJAX, fournissant soit :

5
bds/admin.py Normal file
View file

@ -0,0 +1,5 @@
from django.contrib import admin
from bds.models import BDSProfile
admin.site.register(BDSProfile)

28
bds/apps.py Normal file
View file

@ -0,0 +1,28 @@
from django.apps import AppConfig, apps as global_apps
from django.db.models import Q
from django.db.models.signals import post_migrate
def bds_group_perms(app_config, apps=global_apps, **kwargs):
try:
Permission = apps.get_model("auth", "Permission")
Group = apps.get_model("auth", "Group")
group = Group.objects.get(name="Burô du BDS")
perms = Permission.objects.filter(
Q(content_type__app_label="bds")
| Q(content_type__app_label="auth") & Q(content_type__model="user")
)
group.permissions.set(perms)
group.save()
except (LookupError, Group.DoesNotExist):
return
class BdsConfig(AppConfig):
name = "bds"
verbose_name = "Gestion des adhérent·e·s du BDS"
def ready(self):
post_migrate.connect(bds_group_perms, sender=self)

63
bds/autocomplete.py Normal file
View file

@ -0,0 +1,63 @@
from urllib.parse import urlencode
from django.contrib.auth import get_user_model
from django.db.models import Q
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from shared import autocomplete
User = get_user_model()
class BDSMemberSearch(autocomplete.ModelSearch):
model = User
search_fields = ["username", "first_name", "last_name"]
verbose_name = _("Membres du BDS")
def get_queryset_filter(self, *args, **kwargs):
qset_filter = super().get_queryset_filter(*args, **kwargs)
qset_filter &= Q(bds__is_member=True)
return qset_filter
def result_uuid(self, user):
return user.username
def result_link(self, user):
return reverse("bds:user.update", args=(user.pk,))
class BDSOthersSearch(autocomplete.ModelSearch):
model = User
search_fields = ["username", "first_name", "last_name"]
verbose_name = _("Non-membres du BDS")
def get_queryset_filter(self, *args, **kwargs):
qset_filter = super().get_queryset_filter(*args, **kwargs)
qset_filter &= Q(bds__isnull=True) | Q(bds__is_member=False)
return qset_filter
def result_uuid(self, user):
return user.username
def result_link(self, user):
return reverse("bds:user.update", args=(user.pk,))
class BDSLDAPSearch(autocomplete.LDAPSearch):
def result_link(self, clipper):
url = reverse("bds:user.create.fromclipper", args=(clipper.clipper,))
get = {"fullname": clipper.fullname, "mail": clipper.mail}
return "{}?{}".format(url, urlencode(get))
class BDSSearch(autocomplete.Compose):
search_units = [
("members", BDSMemberSearch()),
("others", BDSOthersSearch()),
("clippers", BDSLDAPSearch()),
]
bds_search = BDSSearch()

41
bds/forms.py Normal file
View file

@ -0,0 +1,41 @@
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import UserCreationForm
from django.utils.translation import gettext_lazy as _
from bds.models import BDSProfile
User = get_user_model()
class UserForm(forms.ModelForm):
is_buro = forms.BooleanField(label=_("Membre du Burô"), required=False)
class Meta:
model = User
fields = ["email", "first_name", "last_name"]
class UserFromClipperForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["username"].disabled = True
class Meta:
model = User
fields = ["username", "email", "first_name", "last_name"]
class UserFromScratchForm(UserCreationForm):
class Meta:
model = User
fields = ["username", "email", "first_name", "last_name"]
class ProfileForm(forms.ModelForm):
class Meta:
model = BDSProfile
exclude = ["user"]
widgets = {
"birthdate": forms.DateInput(attrs={"type": "date"}, format="%Y-%m-%d")
}

View file

@ -0,0 +1,141 @@
# Generated by Django 2.2 on 2019-07-17 12:48
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
import bds.models
class Migration(migrations.Migration):
initial = True
dependencies = [migrations.swappable_dependency(settings.AUTH_USER_MODEL)]
operations = [
migrations.CreateModel(
name="BDSProfile",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"phone",
models.CharField(
blank=True, max_length=20, verbose_name="téléphone"
),
),
(
"occupation",
models.CharField(
choices=[
("EXT", "Extérieur"),
("1A", "1A"),
("2A", "2A"),
("3A", "3A"),
("4A", "4A"),
("MAG", "Magistérien"),
("ARC", "Archicube"),
("DOC", "Doctorant"),
("CST", "CST"),
("PER", "Personnel ENS"),
],
default="1A",
max_length=3,
verbose_name="occupation",
),
),
(
"departement",
models.CharField(
blank=True, max_length=50, verbose_name="département"
),
),
(
"birthdate",
models.DateField(
blank=True, null=True, verbose_name="date de naissance"
),
),
(
"mails_bds",
models.BooleanField(
default=False, verbose_name="recevoir les mails du BDS"
),
),
(
"is_buro",
models.BooleanField(
default=False, verbose_name="membre du Burô du BDS"
),
),
(
"has_certificate",
models.BooleanField(
default=False, verbose_name="certificat médical"
),
),
(
"certificate_file",
models.FileField(
blank=True,
upload_to=bds.models.BDSProfile.get_certificate_filename,
verbose_name="fichier de certificat médical",
),
),
(
"ASPSL_number",
models.CharField(
blank=True,
max_length=50,
null=True,
verbose_name="numéro AS PSL",
),
),
(
"FFSU_number",
models.CharField(
blank=True, max_length=50, null=True, verbose_name="numéro FFSU"
),
),
(
"cotisation_period",
models.CharField(
choices=[
("ANN", "Année"),
("SE1", "Premier semestre"),
("SE2", "Deuxième semestre"),
("NO", "Aucune"),
],
default="NO",
max_length=3,
verbose_name="inscription",
),
),
(
"registration_date",
models.DateField(
auto_now_add=True, verbose_name="date d'inscription"
),
),
(
"user",
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
related_name="bds",
to=settings.AUTH_USER_MODEL,
),
),
],
options={
"verbose_name": "Profil BDS",
"verbose_name_plural": "Profils BDS",
},
)
]

View file

@ -0,0 +1,16 @@
# Generated by Django 2.2 on 2019-07-17 14:56
from django.db import migrations
def create_bds_buro_group(apps, schema_editor):
Group = apps.get_model("auth", "Group")
Group.objects.get_or_create(name="Burô du BDS")
class Migration(migrations.Migration):
dependencies = [("bds", "0001_initial")]
operations = [
migrations.RunPython(create_bds_buro_group, migrations.RunPython.noop)
]

View file

@ -0,0 +1,24 @@
# Generated by Django 2.2.8 on 2019-12-20 22:48
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("bds", "0002_bds_group"),
]
operations = [
migrations.AlterModelOptions(
name="bdsprofile",
options={
"permissions": (("is_team", "est membre du burô"),),
"verbose_name": "Profil BDS",
"verbose_name_plural": "Profils BDS",
},
),
migrations.RemoveField(
model_name="bdsprofile",
name="is_buro",
),
]

View file

@ -0,0 +1,33 @@
# Generated by Django 2.2.8 on 2019-12-22 10:20
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bds", "0003_staff_permission"),
]
operations = [
migrations.AddField(
model_name="bdsprofile",
name="cotisation_type",
field=models.CharField(
choices=[
("ETU", "Étudiant"),
("NOR", "Normalien"),
("EXT", "Extérieur"),
("ARC", "Archicube"),
],
default="Normalien",
max_length=9,
verbose_name="type de cotisation",
),
preserve_default=False,
),
migrations.AddField(
model_name="bdsprofile",
name="is_member",
field=models.BooleanField(default=False, verbose_name="adhérent⋅e du BDS"),
),
]

View file

@ -0,0 +1,16 @@
# Generated by Django 2.2.14 on 2020-07-27 20:14
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("bds", "0004_is_member_cotiz_type"),
]
operations = [
migrations.RemoveField(
model_name="bdsprofile",
name="certificate_file",
),
]

View file

@ -0,0 +1,22 @@
# Generated by Django 2.2.12 on 2020-08-28 12:14
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bds", "0005_remove_bdsprofile_certificate_file"),
]
operations = [
migrations.AddField(
model_name="bdsprofile",
name="comments",
field=models.TextField(
blank=True,
help_text="Attention : l'utilisateur·ice dispose d'un droit d'accès"
" aux données le/la concernant, dont le contenu de ce champ !",
verbose_name="commentaires",
),
),
]

122
bds/mixins.py Normal file
View file

@ -0,0 +1,122 @@
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.core.exceptions import ImproperlyConfigured
from django.http import HttpResponseRedirect
from django.views.generic.base import ContextMixin, TemplateResponseMixin, View
class StaffRequiredMixin(PermissionRequiredMixin):
permission_required = "bds.is_team"
class MultipleFormMixin(ContextMixin):
"""Mixin pour gérer plusieurs formulaires dans la même vue.
Le fonctionnement est relativement identique à celui de
FormMixin, dont la documentation est disponible ici :
https://docs.djangoproject.com/en/3.0/ref/class-based-views/mixins-editing/
Les principales différences sont :
- au lieu de form_class, il faut donner comme attribut un dict de la forme
{<form_name>: <form_class>}, avec tous les formulaires à instancier. On
peut aussi redéfinir `get_form_classes`
- les données initiales se récupèrent pour chaque form via l'attribut
`<form_name>_initial` ou la fonction `get_<form_name>_initial`. De même,
si certaines forms sont des `ModelForm`s, on peut définir la fonction
`get_<form_name>_instance`.
- chaque form a un préfixe rajouté, par défaut <form_name>, mais qui peut
être customisé via `prefixes` ou `get_prefixes`.
"""
form_classes = {}
prefixes = {}
initial = {}
success_url = None
def get_form_classes(self):
return self.form_classes
def get_initial(self, form_name):
initial_attr = "%s_initial" % form_name
initial_method = "get_%s_initial" % form_name
initial_method = getattr(self, initial_method, None)
if hasattr(self, initial_attr):
return getattr(self, initial_attr)
elif callable(initial_method):
return initial_method()
else:
return self.initial.copy()
def get_prefix(self, form_name):
return self.prefixes.get(form_name, form_name)
def get_instance(self, form_name):
# Au cas où certaines des forms soient des ModelForms
instance_method = "get_%s_instance" % form_name
instance_method = getattr(self, instance_method, None)
if callable(instance_method):
return instance_method()
else:
return None
def get_form_kwargs(self, form_name):
kwargs = {
"initial": self.get_initial(form_name),
"prefix": self.get_prefix(form_name),
"instance": self.get_instance(form_name),
}
if self.request.method in ("POST", "PUT"):
kwargs.update({"data": self.request.POST, "files": self.request.FILES})
return kwargs
def get_forms(self):
form_classes = self.get_form_classes()
return {
form_name: form_class(**self.get_form_kwargs(form_name))
for form_name, form_class in form_classes.items()
}
def get_success_url(self):
if not self.success_url:
raise ImproperlyConfigured("No URL to redirect to. Provide a success_url.")
return str(self.success_url)
def form_valid(self, forms):
# on garde le nom form_valid pour l'interface avec SuccessMessageMixin
return HttpResponseRedirect(self.get_success_url())
def form_invalid(self, forms):
"""If the form is invalid, render the invalid form."""
return self.render_to_response(self.get_context_data(forms=forms))
class ProcessMultipleFormView(View):
"""Équivalent de `ProcessFormView` pour plusieurs forms.
Note : il faut que *tous* les formulaires soient valides pour
qu'ils soient sauvegardés !
"""
def get(self, request, *args, **kwargs):
forms = self.get_forms()
return self.render_to_response(self.get_context_data(forms=forms))
def post(self, request, *args, **kwargs):
forms = self.get_forms()
if all(form.is_valid() for form in forms.values()):
return self.form_valid(forms)
else:
return self.form_invalid(forms)
class BaseMultipleFormView(MultipleFormMixin, ProcessMultipleFormView):
pass
class MultipleFormView(TemplateResponseMixin, BaseMultipleFormView):
pass

113
bds/models.py Normal file
View file

@ -0,0 +1,113 @@
from datetime import date
from os.path import splitext
from django.contrib.auth import get_user_model
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from shared.utils import choices_length
User = get_user_model()
class BDSProfile(models.Model):
OCCUPATION_CHOICES = (
("EXT", "Extérieur"),
("1A", "1A"),
("2A", "2A"),
("3A", "3A"),
("4A", "4A"),
("MAG", "Magistérien"),
("ARC", "Archicube"),
("DOC", "Doctorant"),
("CST", "CST"),
("PER", "Personnel ENS"),
)
TYPE_COTIZ_CHOICES = (
("ETU", "Étudiant"),
("NOR", "Normalien"),
("EXT", "Extérieur"),
("ARC", "Archicube"),
)
COTIZ_DURATION_CHOICES = (
("ANN", "Année"),
("SE1", "Premier semestre"),
("SE2", "Deuxième semestre"),
("NO", "Aucune"),
)
def get_certificate_filename(instance, filename):
_, ext = splitext(filename) # récupère l'extension du fichier
year = str(date.now().year)
return "certifs/{username}-{year}.{ext}".format(
username=instance.user.username, year=year, ext=ext
)
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="bds")
phone = models.CharField(_("téléphone"), max_length=20, blank=True)
occupation = models.CharField(
_("occupation"),
default="1A",
choices=OCCUPATION_CHOICES,
max_length=choices_length(OCCUPATION_CHOICES),
)
departement = models.CharField(_("département"), max_length=50, blank=True)
birthdate = models.DateField(
auto_now_add=False,
auto_now=False,
verbose_name=_("date de naissance"),
blank=True,
null=True,
)
is_member = models.BooleanField(_("adhérent⋅e du BDS"), default=False)
mails_bds = models.BooleanField(_("recevoir les mails du BDS"), default=False)
has_certificate = models.BooleanField(_("certificat médical"), default=False)
ASPSL_number = models.CharField(
_("numéro AS PSL"), max_length=50, blank=True, null=True
)
FFSU_number = models.CharField(
_("numéro FFSU"), max_length=50, blank=True, null=True
)
cotisation_period = models.CharField(
_("inscription"), default="NO", choices=COTIZ_DURATION_CHOICES, max_length=3
)
registration_date = models.DateField(
auto_now_add=True, verbose_name=_("date d'inscription")
)
cotisation_type = models.CharField(
_("type de cotisation"), choices=TYPE_COTIZ_CHOICES, max_length=9
)
comments = models.TextField(
_("commentaires"),
blank=True,
help_text=_(
"Attention : l'utilisateur·ice dispose d'un droit d'accès aux données "
"le/la concernant, dont le contenu de ce champ !"
),
)
@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:
verbose_name = _("Profil BDS")
verbose_name_plural = _("Profils BDS")
permissions = (("is_team", _("est membre du burô")),)
def __str__(self):
return self.user.username

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,15 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="300px" height="246px" viewBox="0 0 3000 2460" preserveAspectRatio="xMidYMid meet">
<g id="layer101" fill="#ffffff" stroke="none">
<path d="M0 1230 l0 -1230 1500 0 1500 0 0 1230 0 1230 -1500 0 -1500 0 0 -1230z"/>
</g>
<g id="layer102" fill="#3e2263" stroke="none">
<path d="M0 1230 l0 -1230 1500 0 1500 0 0 1230 0 1230 -1500 0 -1500 0 0 -1230z m1716 765 c103 -17 204 -46 284 -83 l55 -25 -40 -8 c-80 -16 -169 -10 -245 16 -123 42 -232 59 -385 59 -126 0 -278 -18 -341 -40 -13 -5 -16 -4 -9 4 14 15 166 60 254 76 102 19 315 19 427 1z m-703 -217 c15 -6 27 -13 27 -17 0 -4 -37 -25 -82 -47 -86 -43 -182 -120 -193 -155 -8 -26 32 -113 78 -167 44 -52 46 -62 10 -62 -39 1 -106 33 -165 80 -40 31 -54 38 -64 29 -21 -18 -17 -50 16 -116 57 -113 151 -199 259 -235 49 -16 51 -18 16 -13 -123 19 -260 151 -322 310 -15 39 -14 -81 1 -147 25 -107 55 -176 112 -251 49 -65 52 -73 38 -88 -21 -23 -104 -62 -216 -100 -51 -18 -97 -35 -102 -40 -4 -4 32 -10 80 -14 106 -9 256 13 317 48 l39 22 56 -33 c32 -18 114 -61 184 -95 80 -39 126 -67 123 -74 -6 -19 12 -16 19 3 9 24 28 5 22 -22 -7 -26 8 -34 18 -9 11 29 28 16 21 -18 -6 -30 -5 -31 10 -13 8 11 15 24 15 29 0 4 5 5 10 2 6 -3 8 -18 4 -33 -5 -26 -5 -26 10 -8 15 19 18 19 118 -12 113 -35 284 -72 329 -72 24 0 29 4 29 25 0 34 -36 125 -63 158 l-22 28 -59 -30 c-74 -39 -165 -43 -233 -10 -24 11 -43 25 -43 30 0 4 28 6 63 2 49 -4 71 -2 98 12 46 23 79 55 79 75 0 16 -48 66 -135 139 l-40 33 43 -23 c55 -30 166 -121 188 -154 9 -13 13 -29 9 -36 -15 -23 -100 -69 -129 -69 -17 0 -38 -5 -46 -10 -12 -8 -10 -10 10 -10 49 1 104 19 149 51 l45 31 24 -28 c33 -40 72 -128 79 -180 10 -79 -25 -96 -233 -114 -84 -7 -148 -7 -218 0 -106 12 -269 51 -317 76 -28 14 -31 13 -62 -10 -56 -43 -167 -89 -225 -94 l-55 -5 6 29 c2 16 14 55 26 86 21 57 27 112 15 142 -3 9 -34 38 -68 64 l-62 49 -104 7 c-166 12 -192 34 -83 70 34 12 65 24 68 28 4 4 -7 27 -24 52 -118 171 -124 402 -16 571 18 29 50 88 70 131 42 93 99 154 168 184 82 35 212 44 280 18z m540 -39 c60 -16 70 -41 75 -196 l5 -134 -39 3 -39 3 -5 114 c-4 93 -8 116 -22 125 -31 19 -41 -7 -47 -126 l-6 -113 -32 -3 c-41 -4 -44 6 -34 151 9 143 25 172 101 186 3 0 22 -4 43 -10z m322 -34 c0 -30 0 -30 -64 -33 l-64 -3 7 -130 7 -129 -35 0 -36 0 0 165 0 166 93 -3 92 -3 0 -30z m115 -55 l5 -84 18 27 c21 33 39 34 60 5 15 -22 16 -18 16 60 l1 82 35 0 35 0 -2 -162 -3 -163 -40 0 c-38 0 -41 2 -53 43 -16 49 -24 48 -42 -7 -12 -38 -16 -41 -50 -41 -34 0 -38 3 -44 31 -8 43 -8 284 1 293 4 4 19 6 33 4 24 -3 25 -6 30 -88z m370 -42 c193 -243 228 -505 100 -759 -61 -120 -195 -260 -328 -343 -66 -41 -60 -26 13 33 36 29 92 85 125 126 182 230 209 500 75 753 -42 79 -45 89 -45 163 0 44 4 79 9 79 5 0 28 -24 51 -52z m-1111 -294 c76 -30 94 -102 41 -156 -27 -27 -29 -32 -17 -47 34 -40 25 -100 -19 -120 -30 -13 -143 -15 -164 -1 -11 7 -15 42 -18 164 l-4 156 23 9 c37 15 115 13 158 -5z m571 -9 c84 -43 61 -135 -43 -173 -46 -18 -52 -23 -52 -48 0 -39 30 -42 79 -9 l37 25 -3 -41 c-4 -49 -32 -76 -90 -85 -32 -6 -41 -2 -68 24 -24 25 -30 39 -30 74 0 57 21 85 87 114 40 18 54 29 51 42 -5 29 -71 28 -111 -2 -19 -14 -36 -26 -39 -26 -11 0 -16 55 -7 72 24 45 131 63 189 33z m-303 -12 c56 -26 75 -65 71 -150 -3 -67 -6 -75 -38 -108 -43 -44 -94 -61 -146 -48 l-39 9 -3 144 c-1 79 0 150 2 157 8 19 110 17 153 -4z"/>
<path d="M1503 633 c4 -3 10 -3 14 0 3 4 0 7 -7 7 -7 0 -10 -3 -7 -7z"/>
<path d="M1532 448 c3 -7 15 -14 29 -16 23 -2 23 -2 5 13 -24 18 -39 20 -34 3z"/>
<path d="M1140 1231 c0 -45 10 -61 36 -61 26 0 64 32 64 53 0 23 -23 37 -62 37 -35 0 -38 -2 -38 -29z"/>
<path d="M1140 1070 c0 -35 17 -45 56 -36 20 5 25 12 22 34 -3 23 -8 27 -40 30 -36 3 -38 2 -38 -28z"/>
<path d="M1430 1151 c0 -72 3 -91 14 -91 28 0 47 13 61 41 31 60 10 121 -47 135 l-28 6 0 -91z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="xMidYMid meet"
viewBox="0 0 2560 2560"
height="256"
width="256"
version="1.0">
<g
transform="translate(-220,50)"
stroke="none"
fill="#ffffff"
id="layer101">
<path
id="path2"
d="M 0,1230 V 0 H 1500 3000 V 1230 2460 H 1500 0 Z" />
</g>
<g
transform="translate(-220,50)"
stroke="none"
fill="#3e2263"
id="layer102">
<path
id="path5"
d="M 220,1230 V -50 H 1500 2780 V 1230 2510 H 1500 220 Z m 1496,765 c 103,-17 204,-46 284,-83 l 55,-25 -40,-8 c -80,-16 -169,-10 -245,16 -123,42 -232,59 -385,59 -126,0 -278,-18 -341,-40 -13,-5 -16,-4 -9,4 14,15 166,60 254,76 102,19 315,19 427,1 z m -703,-217 c 15,-6 27,-13 27,-17 0,-4 -37,-25 -82,-47 -86,-43 -182,-120 -193,-155 -8,-26 32,-113 78,-167 44,-52 46,-62 10,-62 -39,1 -106,33 -165,80 -40,31 -54,38 -64,29 -21,-18 -17,-50 16,-116 57,-113 151,-199 259,-235 49,-16 51,-18 16,-13 -123,19 -260,151 -322,310 -15,39 -14,-81 1,-147 25,-107 55,-176 112,-251 49,-65 52,-73 38,-88 -21,-23 -104,-62 -216,-100 -51,-18 -97,-35 -102,-40 -4,-4 32,-10 80,-14 106,-9 256,13 317,48 l 39,22 56,-33 c 32,-18 114,-61 184,-95 80,-39 126,-67 123,-74 -6,-19 12,-16 19,3 9,24 28,5 22,-22 -7,-26 8,-34 18,-9 11,29 28,16 21,-18 -6,-30 -5,-31 10,-13 8,11 15,24 15,29 0,4 5,5 10,2 6,-3 8,-18 4,-33 -5,-26 -5,-26 10,-8 15,19 18,19 118,-12 113,-35 284,-72 329,-72 24,0 29,4 29,25 0,34 -36,125 -63,158 l -22,28 -59,-30 c -74,-39 -165,-43 -233,-10 -24,11 -43,25 -43,30 0,4 28,6 63,2 49,-4 71,-2 98,12 46,23 79,55 79,75 0,16 -48,66 -135,139 l -40,33 43,-23 c 55,-30 166,-121 188,-154 9,-13 13,-29 9,-36 -15,-23 -100,-69 -129,-69 -17,0 -38,-5 -46,-10 -12,-8 -10,-10 10,-10 49,1 104,19 149,51 l 45,31 24,-28 c 33,-40 72,-128 79,-180 10,-79 -25,-96 -233,-114 -84,-7 -148,-7 -218,0 -106,12 -269,51 -317,76 -28,14 -31,13 -62,-10 -56,-43 -167,-89 -225,-94 l -55,-5 6,29 c 2,16 14,55 26,86 21,57 27,112 15,142 -3,9 -34,38 -68,64 l -62,49 -104,7 c -166,12 -192,34 -83,70 34,12 65,24 68,28 4,4 -7,27 -24,52 -118,171 -124,402 -16,571 18,29 50,88 70,131 42,93 99,154 168,184 82,35 212,44 280,18 z m 540,-39 c 60,-16 70,-41 75,-196 l 5,-134 -39,3 -39,3 -5,114 c -4,93 -8,116 -22,125 -31,19 -41,-7 -47,-126 l -6,-113 -32,-3 c -41,-4 -44,6 -34,151 9,143 25,172 101,186 3,0 22,-4 43,-10 z m 322,-34 c 0,-30 0,-30 -64,-33 l -64,-3 7,-130 7,-129 h -35 -36 v 165 166 l 93,-3 92,-3 z m 115,-55 5,-84 18,27 c 21,33 39,34 60,5 15,-22 16,-18 16,60 l 1,82 h 35 35 l -2,-162 -3,-163 h -40 c -38,0 -41,2 -53,43 -16,49 -24,48 -42,-7 -12,-38 -16,-41 -50,-41 -34,0 -38,3 -44,31 -8,43 -8,284 1,293 4,4 19,6 33,4 24,-3 25,-6 30,-88 z m 370,-42 c 193,-243 228,-505 100,-759 -61,-120 -195,-260 -328,-343 -66,-41 -60,-26 13,33 36,29 92,85 125,126 182,230 209,500 75,753 -42,79 -45,89 -45,163 0,44 4,79 9,79 5,0 28,-24 51,-52 z M 1249,1314 c 76,-30 94,-102 41,-156 -27,-27 -29,-32 -17,-47 34,-40 25,-100 -19,-120 -30,-13 -143,-15 -164,-1 -11,7 -15,42 -18,164 l -4,156 23,9 c 37,15 115,13 158,-5 z m 571,-9 c 84,-43 61,-135 -43,-173 -46,-18 -52,-23 -52,-48 0,-39 30,-42 79,-9 l 37,25 -3,-41 c -4,-49 -32,-76 -90,-85 -32,-6 -41,-2 -68,24 -24,25 -30,39 -30,74 0,57 21,85 87,114 40,18 54,29 51,42 -5,29 -71,28 -111,-2 -19,-14 -36,-26 -39,-26 -11,0 -16,55 -7,72 24,45 131,63 189,33 z m -303,-12 c 56,-26 75,-65 71,-150 -3,-67 -6,-75 -38,-108 -43,-44 -94,-61 -146,-48 l -39,9 -3,144 c -1,79 0,150 2,157 8,19 110,17 153,-4 z" />
<path
id="path7"
d="m 1503,633 c 4,-3 10,-3 14,0 3,4 0,7 -7,7 -7,0 -10,-3 -7,-7 z" />
<path
id="path9"
d="m 1532,448 c 3,-7 15,-14 29,-16 23,-2 23,-2 5,13 -24,18 -39,20 -34,3 z" />
<path
id="path11"
d="m 1140,1231 c 0,-45 10,-61 36,-61 26,0 64,32 64,53 0,23 -23,37 -62,37 -35,0 -38,-2 -38,-29 z" />
<path
id="path13"
d="m 1140,1070 c 0,-35 17,-45 56,-36 20,5 25,12 22,34 -3,23 -8,27 -40,30 -36,3 -38,2 -38,-28 z" />
<path
id="path15"
d="m 1430,1151 c 0,-72 3,-91 14,-91 28,0 47,13 61,41 31,60 10,121 -47,135 l -28,6 z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4 KiB

View file

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:ns1="http://sozi.baierouge.fr"
xmlns:cc="http://web.resource.org/cc/"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:dc="http://purl.org/dc/elements/1.1/"
id="Layer_1"
enable-background="new 0 0 40 40"
xml:space="preserve"
viewBox="0 0 40 40"
version="1.1"
y="0px"
x="0px"
>
<polygon
points="36.351 32.435 25.5 36.271 25.5 3.94 36.351 6.242"
fill="#ffffff"
/>
<g
fill="#ffffff"
>
<path
d="m13.627 29.253l8.123-8.941c0.241-0.241 0.379-0.58 0.379-0.934s-0.138-0.693-0.379-0.934l-8.123-8.943c-0.346-0.348-0.853-0.44-1.286-0.238-0.436 0.203-0.717 0.662-0.717 1.171v3.193h-7.745c-0.658 0-1.191 0.572-1.191 1.277v8.943c0 0.705 0.533 1.276 1.191 1.276h7.745v3.194c0 0.509 0.281 0.969 0.716 1.172 0.434 0.204 0.94 0.112 1.287-0.236z"
/>
<path
d="m13.627 29.253l8.123-8.941c0.241-0.241 0.379-0.58 0.379-0.934s-0.138-0.693-0.379-0.934l-8.123-8.943c-0.346-0.348-0.853-0.44-1.286-0.238-0.436 0.203-0.717 0.662-0.717 1.171v3.193h-7.745c-0.658 0-1.191 0.572-1.191 1.277v8.943c0 0.705 0.533 1.276 1.191 1.276h7.745v3.194c0 0.509 0.281 0.969 0.716 1.172 0.434 0.204 0.94 0.112 1.287-0.236z"
/>
</g
>
<path
stroke-linejoin="round"
d="m24.166 6.224h-1.288c-1.78 0-3.223 1.442-3.223 3.223v3.981"
stroke="#ffffff"
stroke-linecap="round"
stroke-miterlimit="10"
fill="none"
/>
<path
stroke-linejoin="round"
d="m19.655 25.495v3.733c0 1.78 1.442 3.223 3.223 3.223h1.288"
stroke="#ffffff"
stroke-linecap="round"
stroke-miterlimit="10"
fill="none"
/>
<metadata
><rdf:RDF
><cc:Work
><dc:format
>image/svg+xml</dc:format
><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage"
/><cc:license
rdf:resource="http://creativecommons.org/licenses/publicdomain/"
/><dc:publisher
><cc:Agent
rdf:about="http://openclipart.org/"
><dc:title
>Openclipart</dc:title
></cc:Agent
></dc:publisher
></cc:Work
><cc:License
rdf:about="http://creativecommons.org/licenses/publicdomain/"
><cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction"
/><cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution"
/><cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
/></cc:License
></rdf:RDF
></metadata
></svg
>

After

Width:  |  Height:  |  Size: 2.9 KiB

7
bds/static/bds/js/bds.js Normal file
View file

@ -0,0 +1,7 @@
$(function () {
// Close notifications when delete button is pressed
$(".notification .delete").on("click", function () {
$(this).parent().remove();
});
});

View file

@ -0,0 +1,152 @@
// Compilation command :
// sass -I shared/static/src/ --watch bds/static/src/sass/bds.scss bds/static/bds/css/bds.css --style compressed
$text: black;
@import "bulma/bulma.sass";
$primary_color: #3e2263;
$background_color: #ddcecc;
html, body {
background: $background_color;
font-size: 18px;
}
a {
text-decoration: none;
color: #a82305;
}
/* header */
#search-bar {
background-color: $primary_color;
padding: 0 1em;
margin-bottom: 0;
#logout-mobile {
display: none;
}
@include mobile {
display: flex;
flex-wrap: wrap;
#logout-mobile {
display: flex;
flex-direction: row-reverse;
justify-content: space-between;
}
#logout {
display: none;
}
#search-input {
flex: 0 1 100%;
}
}
// Workaround : `justify-content : <left/right>` pas encore supporté
// Voir https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content
& :first-child, & :last-child {
justify-content: space-between;
}
& :last-child {
flex-direction: row-reverse;
}
input {
border-radius: 0;
margin: 10px 0;
}
}
/* Autocomplétion du BDS */
.highlight {
text-decoration: underline;
font-weight: bold;
}
.yourlabs-autocomplete {
ul {
list-style: none;
padding: 0;
margin: 0;
li {
height: 2em;
line-height: 2em;
padding: 0;
a {
color: inherit;
}
}
li.hilight {
background: #e8554e;
}
}
}
.autocomplete-item {
display: block;
width: 480px;
height: 100%;
padding: 2px 10px;
margin: 0;
}
.autocomplete-header {
background: #b497e1;
}
.autocomplete-value, .autocomplete-new, .autocomplete-more {
background: white;
}
/* --- Forms --- */
$button_color: lighten($primary_color, 10);
input[type="submit"] {
background-color: $button_color;
color: findColorInvert($button_color);
&:hover {
background-color: $primary_color;
color: findColorInvert($primary_color);
}
}
.button.is-primary {
background-color: $button_color;
color: findColorInvert($button_color);
&:hover {
background-color: $primary_color;
color: findColorInvert($primary_color);
}
}
/* --- Message styling --- */
.notification {
padding: 0.5em 0;
font-size: 1.2em;
text-align: center;
}
/* --- Modals --- */
.modal-card-head {
background-color: $primary_color;
.modal-card-title {
color: findColorInvert($primary_color);
}
}

View file

@ -0,0 +1,50 @@
{% load static %}
{% load bulma_utils %}
<!DOCTYPE html>
<html>
<head>
<title>{{ site.name }}</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
{# CSS #}
<link rel="stylesheet" href="{% static "bds/css/bds.css" %}">
<link type="text/css" rel="stylesheet" href="{% static 'vendor/font-awesome/css/font-awesome.min.css' %}">
{# Javascript #}
<script src="{% static 'vendor/jquery/jquery-3.3.1.min.js' %}"></script>
<script src="{% static "vendor/jquery/jquery.autocomplete-light.min.js" %}"></script>
<script src="{% static 'bds/js/bds.js' %}"></script>
{% block extra_head %}{% endblock extra_head %}
</head>
<body>
{% include "bds/nav.html" %}
{% block layout %}
<div class="columns">
<div class="column is-two-thirds is-offset-2">
<section class="section">
{% if messages %}
{% for message in messages %}
<div class="notification is-{{ message.level_tag|bulma_message_tag }}">
{% if 'safe' in message.tags %}
{{ message|safe }}
{% else %}
{{ message }}
{% endif %}
<button class="delete"></button>
</div>
{% endfor %}
{% endif %}
{% block content %}
{% endblock content %}
</section>
</div>
</div>
{% endblock layout %}
</body>
</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

@ -0,0 +1,16 @@
<div class="control">
{% if field.auto_id %}
<label class="checkbox {% if field.field.required %}{{ form.required_css_class }}{% endif %}">
{{ field }} {{ field.label }}
</label>
{% endif %}
{% for error in field.errors %}
<span class="help is-danger {{ form.error_css_class }}">{{ error }}</span>
{% endfor %}
{% if field.help_text %}
<p class="help">
{{ field.help_text|safe }}
</p>
{% endif %}
</div>

View file

@ -0,0 +1,33 @@
{% load bulma_utils %}
<div class="field">
{% if field|is_checkbox %}
{% include "bds/forms/checkbox.html" with field=field %}
{% elif field|is_radio %}
{% include "bds/forms/radio.html" with field=field %}
{% elif field|is_input %}
{% include "bds/forms/input.html" with field=field %}
{% elif field|is_textarea %}
{% include "bds/forms/textarea.html" with field=field %}
{% elif field|is_select %}
{% include "bds/forms/select.html" with field=field %}
{% elif field|is_file %}
{% include "bds/forms/file.html" with field=field %}
{% else %}
{% include "bds/forms/other.html" with field=field %}
{% endif %}
</div>

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