Compare commits

..

40 commits

Author SHA1 Message Date
b4669847de Update tests for BDS 2022-10-03 18:25:51 +02:00
157165a7c9 dev: update requirements and directly read the files 2022-10-03 15:47:31 +02:00
7968a70236 kfet/open: Add comment to test 2022-10-03 13:24:00 +02:00
74241e22cc dev: set explicitely DJANGO_SETTINGS_MODULE 2022-10-03 13:19:52 +02:00
192b9d1e15 kfet: remove redundant static tag 2022-10-03 13:10:20 +02:00
e2d7bba816 dev: update requirements 2022-10-03 13:08:01 +02:00
d756cb1f5b Remove useless migrations 2022-10-03 10:58:52 +02:00
ef68e469b5 Update django-hCaptcha 2022-10-03 10:58:52 +02:00
2b2fcb8d52 assertDictContainsSubset is deprecated 2022-10-03 10:58:52 +02:00
0b03a42acc Explicitely set transform=repr in assertQuerysetEquals 2022-10-03 10:58:52 +02:00
75bf5c9b7d assertEquals is deprecated 2022-10-03 10:58:52 +02:00
e51951b1f2 Use AutoField instead of BigAutoField 2022-10-03 10:58:52 +02:00
29726486e0 url -> re_path 2022-10-03 10:58:52 +02:00
6be970b230 Replace unique_together by UniqueConstraint 2022-10-03 10:58:52 +02:00
1e5d30737f Update changelog 2022-10-03 10:58:46 +02:00
8d655f8b2f cof has been renamed to gestioasso 2022-10-03 10:55:33 +02:00
14eb740179 Fix typo 2022-10-03 10:55:33 +02:00
48dd2571bc Only run kf tests in sequential mode (to fix issues with channels) 2022-10-03 10:55:33 +02:00
16f500838f Try not running tests in parallel 2022-10-03 10:55:33 +02:00
67e921a497 Try to flush old messages in tests 2022-10-03 10:55:33 +02:00
9e1e13d360 Update kfet.open tests 2022-10-03 10:55:33 +02:00
aeb90f729b Remove default_app_config 2022-10-03 10:55:33 +02:00
6e4895fb16 Update django-djconfig 2022-10-03 10:55:33 +02:00
b512ba2d58 Change backend name as the old one is deprecated 2022-10-03 10:55:33 +02:00
8a1c39e43b ugettext -> gettext 2022-10-03 10:55:33 +02:00
95e658d05b Update redis, and implement a custom channel layer to send datetime/decimal objects 2022-10-03 10:55:33 +02:00
9a7deb5e2a Fix kfet.ope tests 2022-10-03 10:55:33 +02:00
c9158c8e13 Fix kpsul tests 2022-10-03 10:55:33 +02:00
5a28aab7cb Simplify group_send for kpsul 2022-10-03 10:55:33 +02:00
2b712dd05d Channels 3 2022-10-03 10:55:33 +02:00
1ae5c80f76 Add default django asgi handler 2022-10-03 10:55:33 +02:00
a01e11e45b Fix app import 2022-10-03 10:55:33 +02:00
3411bc8a00 keyOrder is deprecated, using a list in Meta gives the correct order 2022-10-03 10:55:33 +02:00
65ea5d21b2 Update django-redis-cache and fix vagrant setup 2022-10-03 10:55:33 +02:00
6db3ed604b Update django version 2022-10-03 10:55:33 +02:00
d120a2bb62 Update base consumers 2022-10-03 10:55:33 +02:00
e1d942a7ca Add default http router 2022-10-03 10:55:33 +02:00
654848c4f0 Update daphne version 2022-10-03 10:55:33 +02:00
f026e0b5e3 Update to django channels 2 2022-10-03 10:55:33 +02:00
965ba074b6 Fix vagrant setup w/ daphne 2022-10-03 10:55:33 +02:00
196 changed files with 627 additions and 1608 deletions

View file

@ -1 +0,0 @@
0x0000000000000000000000000000000000000000

View file

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

View file

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

View file

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

3
.gitignore vendored
View file

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

View file

@ -30,40 +30,6 @@ adhérents ni des cotisations.
## 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

View file

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

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -5,6 +5,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("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)
# 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:
@ -293,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] = []

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,3 +1,4 @@
from datetime import date
from unittest import mock
from django.conf import settings
@ -6,6 +7,8 @@ from django.contrib.auth.models import Permission
from django.test import Client, TestCase
from django.urls import reverse, reverse_lazy
from bds.models import BDSProfile
User = get_user_model()
@ -24,7 +27,7 @@ def login_url(next=None):
class TestHomeView(TestCase):
@mock.patch("gestioncof.signals.messages")
def test_get(self, mock_messages):
def test_get(self, _):
user = User.objects.create_user(username="random_user")
give_bds_buro_permissions(user)
self.client.force_login(
@ -36,7 +39,7 @@ class TestHomeView(TestCase):
class TestRegistrationView(TestCase):
@mock.patch("gestioncof.signals.messages")
def test_get_autocomplete(self, mock_messages):
def test_get_autocomplete(self, _):
user = User.objects.create_user(username="toto")
url = reverse("bds:autocomplete") + "?q=foo"
client = Client()
@ -56,7 +59,7 @@ class TestRegistrationView(TestCase):
self.assertEqual(resp.status_code, 200)
@mock.patch("gestioncof.signals.messages")
def test_get(self, mock_messages):
def test_get(self, _):
user = User.objects.create_user(username="toto")
url = reverse("bds:user.update", args=(user.id,))
client = Client()
@ -74,3 +77,174 @@ class TestRegistrationView(TestCase):
give_bds_buro_permissions(user)
resp = client.get(url)
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,6 +5,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [migrations.swappable_dependency(settings.AUTH_USER_MODEL)]

View file

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

View file

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

View file

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

View file

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

View file

@ -67,8 +67,8 @@ INSTALLED_APPS = (
"wagtail.images",
"wagtail.search",
"wagtail.admin",
"wagtail",
# "wagtail.contrib.modeladmin",
"wagtail.core",
"wagtail.contrib.modeladmin",
"wagtail.contrib.routable_page",
"wagtailmenus",
"modelcluster",
@ -205,9 +205,8 @@ MAIL_DATA = {
"REPLYTO": "cof@ens.fr",
},
"rappels": {"FROM": "Le BdA <bda@ens.fr>", "REPLYTO": "Le BdA <bda@ens.fr>"},
"kfet": {
"FROM": "La K-Fêt <chefs-k-fet@ens.fr>",
"REPLYTO": "La K-Fêt <chefs-k-fet@ens.fr>",
"rappel_negatif": {
"FROM": "La K-Fêt <k-fet@ens.fr>",
},
"revente": {
"FROM": "BdA-Revente <bda-revente@ens.fr>",

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,19 +0,0 @@
# 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

@ -1,13 +0,0 @@
# Generated by Django 3.2.25 on 2024-12-18 21:40
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("gestioncof", "0019_auto_20220630_1241"),
("gestioncof", "0019_cofprofile_date_adhesion"),
]
operations = []

View file

@ -50,7 +50,6 @@ class CofProfile(models.Model):
"Login clipper", max_length=32, blank=True, unique=True, null=True
)
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)
occupation = models.CharField(
_("Occupation"),

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
from django.templatetags.static import static
from django.utils.html import format_html
from wagtail import hooks
from wagtail.core import hooks
@hooks.register("insert_editor_css")

View file

@ -1,7 +1,7 @@
from django.contrib.auth.models import Group
from django.core.management import call_command
from django.core.management.base import BaseCommand
from wagtail.models import Page, Site
from wagtail.core.models import Page, Site
class Command(BaseCommand):
@ -11,6 +11,7 @@ class Command(BaseCommand):
parser.add_argument("--file", default="kfet_wagtail_02_19")
def handle(self, *args, **options):
self.stdout.write("Import des données wagtail")
# Nettoyage des données initiales posées par Wagtail dans la migration

View file

@ -2,8 +2,8 @@
from __future__ import unicode_literals
import django.db.models.deletion
import wagtail.blocks
import wagtail.fields
import wagtail.core.blocks
import wagtail.core.fields
import wagtail.snippets.blocks
from django.db import migrations, models
@ -11,6 +11,7 @@ import kfet.cms.models
class Migration(migrations.Migration):
dependencies = [
("wagtailcore", "0033_remove_golive_expiry_help_text"),
("wagtailimages", "0019_delete_filter"),
@ -41,20 +42,20 @@ class Migration(migrations.Migration):
),
(
"content",
wagtail.fields.StreamField(
wagtail.core.fields.StreamField(
(
(
"rich",
wagtail.blocks.RichTextBlock(label="Éditeur"),
wagtail.core.blocks.RichTextBlock(label="Éditeur"),
),
("carte", kfet.cms.models.MenuBlock()),
(
"group_team",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
(
(
"show_only",
wagtail.blocks.IntegerBlock(
wagtail.core.blocks.IntegerBlock(
help_text="Nombre initial de membres affichés. Laisser vide pour tou-te-s les afficher.", # noqa
required=False,
label="Montrer seulement",
@ -62,7 +63,7 @@ class Migration(migrations.Migration):
),
(
"members",
wagtail.blocks.ListBlock(
wagtail.core.blocks.ListBlock(
wagtail.snippets.blocks.SnippetChooserBlock( # noqa
kfet.cms.models.MemberTeam
),
@ -75,22 +76,22 @@ class Migration(migrations.Migration):
),
(
"group",
wagtail.blocks.StreamBlock(
wagtail.core.blocks.StreamBlock(
(
(
"rich",
wagtail.blocks.RichTextBlock(
wagtail.core.blocks.RichTextBlock(
label="Éditeur"
),
),
("carte", kfet.cms.models.MenuBlock()),
(
"group_team",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
(
(
"show_only",
wagtail.blocks.IntegerBlock( # noqa
wagtail.core.blocks.IntegerBlock( # noqa
help_text="Nombre initial de membres affichés. Laisser vide pour tou-te-s les afficher.", # noqa
required=False,
label="Montrer seulement",
@ -98,7 +99,7 @@ class Migration(migrations.Migration):
),
(
"members",
wagtail.blocks.ListBlock(
wagtail.core.blocks.ListBlock(
wagtail.snippets.blocks.SnippetChooserBlock( # noqa
kfet.cms.models.MemberTeam # noqa
),

View file

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

View file

@ -1,90 +0,0 @@
# Generated by Django 4.2.17 on 2024-12-19 12:27
import wagtail.blocks
import wagtail.fields
import wagtail.snippets.blocks
from django.db import migrations
import kfet.cms.models
class Migration(migrations.Migration):
dependencies = [
("kfetcms", "0002_alter_kfetpage_colcount"),
]
operations = [
migrations.AlterField(
model_name="kfetpage",
name="content",
field=wagtail.fields.StreamField(
[
("rich", wagtail.blocks.RichTextBlock(label="Éditeur")),
("carte", kfet.cms.models.MenuBlock()),
(
"group_team",
wagtail.blocks.StructBlock(
[
(
"show_only",
wagtail.blocks.IntegerBlock(
help_text="Nombre initial de membres affichés. Laisser vide pour tou-te-s les afficher.",
label="Montrer seulement",
required=False,
),
),
(
"members",
wagtail.blocks.ListBlock(
wagtail.snippets.blocks.SnippetChooserBlock(
kfet.cms.models.MemberTeam
),
form_classname="team-group",
label="K-Fêt-eux-ses",
),
),
]
),
),
(
"group",
wagtail.blocks.StreamBlock(
[
("rich", wagtail.blocks.RichTextBlock(label="Éditeur")),
("carte", kfet.cms.models.MenuBlock()),
(
"group_team",
wagtail.blocks.StructBlock(
[
(
"show_only",
wagtail.blocks.IntegerBlock(
help_text="Nombre initial de membres affichés. Laisser vide pour tou-te-s les afficher.",
label="Montrer seulement",
required=False,
),
),
(
"members",
wagtail.blocks.ListBlock(
wagtail.snippets.blocks.SnippetChooserBlock(
kfet.cms.models.MemberTeam
),
form_classname="team-group",
label="K-Fêt-eux-ses",
),
),
]
),
),
],
label="Contenu groupé",
),
),
],
use_json_field=True,
verbose_name="Contenu",
),
),
]

View file

@ -1,9 +1,15 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from wagtail import blocks
from wagtail.admin.panels import FieldPanel, FieldRowPanel, MultiFieldPanel
from wagtail.fields import StreamField
from wagtail.models import Page
from wagtail.admin.edit_handlers import (
FieldPanel,
FieldRowPanel,
MultiFieldPanel,
StreamFieldPanel,
)
from wagtail.core import blocks
from wagtail.core.fields import StreamField
from wagtail.core.models import Page
from wagtail.images.edit_handlers import ImageChooserPanel
from wagtail.snippets.blocks import SnippetChooserBlock
from wagtail.snippets.models import register_snippet
@ -37,7 +43,7 @@ class MemberTeam(models.Model):
FieldPanel("first_name"),
FieldPanel("last_name"),
FieldPanel("nick_name"),
FieldPanel("photo"),
ImageChooserPanel("photo"),
]
def __str__(self):
@ -91,9 +97,8 @@ class KFetStreamBlock(ChoicesStreamBlock):
class KFetPage(Page):
content = StreamField(
KFetStreamBlock, verbose_name=_("Contenu"), use_json_field=True
)
content = StreamField(KFetStreamBlock, verbose_name=_("Contenu"))
# Layout fields
@ -131,7 +136,7 @@ class KFetPage(Page):
# Panels
content_panels = Page.content_panels + [FieldPanel("content")]
content_panels = Page.content_panels + [StreamFieldPanel("content")]
layout_panel = [
FieldPanel("no_header"),

View file

@ -45,47 +45,6 @@ class DateTimeWidget(forms.DateTimeInput):
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
# -----
@ -93,7 +52,7 @@ class DemandeSoireeForm(forms.Form):
def default_promo():
now = date.today()
return now.month <= 7 and now.year - 1 or now.year
return now.month <= 8 and now.year - 1 or now.year
def get_promo_choices():
@ -502,6 +461,7 @@ class AddcostForm(forms.Form):
class KFetConfigForm(ConfigForm):
kfet_reduction_cof = forms.DecimalField(
label="Réduction COF",
initial=Decimal("20"),

View file

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

View file

@ -63,7 +63,7 @@ class Command(MyBaseCommand):
created_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(
trigramme=trigramme,
cofprofile=profile,
@ -74,7 +74,7 @@ class Command(MyBaseCommand):
if profile.user.first_name == "Abraracourcix":
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(
trigramme=trigramme,
cofprofile=profile,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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