Compare commits

..

86 commits

Author SHA1 Message Date
thubrecht 2126224e15 Merge pull request 'Thubrecht/daphne' (#815) from thubrecht/daphne into master
Reviewed-on: DGNum/gestioCOF#815
2024-07-30 18:40:56 +02:00
Tom Hubrecht d6109a9312 dev: update requirements and directly read the files 2024-07-12 14:54:14 +02:00
Tom Hubrecht a69bd0426f kfet/open: Add comment to test 2024-07-12 14:54:14 +02:00
Tom Hubrecht 81a4dbef7c dev: set explicitely DJANGO_SETTINGS_MODULE 2024-07-12 14:54:14 +02:00
Tom Hubrecht 4fedf3453d kfet: remove redundant static tag 2024-07-12 14:54:14 +02:00
Tom Hubrecht 8607d77c84 dev: update requirements 2024-07-12 14:54:14 +02:00
Tom Hubrecht bc55a3067e Remove useless migrations 2024-07-12 14:54:14 +02:00
Tom Hubrecht dd68ad91cd Update django-hCaptcha 2024-07-12 14:54:14 +02:00
Tom Hubrecht 2f71246509 assertDictContainsSubset is deprecated 2024-07-12 14:54:14 +02:00
Tom Hubrecht a20a1c11d6 Explicitely set transform=repr in assertQuerysetEquals 2024-07-12 14:54:14 +02:00
Tom Hubrecht 0e1ff1765a assertEquals is deprecated 2024-07-12 14:54:14 +02:00
Tom Hubrecht 177d413f4c Use AutoField instead of BigAutoField 2024-07-12 14:54:14 +02:00
Tom Hubrecht 01dd16c795 url -> re_path 2024-07-12 14:54:14 +02:00
Tom Hubrecht 84c87c1b4b Replace unique_together by UniqueConstraint 2024-07-12 14:54:14 +02:00
Tom Hubrecht 1b143b322f Update changelog 2024-07-12 14:54:14 +02:00
Tom Hubrecht f9456e3c29 cof has been renamed to gestioasso 2024-07-12 14:54:14 +02:00
Tom Hubrecht dd1350f1c2 Fix typo 2024-07-12 14:54:14 +02:00
Tom Hubrecht 8f4cb68d31 Only run kf tests in sequential mode (to fix issues with channels) 2024-07-12 14:54:14 +02:00
Tom Hubrecht 3a3f96a8df Try not running tests in parallel 2024-07-12 14:54:14 +02:00
Tom Hubrecht 7d8926e459 Try to flush old messages in tests 2024-07-12 14:54:14 +02:00
Tom Hubrecht 3fee014384 Update kfet.open tests 2024-07-12 14:54:14 +02:00
Tom Hubrecht cd351786bb Remove default_app_config 2024-07-12 14:54:14 +02:00
Tom Hubrecht 7362c2fa2a Update django-djconfig 2024-07-12 14:54:14 +02:00
Tom Hubrecht efbc947145 Change backend name as the old one is deprecated 2024-07-12 14:54:14 +02:00
Tom Hubrecht 0c45262fbc ugettext -> gettext 2024-07-12 14:54:14 +02:00
Tom Hubrecht cabd277b4a Update redis, and implement a custom channel layer to send datetime/decimal objects 2024-07-12 14:54:14 +02:00
Tom Hubrecht 4108efe8c9 Fix kfet.ope tests 2024-07-12 14:54:14 +02:00
Tom Hubrecht 693e4252d5 Fix kpsul tests 2024-07-12 14:54:14 +02:00
Tom Hubrecht 3aa928e8f0 Simplify group_send for kpsul 2024-07-12 14:54:14 +02:00
Tom Hubrecht 5e2e68960b Channels 3 2024-07-12 14:54:14 +02:00
Tom Hubrecht 91e9beee11 Add default django asgi handler 2024-07-12 14:54:14 +02:00
Tom Hubrecht ac286209ed Fix app import 2024-07-12 14:54:14 +02:00
Tom Hubrecht b03cda5962 keyOrder is deprecated, using a list in Meta gives the correct order 2024-07-12 14:54:14 +02:00
Tom Hubrecht 4feb567af7 Update django-redis-cache and fix vagrant setup 2024-07-12 14:54:14 +02:00
Tom Hubrecht 1ac47885d0 Update django version 2024-07-12 14:54:14 +02:00
Tom Hubrecht 071c810605 Update base consumers 2024-07-12 14:54:14 +02:00
Tom Hubrecht 7f00ce0ff1 Add default http router 2024-07-12 14:54:14 +02:00
Tom Hubrecht 95136cb4eb Update daphne version 2024-07-12 14:54:14 +02:00
Tom Hubrecht e299997aa8 Update to django channels 2 2024-07-12 14:54:14 +02:00
Tom Hubrecht 40f34926bb Fix vagrant setup w/ daphne 2024-07-12 14:54:14 +02:00
thubrecht 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: DGNum/gestioCOF#833
2024-07-06 16:54:25 +02:00
Antoine Groudiev 6621ae3950 style(kfet): suppression de return 2024-07-06 16:49:35 +02:00
Antoine Groudiev 9288daaf9e feat(kfet): envoi de mail lors de la création d'un trigramme 2024-07-06 12:14:49 +02:00
Tom Hubrecht 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
soyouzpanda 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
Tom Hubrecht 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
Tom Hubrecht 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
Tom Hubrecht 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
Tom Hubrecht 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
Tom Hubrecht 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
Tom Hubrecht 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
Tom Hubrecht c36dd30bce fix(kfet): Affiche la bonne information 2023-05-22 18:26:24 +02:00
Tom Hubrecht 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
Tom Hubrecht 3eaac5c68f feat(cof): Rajoute la date d'adhésion dans les profils 2023-05-22 11:28:23 +02:00
Tom Hubrecht af4c8e0744 Update shell.nix and use django-types 2023-05-22 10:57:11 +02:00
Tom Hubrecht 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
Tom Hubrecht cb262ad479 fix(kfet): Update timezone data for moment.js 2023-05-19 16:45:15 +02:00
Tom Hubrecht 5c47118834 Update gitignore and shell.nix 2023-05-19 15:14:55 +02:00
Tom Hubrecht 30e842ce80 shell.nix: Update to use virtualenv 2023-05-19 14:59:19 +02:00
Tom Hubrecht 892bf51163 Run black on all files 2023-05-19 14:57:48 +02:00
Tom Hubrecht 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
Alice b80426c56f feat(kfet): message info about prices 2023-01-28 15:28:54 +01:00
Alice 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
Alice aad3775222 fix(kfet): fix js error when cancelling already canceled operation 2023-01-28 15:13:55 +01:00
Alice 4b92716092 feat: poc inventory amount value
and lint
2023-01-23 21:53:46 +01:00
Tom Hubrecht dfa5b4bf69 changelog: add current date 2022-10-03 18:37:41 +02:00
Tom Hubrecht fcf2002cd7 On n'affiche le négatif que s'il existe vraiment 2022-01-11 18:10:00 +01:00
Tom Hubrecht b236d6a950 Si last_rappel vaut None il n'est pas inclus dans le __lt 2022-01-11 18:10:00 +01:00
Tom Hubrecht 4b29097f02 On sauvegarde la date de fin du négatif 2022-01-11 18:10:00 +01:00
Tom Hubrecht 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 373ff1f62c Rend le surnom lisible par la personne 2021-11-25 14:44:40 +01:00
182 changed files with 457 additions and 452 deletions

3
.gitignore vendored
View file

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

View file

@ -30,6 +30,40 @@ adhérents ni des cotisations.
## Version ??? - ??/??/???? ## 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 ### K-Fêt
- Fixe un problème de rendu causé par l'agrandissement du menu - Fixe un problème de rendu causé par l'agrandissement du menu

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,3 @@
from datetime import date
from unittest import mock from unittest import mock
from django.conf import settings from django.conf import settings
@ -7,8 +6,6 @@ from django.contrib.auth.models import Permission
from django.test import Client, TestCase from django.test import Client, TestCase
from django.urls import reverse, reverse_lazy from django.urls import reverse, reverse_lazy
from bds.models import BDSProfile
User = get_user_model() User = get_user_model()
@ -27,7 +24,7 @@ def login_url(next=None):
class TestHomeView(TestCase): class TestHomeView(TestCase):
@mock.patch("gestioncof.signals.messages") @mock.patch("gestioncof.signals.messages")
def test_get(self, _): def test_get(self, mock_messages):
user = User.objects.create_user(username="random_user") user = User.objects.create_user(username="random_user")
give_bds_buro_permissions(user) give_bds_buro_permissions(user)
self.client.force_login( self.client.force_login(
@ -39,7 +36,7 @@ class TestHomeView(TestCase):
class TestRegistrationView(TestCase): class TestRegistrationView(TestCase):
@mock.patch("gestioncof.signals.messages") @mock.patch("gestioncof.signals.messages")
def test_get_autocomplete(self, _): def test_get_autocomplete(self, mock_messages):
user = User.objects.create_user(username="toto") user = User.objects.create_user(username="toto")
url = reverse("bds:autocomplete") + "?q=foo" url = reverse("bds:autocomplete") + "?q=foo"
client = Client() client = Client()
@ -59,7 +56,7 @@ class TestRegistrationView(TestCase):
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
@mock.patch("gestioncof.signals.messages") @mock.patch("gestioncof.signals.messages")
def test_get(self, _): def test_get(self, mock_messages):
user = User.objects.create_user(username="toto") user = User.objects.create_user(username="toto")
url = reverse("bds:user.update", args=(user.id,)) url = reverse("bds:user.update", args=(user.id,))
client = Client() client = Client()
@ -77,174 +74,3 @@ class TestRegistrationView(TestCase):
give_bds_buro_permissions(user) give_bds_buro_permissions(user)
resp = client.get(url) resp = client.get(url)
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
class TestResetMemberships(TestCase):
@classmethod
def setUpTestData(cls):
cls.admin = User.objects.create_user(username="bds_admin")
# Create users and profiles
cls.u_1 = User.objects.create_user(username="bds-01")
cls.p_1 = BDSProfile.objects.create(user=cls.u_1)
cls.u_2 = User.objects.create_user(username="bds-02")
cls.p_2 = BDSProfile.objects.create(user=cls.u_2)
cls.u_3 = User.objects.create_user(username="bds-03")
cls.p_3 = BDSProfile.objects.create(user=cls.u_3)
cls.u_4 = User.objects.create_user(username="bds-04")
cls.p_4 = BDSProfile.objects.create(user=cls.u_4)
@mock.patch("gestioncof.signals.messages")
def setUp(self, _):
give_bds_buro_permissions(self.admin)
# bds-01 est membre à l'année
self.p_1.is_member = True
self.p_1.mails_bds = True
self.p_1.cotisation_period = "ANN"
self.p_1.save()
# bds-02 est membre au S1
self.p_2.is_member = True
self.p_2.mails_bds = True
self.p_2.cotisation_period = "SE1"
self.p_2.save()
# bds-03 est membre au S2
self.p_3.is_member = True
self.p_3.mails_bds = True
self.p_3.cotisation_period = "SE2"
self.p_3.save()
@mock.patch("gestioncof.signals.messages")
def test_get_expired(self, _):
user = User.objects.create_user(username="toto")
url = reverse("bds:members.expired")
client = Client()
# Anonymous GET
resp = client.get(url)
self.assertRedirects(resp, login_url(next=url))
# Logged-in but unprivileged GET
client.force_login(user, backend="django.contrib.auth.backends.ModelBackend")
resp = client.get(url)
self.assertEquals(resp.status_code, 403)
# Burô user GET
give_bds_buro_permissions(user)
resp = client.get(url)
self.assertEquals(resp.status_code, 200)
self.assertQuerysetEqual(
resp.context_data["object_list"], BDSProfile.expired_members()
)
@mock.patch("gestioncof.signals.messages")
def test_get_reset(self, _):
user = User.objects.create_user(username="tata")
url = reverse("bds:members.reset")
client = Client()
# Anonymous GET
resp = client.get(url)
self.assertRedirects(resp, login_url(next=url))
# Logged-in but unprivileged GET
client.force_login(user, backend="django.contrib.auth.backends.ModelBackend")
resp = client.get(url)
self.assertEquals(resp.status_code, 403)
# Burô user GET
give_bds_buro_permissions(user)
resp = client.get(url)
self.assertRedirects(resp, reverse("bds:members.expired"))
def test_expired_memberships(self):
# In september, there is no expired members
with mock.patch("bds.models.timezone.now", return_value=date(2022, 9, 1)):
self.assertQuerysetEqual(BDSProfile.expired_members(), [])
# In march, only bds-02's membership is expired
with mock.patch("django.utils.timezone.now", return_value=date(2023, 3, 1)):
self.assertQuerysetEqual(BDSProfile.expired_members(), [self.p_2])
# During summer, all memberships are expired
with mock.patch("django.utils.timezone.now", return_value=date(2023, 7, 1)):
self.assertQuerysetEqual(
BDSProfile.expired_members(),
[self.p_1, self.p_2, self.p_3],
ordered=False,
)
@mock.patch("gestioncof.signals.messages")
def test_reset_memberships(self, _):
url = reverse("bds:members.reset")
# Reset during S1 does nothig
with mock.patch("bds.models.timezone.now", return_value=date(2022, 9, 1)):
self.client.force_login(
self.admin, backend="django.contrib.auth.backends.ModelBackend"
)
resp = self.client.get(url)
self.assertRedirects(resp, reverse("bds:members.expired"))
self.assertQuerysetEqual(BDSProfile.expired_members(), [])
self.assertQuerysetEqual(
BDSProfile.objects.filter(is_member=True),
[self.p_1, self.p_2, self.p_3],
ordered=False,
)
# Reset in march
with mock.patch("django.utils.timezone.now", return_value=date(2023, 3, 1)):
self.client.force_login(
self.admin, backend="django.contrib.auth.backends.ModelBackend"
)
resp = self.client.get(url)
self.assertRedirects(resp, reverse("bds:members.expired"))
# After a reset we have no expired memberships
self.assertQuerysetEqual(BDSProfile.expired_members(), [])
# Test reset attributes
self.p_2.refresh_from_db()
self.assertEqual(
[self.p_2.is_member, self.p_2.mails_bds, self.p_2.cotisation_period],
[False, False, "NO"],
)
# Reset during summer
with mock.patch("django.utils.timezone.now", return_value=date(2023, 7, 1)):
# bds-02's membership wa already reset
self.assertQuerysetEqual(
BDSProfile.expired_members(), [self.p_1, self.p_3], ordered=False
)
self.client.force_login(
self.admin, backend="django.contrib.auth.backends.ModelBackend"
)
resp = self.client.get(url)
self.assertRedirects(resp, reverse("bds:members.expired"))
# After a reset we have no expired memberships
self.assertQuerysetEqual(BDSProfile.expired_members(), [])
# Test reset attributes
self.p_1.refresh_from_db()
self.assertEqual(
[self.p_1.is_member, self.p_1.mails_bds, self.p_1.cotisation_period],
[False, False, "NO"],
)
self.p_3.refresh_from_db()
self.assertEqual(
[self.p_3.is_member, self.p_3.mails_bds, self.p_3.cotisation_period],
[False, False, "NO"],
)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -205,8 +205,9 @@ MAIL_DATA = {
"REPLYTO": "cof@ens.fr", "REPLYTO": "cof@ens.fr",
}, },
"rappels": {"FROM": "Le BdA <bda@ens.fr>", "REPLYTO": "Le BdA <bda@ens.fr>"}, "rappels": {"FROM": "Le BdA <bda@ens.fr>", "REPLYTO": "Le BdA <bda@ens.fr>"},
"rappel_negatif": { "kfet": {
"FROM": "La K-Fêt <k-fet@ens.fr>", "FROM": "La K-Fêt <chefs-k-fet@ens.fr>",
"REPLYTO": "La K-Fêt <chefs-k-fet@ens.fr>",
}, },
"revente": { "revente": {
"FROM": "BdA-Revente <bda-revente@ens.fr>", "FROM": "BdA-Revente <bda-revente@ens.fr>",

View file

@ -35,7 +35,7 @@ app_dict = {
"events": "gestion/event_v2/", # the events module is still experimental ! "events": "gestion/event_v2/", # the events module is still experimental !
"authens": "gestion/authens/", "authens": "gestion/authens/",
} }
for (app_name, url_prefix) in app_dict.items(): for app_name, url_prefix in app_dict.items():
if app_name in settings.INSTALLED_APPS: if app_name in settings.INSTALLED_APPS:
urlpatterns += [path(url_prefix, include("{}.urls".format(app_name)))] urlpatterns += [path(url_prefix, include("{}.urls".format(app_name)))]

View file

@ -13,7 +13,6 @@ import gestioncof.cms.models
class Migration(migrations.Migration): class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [

View file

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

View file

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

View file

@ -6,7 +6,6 @@ from django.db import migrations
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("cofcms", "0003_directory_entry_optional_links"), ("cofcms", "0003_directory_entry_optional_links"),
] ]

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -5,7 +5,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("gestioncof", "0011_remove_cofprofile_num"), ("gestioncof", "0011_remove_cofprofile_num"),
("gestioncof", "0011_longer_clippers"), ("gestioncof", "0011_longer_clippers"),

View file

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

View file

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

View file

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

View file

@ -16,7 +16,6 @@ def null_clippers_to_empty(apps, schema_editor):
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("gestioncof", "0015_psql_choices_niveaux")] dependencies = [("gestioncof", "0015_psql_choices_niveaux")]
operations = [ operations = [

View file

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

View file

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

View file

@ -0,0 +1,19 @@
# Generated by Django 2.2.28 on 2023-05-22 09:01
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("gestioncof", "0018_petitscours_email"),
]
operations = [
migrations.AddField(
model_name="cofprofile",
name="date_adhesion",
field=models.DateField(
blank=True, null=True, verbose_name="Date d'adhésion"
),
),
]

View file

@ -50,6 +50,7 @@ class CofProfile(models.Model):
"Login clipper", max_length=32, blank=True, unique=True, null=True "Login clipper", max_length=32, blank=True, unique=True, null=True
) )
is_cof = models.BooleanField("Membre du COF", default=False) is_cof = models.BooleanField("Membre du COF", default=False)
date_adhesion = models.DateField("Date d'adhésion", blank=True, null=True)
phone = models.CharField("Téléphone", max_length=20, blank=True) phone = models.CharField("Téléphone", max_length=20, blank=True)
occupation = models.CharField( occupation = models.CharField(
_("Occupation"), _("Occupation"),

View file

@ -1,5 +1,5 @@
import uuid import uuid
from datetime import timedelta from datetime import date, timedelta
from django.contrib import messages from django.contrib import messages
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
@ -486,6 +486,7 @@ class ExportMembersViewTests(CSVResponseMixin, ViewTestCaseMixin, TestCase):
u1.last_name = "last" u1.last_name = "last"
u1.email = "user@mail.net" u1.email = "user@mail.net"
u1.save() u1.save()
u1.profile.date_adhesion = date(2023, 5, 22)
u1.profile.phone = "0123456789" u1.profile.phone = "0123456789"
u1.profile.departement = "Dept" u1.profile.departement = "Dept"
u1.profile.save() u1.profile.save()
@ -507,8 +508,9 @@ class ExportMembersViewTests(CSVResponseMixin, ViewTestCaseMixin, TestCase):
"1A", "1A",
"Dept", "Dept",
"normalien", "normalien",
"2023-05-22",
], ],
[str(u2.pk), "staff", "", "", "", "", "1A", "", "normalien"], [str(u2.pk), "staff", "", "", "", "", "1A", "", "normalien", "None"],
], ],
) )
@ -550,7 +552,6 @@ class ExportMegaOrgasViewTests(MegaHelperMixin, ViewTestCaseMixin, TestCase):
auth_forbidden = [None, "user", "member"] auth_forbidden = [None, "user", "member"]
def test(self): def test(self):
r = self.client.get(self.url) r = self.client.get(self.url)
self.assertEqual(r.status_code, 200) self.assertEqual(r.status_code, 200)

View file

@ -1,6 +1,6 @@
import csv import csv
import uuid import uuid
from datetime import timedelta from datetime import date, timedelta
from smtplib import SMTPRecipientsRefused from smtplib import SMTPRecipientsRefused
from urllib.parse import parse_qs, urlencode, urlparse, urlunparse from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
@ -86,6 +86,7 @@ class ResetComptes(BuroRequiredMixin, TemplateView):
nb_adherents = CofProfile.objects.filter(is_cof=True).count() nb_adherents = CofProfile.objects.filter(is_cof=True).count()
CofProfile.objects.update( CofProfile.objects.update(
is_cof=False, is_cof=False,
date_adhesion=None,
mailing_cof=False, mailing_cof=False,
mailing_bda=False, mailing_bda=False,
mailing_bda_revente=False, mailing_bda_revente=False,
@ -575,6 +576,9 @@ def registration(request):
profile = profile_form.save() profile = profile_form.save()
if profile.is_cof and not was_cof: if profile.is_cof and not was_cof:
notify_new_member(request, member) notify_new_member(request, member)
profile.date_adhesion = date.today()
profile.save()
# Enregistrement des inscriptions aux événements # Enregistrement des inscriptions aux événements
for form in event_formset: for form in event_formset:
if "status" not in form.cleaned_data: if "status" not in form.cleaned_data:
@ -715,6 +719,7 @@ def export_members(request):
profile.occupation, profile.occupation,
profile.departement, profile.departement,
profile.type_cotiz, profile.type_cotiz,
profile.date_adhesion,
] ]
writer.writerow([str(bit) for bit in bits]) writer.writerow([str(bit) for bit in bits])

View file

@ -5,7 +5,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("auth", "0006_require_contenttypes_0002"), ("auth", "0006_require_contenttypes_0002"),
# Following dependency allows using Account model to set up the kfet # Following dependency allows using Account model to set up the kfet

View file

@ -7,7 +7,6 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("auth", "0011_update_proxy_permissions"), ("auth", "0011_update_proxy_permissions"),
("kfetauth", "0001_initial"), ("kfetauth", "0001_initial"),

View file

@ -13,7 +13,6 @@ def existing_groups(apps, schema_editor):
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("kfetauth", "0002_kfetgroup_kfetpermission"), ("kfetauth", "0002_kfetgroup_kfetpermission"),
] ]

View file

@ -11,7 +11,6 @@ class Command(BaseCommand):
parser.add_argument("--file", default="kfet_wagtail_02_19") parser.add_argument("--file", default="kfet_wagtail_02_19")
def handle(self, *args, **options): def handle(self, *args, **options):
self.stdout.write("Import des données wagtail") self.stdout.write("Import des données wagtail")
# Nettoyage des données initiales posées par Wagtail dans la migration # Nettoyage des données initiales posées par Wagtail dans la migration

View file

@ -11,7 +11,6 @@ import kfet.cms.models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("wagtailcore", "0033_remove_golive_expiry_help_text"), ("wagtailcore", "0033_remove_golive_expiry_help_text"),
("wagtailimages", "0019_delete_filter"), ("wagtailimages", "0019_delete_filter"),

View file

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

View file

@ -97,7 +97,6 @@ class KFetStreamBlock(ChoicesStreamBlock):
class KFetPage(Page): class KFetPage(Page):
content = StreamField(KFetStreamBlock, verbose_name=_("Contenu")) content = StreamField(KFetStreamBlock, verbose_name=_("Contenu"))
# Layout fields # Layout fields

View file

@ -45,6 +45,47 @@ class DateTimeWidget(forms.DateTimeInput):
js = ("kfet/vendor/bootstrap/bootstrap-datetimepicker.min.js",) js = ("kfet/vendor/bootstrap/bootstrap-datetimepicker.min.js",)
class ContactForm(forms.Form):
from_email = forms.EmailField(
label="Adresse mail",
help_text="Si aucune adresse mail n'est renseignée, la soumission sera anonyme.",
required=False,
)
subject = forms.CharField(label="Objet", required=True)
message = forms.CharField(widget=forms.Textarea, required=True)
def clean_from_email(self):
return self.cleaned_data["from_email"] or "Anonyme <k-fet@ens.psl.eu>"
class DemandeSoireeForm(forms.Form):
HORAIRE_CHOICES = map(lambda s: (s, s), ("22h", "23h", "00h", "01h", "02h", "03h"))
SERVICE_CHOICES = (
("K-Fêt", "K-Fêt standard (L'équipe K-Fêt fait le service normal au bar)"),
("Kalô", "Type Kalô (Vous ramenez vos propres boissons et servez vous-mêmes)"),
)
nom = forms.CharField()
from_email = forms.EmailField(label="Adresse mail de contact")
contact_boum = forms.BooleanField(label="Contacter le Boum", required=False)
contact_pls = forms.BooleanField(label="Contacter PLS", required=False)
theme = forms.CharField(label="Thème de la soirée")
horaire_fin = forms.ChoiceField(label="Horaire de fin", choices=HORAIRE_CHOICES)
service = forms.ChoiceField(label="Mode de service", choices=SERVICE_CHOICES)
date = forms.CharField(label="Date souhaitée")
respo1 = forms.CharField(label="Nom de la personne respo n°1")
respo2 = forms.CharField(label="Nom de la personne respo n°2")
respo3 = forms.CharField(label="Nom de la personne respo n°3")
respo4 = forms.CharField(label="Nom de la personne respo n°4")
remarques = forms.CharField(
label="Remarques supplémentaires", widget=forms.Textarea
)
# ----- # -----
# Account forms # Account forms
# ----- # -----
@ -461,7 +502,6 @@ class AddcostForm(forms.Form):
class KFetConfigForm(ConfigForm): class KFetConfigForm(ConfigForm):
kfet_reduction_cof = forms.DecimalField( kfet_reduction_cof = forms.DecimalField(
label="Réduction COF", label="Réduction COF",
initial=Decimal("20"), initial=Decimal("20"),

View file

@ -41,7 +41,6 @@ class Command(BaseCommand):
) )
def handle(self, *args, **options): def handle(self, *args, **options):
self.stdout.write("Génération d'opérations") self.stdout.write("Génération d'opérations")
# Output log vars # Output log vars
@ -74,7 +73,6 @@ class Command(BaseCommand):
opegroup_list = [] opegroup_list = []
for i in range(num_ops): for i in range(num_ops):
# Randomly pick account # Randomly pick account
if random.random() > 0.25: if random.random() > 0.25:
account = random.choice(accounts) account = random.choice(accounts)
@ -174,7 +172,6 @@ class Command(BaseCommand):
at_list = [] at_list = []
for i in range(num_transfers): for i in range(num_transfers):
# Randomly pick time # Randomly pick time
at = now - timedelta(seconds=random.randint(0, time)) at = now - timedelta(seconds=random.randint(0, time))

View file

@ -63,7 +63,7 @@ class Command(MyBaseCommand):
created_accounts = 0 created_accounts = 0
team_accounts = 0 team_accounts = 0
for (profile, trigramme) in zip(gaulois, gaulois_trigramme): for profile, trigramme in zip(gaulois, gaulois_trigramme):
account, created = Account.objects.get_or_create( account, created = Account.objects.get_or_create(
trigramme=trigramme, trigramme=trigramme,
cofprofile=profile, cofprofile=profile,
@ -74,7 +74,7 @@ class Command(MyBaseCommand):
if profile.user.first_name == "Abraracourcix": if profile.user.first_name == "Abraracourcix":
profile.user.groups.add(group_chef) profile.user.groups.add(group_chef)
for (profile, trigramme) in zip(romains, romains_trigramme): for profile, trigramme in zip(romains, romains_trigramme):
account, created = Account.objects.get_or_create( account, created = Account.objects.get_or_create(
trigramme=trigramme, trigramme=trigramme,
cofprofile=profile, cofprofile=profile,

View file

@ -2,6 +2,7 @@
Gestion en ligne de commande des mails de rappel K-Fet. Gestion en ligne de commande des mails de rappel K-Fet.
""" """
import smtplib
from datetime import timedelta from datetime import timedelta
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
@ -10,6 +11,14 @@ from django.utils import timezone
from kfet.models import AccountNegative from kfet.models import AccountNegative
def send_mail(neg: AccountNegative, stdout) -> None:
try:
neg.send_rappel()
stdout.write(f"Mail de rappel pour {neg.account} envoyé avec succès.")
except smtplib.SMTPException:
stdout.write(f"Erreur lors de l'envoi du mail de rappel pour {neg.account}.")
class Command(BaseCommand): class Command(BaseCommand):
help = ( help = (
"Envoie un mail de rappel aux personnes en négatif.\n" "Envoie un mail de rappel aux personnes en négatif.\n"
@ -19,23 +28,30 @@ class Command(BaseCommand):
def handle(self, *args, **options): def handle(self, *args, **options):
now = timezone.now() now = timezone.now()
# Le premier mail est envoyé après 24h de négatif, puis toutes les semaines
first_delay = timedelta(days=1) first_delay = timedelta(days=1)
periodic_delay = timedelta(weeks=1) periodic_delay = timedelta(weeks=1)
accounts_first_mail = (
AccountNegative.objects.filter(start__lt=now - first_delay) # On n'envoie des mails qu'aux comptes qui ont un négatif vraiment actif
.filter(last_rappel__isnull=True) # et dont la balance est négative
.all() # On ignore les comptes gelés qui signinfient une adresse mail plus valide
account_negatives = AccountNegative.objects.filter(
account__balance__lt=0, account__is_frozen=False
).exclude(end__lte=now)
accounts_first_mail = account_negatives.filter(
start__lt=now - first_delay, last_rappel__isnull=True
) )
accounts_periodic_mail = ( accounts_periodic_mail = account_negatives.filter(
AccountNegative.objects.filter(last_rappel__isnull=False) last_rappel__lt=now - periodic_delay
.filter(last_rappel__lt=now - periodic_delay)
.all()
) )
for neg in accounts_first_mail: for neg in accounts_first_mail:
neg.send_rappel() send_mail(neg, self.stdout)
self.stdout.write(f"Mail de rappel pour {neg.account} envoyé avec succès.")
for neg in accounts_periodic_mail: for neg in accounts_periodic_mail:
neg.send_rappel() send_mail(neg, self.stdout)
self.stdout.write("Mail de rappel pour {neg.account} envoyé avec succès.")
if (not accounts_first_mail) and (not accounts_periodic_mail): if not (accounts_first_mail.exists() or accounts_periodic_mail.exists()):
self.stdout.write("Aucun mail à envoyer.") self.stdout.write("Aucun mail à envoyer.")

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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