Merge branch 'master' into 'Production'
Master See merge request klub-dev-ens/gestioCOF!527
This commit is contained in:
commit
7460ca591f
9 changed files with 92 additions and 21 deletions
|
@ -27,6 +27,13 @@ adhérents ni des cotisations.
|
||||||
|
|
||||||
## Version ??? - ??/??/????
|
## Version ??? - ??/??/????
|
||||||
|
|
||||||
|
## Version 0.15.1 - 15/06/2023
|
||||||
|
|
||||||
|
### K-Fêt
|
||||||
|
|
||||||
|
- Rattrape les erreurs d'envoi de mail de négatif
|
||||||
|
- Utilise l'adresse chefs pour les envois de négatifs
|
||||||
|
|
||||||
## Version 0.15 - 22/05/2023
|
## Version 0.15 - 22/05/2023
|
||||||
|
|
||||||
### K-Fêt
|
### K-Fêt
|
||||||
|
|
|
@ -207,7 +207,8 @@ MAIL_DATA = {
|
||||||
},
|
},
|
||||||
"rappels": {"FROM": "Le BdA <bda@ens.fr>", "REPLYTO": "Le BdA <bda@ens.fr>"},
|
"rappels": {"FROM": "Le BdA <bda@ens.fr>", "REPLYTO": "Le BdA <bda@ens.fr>"},
|
||||||
"rappel_negatif": {
|
"rappel_negatif": {
|
||||||
"FROM": "La K-Fêt <k-fet@ens.fr>",
|
"FROM": "La K-Fêt <chefs-k-fet@ens.fr>",
|
||||||
|
"REPLYTO": "La K-Fêt <chefs-k-fet@ens.fr>",
|
||||||
},
|
},
|
||||||
"revente": {
|
"revente": {
|
||||||
"FROM": "BdA-Revente <bda-revente@ens.fr>",
|
"FROM": "BdA-Revente <bda-revente@ens.fr>",
|
||||||
|
|
19
gestioncof/migrations/0019_cofprofile_date_adhesion.py
Normal file
19
gestioncof/migrations/0019_cofprofile_date_adhesion.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# Generated by Django 2.2.28 on 2023-05-22 09:01
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("gestioncof", "0018_petitscours_email"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="cofprofile",
|
||||||
|
name="date_adhesion",
|
||||||
|
field=models.DateField(
|
||||||
|
blank=True, null=True, verbose_name="Date d'adhésion"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -50,6 +50,7 @@ class CofProfile(models.Model):
|
||||||
"Login clipper", max_length=32, blank=True, unique=True, null=True
|
"Login clipper", max_length=32, blank=True, unique=True, null=True
|
||||||
)
|
)
|
||||||
is_cof = models.BooleanField("Membre du COF", default=False)
|
is_cof = models.BooleanField("Membre du COF", default=False)
|
||||||
|
date_adhesion = models.DateField("Date d'adhésion", blank=True, null=True)
|
||||||
phone = models.CharField("Téléphone", max_length=20, blank=True)
|
phone = models.CharField("Téléphone", max_length=20, blank=True)
|
||||||
occupation = models.CharField(
|
occupation = models.CharField(
|
||||||
_("Occupation"),
|
_("Occupation"),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import uuid
|
import uuid
|
||||||
from datetime import timedelta
|
from datetime import date, timedelta
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
@ -484,6 +484,7 @@ class ExportMembersViewTests(CSVResponseMixin, ViewTestCaseMixin, TestCase):
|
||||||
u1.last_name = "last"
|
u1.last_name = "last"
|
||||||
u1.email = "user@mail.net"
|
u1.email = "user@mail.net"
|
||||||
u1.save()
|
u1.save()
|
||||||
|
u1.profile.date_adhesion = date(2023, 5, 22)
|
||||||
u1.profile.phone = "0123456789"
|
u1.profile.phone = "0123456789"
|
||||||
u1.profile.departement = "Dept"
|
u1.profile.departement = "Dept"
|
||||||
u1.profile.save()
|
u1.profile.save()
|
||||||
|
@ -505,8 +506,9 @@ class ExportMembersViewTests(CSVResponseMixin, ViewTestCaseMixin, TestCase):
|
||||||
"1A",
|
"1A",
|
||||||
"Dept",
|
"Dept",
|
||||||
"normalien",
|
"normalien",
|
||||||
|
"2023-05-22",
|
||||||
],
|
],
|
||||||
[str(u2.pk), "staff", "", "", "", "", "1A", "", "normalien"],
|
[str(u2.pk), "staff", "", "", "", "", "1A", "", "normalien", "None"],
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import csv
|
import csv
|
||||||
import uuid
|
import uuid
|
||||||
from datetime import timedelta
|
from datetime import date, timedelta
|
||||||
from smtplib import SMTPRecipientsRefused
|
from smtplib import SMTPRecipientsRefused
|
||||||
from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
|
from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
|
||||||
|
|
||||||
|
@ -86,6 +86,7 @@ class ResetComptes(BuroRequiredMixin, TemplateView):
|
||||||
nb_adherents = CofProfile.objects.filter(is_cof=True).count()
|
nb_adherents = CofProfile.objects.filter(is_cof=True).count()
|
||||||
CofProfile.objects.update(
|
CofProfile.objects.update(
|
||||||
is_cof=False,
|
is_cof=False,
|
||||||
|
date_adhesion=None,
|
||||||
mailing_cof=False,
|
mailing_cof=False,
|
||||||
mailing_bda=False,
|
mailing_bda=False,
|
||||||
mailing_bda_revente=False,
|
mailing_bda_revente=False,
|
||||||
|
@ -575,6 +576,9 @@ def registration(request):
|
||||||
profile = profile_form.save()
|
profile = profile_form.save()
|
||||||
if profile.is_cof and not was_cof:
|
if profile.is_cof and not was_cof:
|
||||||
notify_new_member(request, member)
|
notify_new_member(request, member)
|
||||||
|
profile.date_adhesion = date.today()
|
||||||
|
profile.save()
|
||||||
|
|
||||||
# Enregistrement des inscriptions aux événements
|
# Enregistrement des inscriptions aux événements
|
||||||
for form in event_formset:
|
for form in event_formset:
|
||||||
if "status" not in form.cleaned_data:
|
if "status" not in form.cleaned_data:
|
||||||
|
@ -715,6 +719,7 @@ def export_members(request):
|
||||||
profile.occupation,
|
profile.occupation,
|
||||||
profile.departement,
|
profile.departement,
|
||||||
profile.type_cotiz,
|
profile.type_cotiz,
|
||||||
|
profile.date_adhesion,
|
||||||
]
|
]
|
||||||
writer.writerow([str(bit) for bit in bits])
|
writer.writerow([str(bit) for bit in bits])
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
Gestion en ligne de commande des mails de rappel K-Fet.
|
Gestion en ligne de commande des mails de rappel K-Fet.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import smtplib
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
|
@ -10,6 +11,14 @@ from django.utils import timezone
|
||||||
from kfet.models import AccountNegative
|
from kfet.models import AccountNegative
|
||||||
|
|
||||||
|
|
||||||
|
def send_mail(neg: AccountNegative, stdout) -> None:
|
||||||
|
try:
|
||||||
|
neg.send_rappel()
|
||||||
|
stdout.write(f"Mail de rappel pour {neg.account} envoyé avec succès.")
|
||||||
|
except smtplib.SMTPException:
|
||||||
|
stdout.write(f"Erreur lors de l'envoi du mail de rappel pour {neg.account}.")
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = (
|
help = (
|
||||||
"Envoie un mail de rappel aux personnes en négatif.\n"
|
"Envoie un mail de rappel aux personnes en négatif.\n"
|
||||||
|
@ -39,12 +48,10 @@ class Command(BaseCommand):
|
||||||
)
|
)
|
||||||
|
|
||||||
for neg in accounts_first_mail:
|
for neg in accounts_first_mail:
|
||||||
neg.send_rappel()
|
send_mail(neg, self.stdout)
|
||||||
self.stdout.write(f"Mail de rappel pour {neg.account} envoyé avec succès.")
|
|
||||||
|
|
||||||
for neg in accounts_periodic_mail:
|
for neg in accounts_periodic_mail:
|
||||||
neg.send_rappel()
|
send_mail(neg, self.stdout)
|
||||||
self.stdout.write(f"Mail de rappel pour {neg.account} envoyé avec succès.")
|
|
||||||
|
|
||||||
if not (accounts_first_mail.exists() or accounts_periodic_mail.exists()):
|
if not (accounts_first_mail.exists() or accounts_periodic_mail.exists()):
|
||||||
self.stdout.write("Aucun mail à envoyer.")
|
self.stdout.write("Aucun mail à envoyer.")
|
||||||
|
|
|
@ -2,7 +2,7 @@ import re
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.core.mail import send_mail
|
from django.core.mail import EmailMessage
|
||||||
from django.core.validators import RegexValidator
|
from django.core.validators import RegexValidator
|
||||||
from django.db import models, transaction
|
from django.db import models, transaction
|
||||||
from django.db.models import F
|
from django.db.models import F
|
||||||
|
@ -298,10 +298,11 @@ class AccountNegative(models.Model):
|
||||||
"""
|
"""
|
||||||
Envoie un mail de rappel signalant que la personne est en négatif.
|
Envoie un mail de rappel signalant que la personne est en négatif.
|
||||||
"""
|
"""
|
||||||
# On envoie le mail
|
mail_data = settings.MAIL_DATA["rappel_negatif"]
|
||||||
send_mail(
|
|
||||||
"Compte K-Psul négatif",
|
email = EmailMessage(
|
||||||
loader.render_to_string(
|
subject="Compte K-Psul négatif",
|
||||||
|
body=loader.render_to_string(
|
||||||
"kfet/mails/rappel.txt",
|
"kfet/mails/rappel.txt",
|
||||||
context={
|
context={
|
||||||
"account": self.account,
|
"account": self.account,
|
||||||
|
@ -309,9 +310,14 @@ class AccountNegative(models.Model):
|
||||||
"start_date": self.start,
|
"start_date": self.start,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
settings.MAIL_DATA["rappel_negatif"]["FROM"],
|
from_email=mail_data["FROM"],
|
||||||
[self.account.email],
|
to=[self.account.email],
|
||||||
|
reply_to=[mail_data["REPLYTO"]],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# On envoie le mail
|
||||||
|
email.send()
|
||||||
|
|
||||||
# On enregistre le fait que l'envoi a bien eu lieu
|
# On enregistre le fait que l'envoi a bien eu lieu
|
||||||
self.last_rappel = timezone.now()
|
self.last_rappel = timezone.now()
|
||||||
self.save()
|
self.save()
|
||||||
|
|
35
shell.nix
35
shell.nix
|
@ -1,5 +1,29 @@
|
||||||
{ pkgs ? import <nixpkgs> { }, ... }:
|
{ pkgs ? import <nixpkgs> { }, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
python = pkgs.python38;
|
||||||
|
|
||||||
|
django-types = python.pkgs.buildPythonPackage rec {
|
||||||
|
pname = "django-types";
|
||||||
|
version = "0.17.0";
|
||||||
|
|
||||||
|
format = "pyproject";
|
||||||
|
|
||||||
|
src = pkgs.fetchPypi {
|
||||||
|
inherit pname version;
|
||||||
|
hash = "sha256-wcQqt4h2xXxyg0LVqwYHJas3H8jcg7uFuuC+BoRqrXA=";
|
||||||
|
};
|
||||||
|
|
||||||
|
nativeBuildInputs = with python.pkgs; [ poetry-core ];
|
||||||
|
|
||||||
|
# setup.cfg tries to pull in nonexistent LICENSE.txt file
|
||||||
|
# postPatch = "rm setup.cfg";
|
||||||
|
|
||||||
|
# propagatedBuildInputs = [ django typing-extensions ];
|
||||||
|
};
|
||||||
|
in
|
||||||
|
|
||||||
|
|
||||||
pkgs.mkShell {
|
pkgs.mkShell {
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
export DJANGO_SETTINGS_MODULE=gestioasso.settings.local
|
export DJANGO_SETTINGS_MODULE=gestioasso.settings.local
|
||||||
|
@ -10,12 +34,11 @@ pkgs.mkShell {
|
||||||
pip install -r requirements-devel.txt | grep -v 'Requirement already satisfied:'
|
pip install -r requirements-devel.txt | grep -v 'Requirement already satisfied:'
|
||||||
'';
|
'';
|
||||||
|
|
||||||
packages = with pkgs; [
|
packages = [ python django-types ] ++ (with python.pkgs; [
|
||||||
python38
|
pip
|
||||||
python38Packages.pip
|
virtualenv
|
||||||
python38Packages.virtualenv
|
python-ldap
|
||||||
python38Packages.python-ldap
|
]);
|
||||||
];
|
|
||||||
|
|
||||||
allowSubstitutes = false;
|
allowSubstitutes = false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue