Compare commits

..

6 commits

202 changed files with 439 additions and 1504 deletions

1
.envrc
View file

@ -1 +0,0 @@
use nix

4
.gitignore vendored
View file

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

View file

@ -21,66 +21,10 @@ Liste des changements notables dans GestioCOF depuis la version 0.1 (septembre
Uniquement un modèle simple de clubs avec des respos. Aucune gestion des Uniquement un modèle simple de clubs avec des respos. Aucune gestion des
adhérents ni des cotisations. adhérents ni des cotisations.
## TODO Prod ## Version 0.11
- Créer un compte hCaptcha (https://www.hcaptcha.com/), au COF, et remplacer les secrets associés
## Version ??? - ??/??/????
## Version 0.15.1 - 15/06/2023
### K-Fêt ### 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
## Version 0.12 - 17/06/2022
### K-Fêt
- Ajoute une exception à la limite d'historique pour les comptes `LIQ` et `#13`
- Répare le problème des étiquettes LIQ/Comptes K-Fêt inversées dans les stats des articles K-Fêt
## Version 0.11 - 26/10/2021
### COF
- Répare un problème de rendu sur le wagtail du COF
### K-Fêt
- Ajoute de mails de rappels pour les comptes en négatif
- La recherche de comptes sur K-Psul remarche normalement - La recherche de comptes sur K-Psul remarche normalement
- Le pointeur de la souris change de forme quand on survole un item d'autocomplétion - Le pointeur de la souris change de forme quand on survole un item d'autocomplétion
- Modification du gel de compte: - Modification du gel de compte:
@ -97,6 +41,10 @@ adhérents ni des cotisations.
## Version 0.10 - 18/04/2021 ## Version 0.10 - 18/04/2021
### TODO Prod
- Créer un compte hCaptcha (https://www.hcaptcha.com/), au COF, et remplacer les secrets associés
### K-Fêt ### K-Fêt
- On fait sauter la limite qui empêchait de vendre plus de 24 unités d'un item à - On fait sauter la limite qui empêchait de vendre plus de 24 unités d'un item à

View file

@ -211,6 +211,7 @@ 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,6 +2,7 @@ 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,6 +6,7 @@ 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,6 +35,7 @@ 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,6 +5,7 @@ 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,6 +5,7 @@ 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,6 +5,7 @@ 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,6 +18,7 @@ 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,6 +5,7 @@ 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,6 +5,7 @@ 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,6 +6,7 @@ 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,6 +21,7 @@ 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,6 +5,7 @@ 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,6 +5,7 @@ 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,6 +13,7 @@ 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,6 +6,7 @@ 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,6 +4,7 @@ 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,6 +29,7 @@ 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,6 +4,7 @@ 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,6 +4,7 @@ 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,6 +5,7 @@ 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

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

View file

@ -8,6 +8,7 @@ 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,6 +9,7 @@ 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,6 +4,7 @@ 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,6 +4,7 @@ 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,6 +4,7 @@ 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,6 +4,7 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("bds", "0005_remove_bdsprofile_certificate_file"), ("bds", "0005_remove_bdsprofile_certificate_file"),
] ]

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -5,6 +5,7 @@ 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,6 +6,7 @@ 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,6 +5,7 @@ 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

@ -7,8 +7,6 @@ Surcharge les settings définis dans common.py
import os import os
from datetime import timedelta from datetime import timedelta
from django.utils import timezone
from .common import * # NOQA from .common import * # NOQA
from .common import ( from .common import (
AUTHENTICATION_BACKENDS, AUTHENTICATION_BACKENDS,
@ -206,10 +204,6 @@ 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>"},
"kfet": {
"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>",
"REPLYTO": "BdA-Revente <bda-revente@ens.fr>", "REPLYTO": "BdA-Revente <bda-revente@ens.fr>",
@ -227,8 +221,3 @@ KFET_HISTORY_DATE_LIMIT = timedelta(days=7)
# Limite plus longue pour les chefs/trez # Limite plus longue pour les chefs/trez
# (qui ont la permission kfet.access_old_history) # (qui ont la permission kfet.access_old_history)
KFET_HISTORY_LONG_DATE_LIMIT = timedelta(days=30) KFET_HISTORY_LONG_DATE_LIMIT = timedelta(days=30)
# These accounts don't represent actual people and can be freely accessed
# Identification based on trigrammes
KFET_HISTORY_NO_DATE_LIMIT_TRIGRAMMES = ["LIQ", "#13"]
KFET_HISTORY_NO_DATE_LIMIT = timezone.datetime(1794, 10, 30) # AKA the distant past

View file

@ -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,6 +13,7 @@ import gestioncof.cms.models
class Migration(migrations.Migration): class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [

View file

@ -4,6 +4,7 @@ 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,6 +6,7 @@ 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,6 +6,7 @@ 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

@ -16,7 +16,7 @@
<link rel="stylesheet" type="text/css" href="{% static "fonts/SourceSansPro/sourceSansPro.css" %}"/> <link rel="stylesheet" type="text/css" href="{% static "fonts/SourceSansPro/sourceSansPro.css" %}"/>
<link rel="stylesheet" type="text/css" href="{% static "cofcms/css/screen.css" %}"/> <link rel="stylesheet" type="text/css" href="{% static "cofcms/css/screen.css" %}"/>
{% block extra_head %}{% endblock %} {% block extra_head %}{% endblock %}
<meta name="viewport" content="width=device-width, initial-scale=1.0; minimum-scale=1.0;"> <meta name="viewport" content="width=device-width, initial-scale=1.0; minimum-scale=1.0;">
</head> </head>
@ -32,27 +32,27 @@
<section class="bottom-menu"> <section class="bottom-menu">
<nav> <nav>
{% flat_menu "cof-nav-int" template="cofcms/base_nav.html" apply_active_classes=True %} {% flat_menu "cof-nav-int" template="cofcms/base_nav.html" apply_active_classes=True %}
{% get_current_language as curlang %}
{% get_current_language as curlang %} <div class="lang-select">
<div class="lang-select">
{% if curlang == 'en' %} {% if curlang == 'en' %}
{% language 'fr' %} {% language 'fr' %}
<a href="{% pageurl self %}" title="Français"><img src="{% static "cofcms/images/fr.png" %}"></a> <a href="{% pageurl self %}" title="Français"><img src="{% static "cofcms/images/fr.png" %}"></a>
{% endlanguage %} {% endlanguage %}
{% else %} {% else %}
{% language 'en' %} {% language 'en' %}
<a href="{% pageurl self %}" title="English"><img src="{% static "cofcms/images/en.png" %}"></a> <a href="{% pageurl self %}" title="English"><img src="{% static "cofcms/images/en.png" %}"></a>
{% endlanguage %} {% endlanguage %}
{% endif %} {% endif %}
</div> </div>
</nav> </nav>
</section> </section>
</header> </header>
<div class="container"> <div class="container">
{% block superaside %}{% endblock %} {% block superaside %}{% endblock %}
<div class="content"> <div class="content">
{% block content %}{% endblock %} {% block content %}{% endblock %}
</div> </div>

View file

@ -17,17 +17,17 @@
{% block content %} {% block content %}
<section class="intro"> <section class="intro">
<h1>{{ page.title }}</h1> <h1>{{ page.title }}</h1>
<div>{{ page.introduction|richtext }}</div> <div>{{ page.introduction|safe }}</div>
</section> </section>
<section class="actulist"> <section class="actulist">
{% if actus.has_previous %} {% if actus.has_previous %}
<a class="block prev-actus" href="?page={{ actus.previous_page_number }}{% for key,value in request.GET.items %}{% ifnotequal key 'page' %}&amp;{{ key }}={{ value }}{% endifnotequal %}{% endfor %}">{% trans "Actualités plus récentes" %}</a> <a class="block prev-actus" href="?page={{ actus.previous_page_number }}{% for key,value in request.GET.items %}{% ifnotequal key 'page' %}&amp;{{ key }}={{ value }}{% endifnotequal %}{% endfor %}">{% trans "Actualités plus récentes" %}</a>
{% endif %} {% endif %}
{% if actus.has_next %} {% if actus.has_next %}
<a class="block next-actus" href="?page={{ actus.next_page_number }}{% for key,value in request.GET.items %}{% ifnotequal key 'page' %}&amp;{{ key }}={{ value }}{% endifnotequal %}{% endfor %}">{% trans "Actualités plus anciennes" %}</a> <a class="block next-actus" href="?page={{ actus.next_page_number }}{% for key,value in request.GET.items %}{% ifnotequal key 'page' %}&amp;{{ key }}={{ value }}{% endifnotequal %}{% endfor %}">{% trans "Actualités plus anciennes" %}</a>
{% endif %} {% endif %}
{% for actu in page.actus %} {% for actu in page.actus %}
<article class="actu"> <article class="actu">
<div class="actu-image" {% if actu.image %}{% image actu.image fill-400x200 as img %}style="background-image:url('{{ img.url }}');"{% endif %}></div> <div class="actu-image" {% if actu.image %}{% image actu.image fill-400x200 as img %}style="background-image:url('{{ img.url }}');"{% endif %}></div>
@ -36,7 +36,7 @@
{% if actu.is_event %} {% if actu.is_event %}
<p><span class="actu-dates">{{ actu|dates|capfirst }}</span><br />{{ actu.chapo }}</p> <p><span class="actu-dates">{{ actu|dates|capfirst }}</span><br />{{ actu.chapo }}</p>
{% else %} {% else %}
{{ actu.body|richtext|truncatewords_html:15 }} {{ actu.body|safe|truncatewords_html:15 }}
{% endif %} {% endif %}
<a href="{% pageurl actu %}">{% trans "Lire plus" %} &gt;</a> <a href="{% pageurl actu %}">{% trans "Lire plus" %} &gt;</a>
</div> </div>
@ -44,10 +44,10 @@
{% endfor %} {% endfor %}
{% if actus.has_previous %} {% if actus.has_previous %}
<a class="block prev-actus" href="?page={{ actus.previous_page_number }}{% for key,value in request.GET.items %}{% ifnotequal key 'page' %}&amp;{{ key }}={{ value }}{% endifnotequal %}{% endfor %}">{% trans "Actualités plus récentes" %}</a> <a class="block prev-actus" href="?page={{ actus.previous_page_number }}{% for key,value in request.GET.items %}{% ifnotequal key 'page' %}&amp;{{ key }}={{ value }}{% endifnotequal %}{% endfor %}">{% trans "Actualités plus récentes" %}</a>
{% endif %} {% endif %}
{% if actus.has_next %} {% if actus.has_next %}
<a class="block next-actus" href="?page={{ actus.next_page_number }}{% for key,value in request.GET.items %}{% ifnotequal key 'page' %}&amp;{{ key }}={{ value }}{% endifnotequal %}{% endfor %}">{% trans "Actualités plus anciennes" %}</a> <a class="block next-actus" href="?page={{ actus.next_page_number }}{% for key,value in request.GET.items %}{% ifnotequal key 'page' %}&amp;{{ key }}={{ value }}{% endifnotequal %}{% endfor %}">{% trans "Actualités plus anciennes" %}</a>
{% endif %} {% endif %}
</section> </section>
{% endblock %} {% endblock %}

View file

@ -1,5 +1,5 @@
{% extends "cofcms/base.html" %} {% extends "cofcms/base.html" %}
{% load wagtailcore_tags wagtailimages_tags cofcms_tags i18n %} {% load wagtailimages_tags cofcms_tags i18n %}
{% block content %} {% block content %}
<section class="intro"> <section class="intro">
@ -11,7 +11,7 @@
<section class="pagecontent"> <section class="pagecontent">
<div class="image">{% image page.image width-700 %}</div> <div class="image">{% image page.image width-700 %}</div>
<article> <article>
{{ page.body|richtext }} {{ page.body|safe }}
</article> </article>
</section> </section>
{% endblock %} {% endblock %}

View file

@ -1,5 +1,5 @@
{% extends "cofcms/base_aside.html" %} {% extends "cofcms/base_aside.html" %}
{% load wagtailcore_tags wagtailimages_tags cofcms_tags static i18n %} {% load wagtailimages_tags cofcms_tags static i18n %}
{% block extra_head %} {% block extra_head %}
{{ block.super }} {{ block.super }}
@ -18,7 +18,7 @@
{% block content %} {% block content %}
<section class="intro"> <section class="intro">
<h1>{{ page.title }}</h1> <h1>{{ page.title }}</h1>
<div>{{ page.introduction|richtext }}</div> <div>{{ page.introduction|safe }}</div>
</section> </section>
<section class="directory"> <section class="directory">
@ -28,7 +28,7 @@
<div class="entry-image">{% image entry.image width-150 class="entry-img" %}</div> <div class="entry-image">{% image entry.image width-150 class="entry-img" %}</div>
{% endif %} {% endif %}
<h2>{{ entry.title }}</h2> <h2>{{ entry.title }}</h2>
<div class="desc">{{ entry.body|richtext }}</div> <div class="desc">{{ entry.body|safe }}</div>
{% if entry.links %} {% if entry.links %}
<ul class="links"> <ul class="links">
{% for block in entry.links %} {% for block in entry.links %}

View file

@ -1,10 +1,10 @@
{% extends "cofcms/base.html" %} {% extends "cofcms/base.html" %}
{% load wagtailcore_tags wagtailimages_tags cofcms_tags %} {% load wagtailimages_tags cofcms_tags %}
{% block content %} {% block content %}
<section class="intro"> <section class="intro">
<h1>{{ page.title }}</h1> <h1>{{ page.title }}</h1>
<div>{{ page.introduction|richtext }}</div> <div>{{ page.introduction|safe }}</div>
</section> </section>
<section class="pagecontent"> <section class="pagecontent">
@ -13,7 +13,7 @@
<h2>{{ block.value }}</h2> <h2>{{ block.value }}</h2>
{% elif block.block_type == "paragraph" %} {% elif block.block_type == "paragraph" %}
<article class="paragraph"> <article class="paragraph">
{{ block.value|richtext }} {{ block.value|safe }}
</article> </article>
{% elif block.block_type == "image" %} {% elif block.block_type == "image" %}
<div class="image"> <div class="image">

View file

@ -18,7 +18,7 @@
{% block content %} {% block content %}
<section class="intro"> <section class="intro">
<h1>{{ page.title }}</h1> <h1>{{ page.title }}</h1>
<div>{{ page.introduction|richtext }}</div> <div>{{ page.introduction|safe }}</div>
</section> </section>
<section class="actuhome"> <section class="actuhome">
@ -31,7 +31,7 @@
{% if actu.is_event %} {% if actu.is_event %}
<span class="actu-minical">{% mini_calendar actu %}</span><span class="actu-dates">{{ actu|dates }}</span> <span class="actu-minical">{% mini_calendar actu %}</span><span class="actu-dates">{{ actu|dates }}</span>
{% else %} {% else %}
{{ actu.body|richtext|truncatewords_html:10 }} {{ actu.body|safe|truncatewords_html:10 }}
{% endif %} {% endif %}
</div> </div>
<a href="{% pageurl actu %}" class="actu-overlay"></a> <a href="{% pageurl actu %}" class="actu-overlay"></a>

View file

@ -6,6 +6,7 @@ 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,6 +5,7 @@ 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,6 +5,7 @@ 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,6 +25,7 @@ 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,6 +5,7 @@ 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,6 +6,7 @@ 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,6 +6,7 @@ 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,6 +10,7 @@ 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,6 +5,7 @@ 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,6 +4,7 @@ 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,6 +5,7 @@ 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,6 +5,7 @@ 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,6 +5,7 @@ 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,6 +5,7 @@ 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,6 +6,7 @@ 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,6 +6,7 @@ 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,6 +16,7 @@ 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,6 +5,7 @@ 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,6 +4,7 @@ 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

@ -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

@ -50,7 +50,6 @@ 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 date, timedelta from datetime import 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
@ -484,7 +484,6 @@ 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()
@ -506,9 +505,8 @@ class ExportMembersViewTests(CSVResponseMixin, ViewTestCaseMixin, TestCase):
"1A", "1A",
"Dept", "Dept",
"normalien", "normalien",
"2023-05-22",
], ],
[str(u2.pk), "staff", "", "", "", "", "1A", "", "normalien", "None"], [str(u2.pk), "staff", "", "", "", "", "1A", "", "normalien"],
], ],
) )
@ -550,6 +548,7 @@ 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 date, timedelta from datetime import 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,7 +86,6 @@ 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,
@ -576,9 +575,6 @@ 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:
@ -719,7 +715,6 @@ 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,6 +5,7 @@ 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,6 +7,7 @@ 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,6 +13,7 @@ def existing_groups(apps, schema_editor):
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("kfetauth", "0002_kfetgroup_kfetpermission"), ("kfetauth", "0002_kfetgroup_kfetpermission"),
] ]

File diff suppressed because one or more lines are too long

View file

@ -11,6 +11,7 @@ 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,6 +11,7 @@ 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,6 +5,7 @@ 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,6 +97,7 @@ 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,47 +45,6 @@ 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
# ----- # -----
@ -502,6 +461,7 @@ 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,6 +41,7 @@ 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
@ -73,6 +74,7 @@ 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)
@ -172,6 +174,7 @@ 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

@ -1,57 +0,0 @@
"""
Gestion en ligne de commande des mails de rappel K-Fet.
"""
import smtplib
from datetime import timedelta
from django.core.management.base import BaseCommand
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"
"Envoie un mail au bout de 24h, puis un mail par semaine."
)
leave_locale_alone = True
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_periodic_mail = account_negatives.filter(
last_rappel__lt=now - periodic_delay
)
for neg in accounts_first_mail:
send_mail(neg, self.stdout)
for neg in accounts_periodic_mail:
send_mail(neg, self.stdout)
if not (accounts_first_mail.exists() or accounts_periodic_mail.exists()):
self.stdout.write("Aucun mail à envoyer.")

View file

@ -9,6 +9,7 @@ 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,6 +7,7 @@ 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,6 +7,7 @@ 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,6 +5,7 @@ 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,6 +5,7 @@ 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,6 +5,7 @@ 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,6 +5,7 @@ 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,6 +6,7 @@ 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,6 +5,7 @@ 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 = [

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