Compare commits
3 Commits
034d8c43b6
...
47dc4dd9e6
Author | SHA1 | Date |
---|---|---|
Yohann D'ANELLO | 47dc4dd9e6 | |
Yohann D'ANELLO | e01b48b807 | |
Yohann D'ANELLO | 31dc478b7a |
|
@ -1,6 +1,6 @@
|
||||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
from django.core.mail import send_mail
|
||||||
from django.core.management import BaseCommand
|
from django.core.management import BaseCommand
|
||||||
from django.db.models import Sum, F
|
from django.db.models import Sum, F
|
||||||
|
|
||||||
|
@ -11,20 +11,30 @@ from note.templatetags.pretty_money import pretty_money
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
def add_arguments(self, parser):
|
def add_arguments(self, parser):
|
||||||
parser.add_argument('--sum-all', '-s', action='store_true', help='Check if the global sum is equal to zero')
|
parser.add_argument('--sum-all', '-s', action='store_true', help='Check if the global sum is equal to zero')
|
||||||
|
parser.add_argument('--check-all', '-a', action='store_true', help='Check all notes')
|
||||||
|
parser.add_argument('--check', '-c', type=int, nargs='+', help='Select note ids')
|
||||||
parser.add_argument('--fix', '-f', action='store_true', help='Fix note balances')
|
parser.add_argument('--fix', '-f', action='store_true', help='Fix note balances')
|
||||||
|
parser.add_argument('--mail', '-m', action='store_true', help='Send mail to admins if there is an error')
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
|
error = False
|
||||||
|
err_log = ""
|
||||||
|
|
||||||
if options["sum_all"]:
|
if options["sum_all"]:
|
||||||
s = Note.objects.aggregate(Sum("balance"))["balance__sum"]
|
s = Note.objects.aggregate(Sum("balance"))["balance__sum"]
|
||||||
if s:
|
if s:
|
||||||
self.stderr.write(self.style.NOTICE("LA SOMME DES NOTES NE VAUT PAS ZÉRO : " + pretty_money(s)))
|
err_log += self.style.NOTICE("LA SOMME DES NOTES NE VAUT PAS ZÉRO : " + pretty_money(s)) + "\n"
|
||||||
exit(-1)
|
error = True
|
||||||
else:
|
else:
|
||||||
self.stdout.write(self.style.SUCCESS("La somme des notes vaut bien zéro."))
|
self.stdout.write(self.style.SUCCESS("La somme des notes vaut bien zéro."))
|
||||||
exit(0)
|
|
||||||
|
|
||||||
error = False
|
notes = Note.objects.none()
|
||||||
for note in Note.objects.all():
|
if options["check_all"]:
|
||||||
|
notes = Note.objects.all()
|
||||||
|
elif options["check"]:
|
||||||
|
notes = Note.objects.filter(pk__in=options["check"])
|
||||||
|
|
||||||
|
for note in notes:
|
||||||
balance = note.balance
|
balance = note.balance
|
||||||
incoming = Transaction.objects.filter(valid=True, destination=note)\
|
incoming = Transaction.objects.filter(valid=True, destination=note)\
|
||||||
.annotate(total=F("quantity") * F("amount")).aggregate(Sum("total"))["total__sum"] or 0
|
.annotate(total=F("quantity") * F("amount")).aggregate(Sum("total"))["total__sum"] or 0
|
||||||
|
@ -32,12 +42,19 @@ class Command(BaseCommand):
|
||||||
.annotate(total=F("quantity") * F("amount")).aggregate(Sum("total"))["total__sum"] or 0
|
.annotate(total=F("quantity") * F("amount")).aggregate(Sum("total"))["total__sum"] or 0
|
||||||
calculated_balance = incoming - outcoming
|
calculated_balance = incoming - outcoming
|
||||||
if calculated_balance != balance:
|
if calculated_balance != balance:
|
||||||
self.stderr.write(self.style.NOTICE("LA SOMME DES TRANSACTIONS DE LA NOTE {} NE CORRESPOND PAS "
|
err_log += self.style.NOTICE("LA SOMME DES TRANSACTIONS DE LA NOTE {} NE CORRESPOND PAS "
|
||||||
"AVEC LE MONTANT RÉEL".format(str(note))))
|
"AVEC LE MONTANT RÉEL".format(str(note))) + "\n"
|
||||||
self.stderr.write(self.style.NOTICE("Attendu : {}, calculé : {}"
|
err_log += self.style.NOTICE("Attendu : {}, calculé : {}"
|
||||||
.format(pretty_money(balance), pretty_money(calculated_balance))))
|
.format(pretty_money(balance), pretty_money(calculated_balance))) + "\n"
|
||||||
if options["fix"]:
|
if options["fix"]:
|
||||||
note.balance = calculated_balance
|
note.balance = calculated_balance
|
||||||
note.save()
|
note.save()
|
||||||
error = True
|
error = True
|
||||||
|
|
||||||
|
if error:
|
||||||
|
self.stderr.write(err_log)
|
||||||
|
if options["mail"]:
|
||||||
|
send_mail("[Note Kfet] La base de données n'est pas consistante", err_log,
|
||||||
|
"NoteKfet2020 <notekfet2020@crans.org>", ["respoinfo.bde@lists.crans.org"])
|
||||||
|
|
||||||
exit(1 if error else 0)
|
exit(1 if error else 0)
|
||||||
|
|
|
@ -131,6 +131,8 @@ class Command(ImportCommand):
|
||||||
"registration_valid": True,
|
"registration_valid": True,
|
||||||
"email_confirmed": True,
|
"email_confirmed": True,
|
||||||
"promotion": MAP_IDBDE_PROMOTION[row["idbde"]]["promo"],
|
"promotion": MAP_IDBDE_PROMOTION[row["idbde"]]["promo"],
|
||||||
|
"report_frequency": row["report_period"],
|
||||||
|
"last_report": make_aware(row["previous_report_date"]).date(),
|
||||||
}
|
}
|
||||||
note_dict["created_at"] = make_aware(MAP_IDBDE_PROMOTION[row["idbde"]]["created_at"])
|
note_dict["created_at"] = make_aware(MAP_IDBDE_PROMOTION[row["idbde"]]["created_at"])
|
||||||
note_dict["polymorphic_ctype"] = note_user_type
|
note_dict["polymorphic_ctype"] = note_user_type
|
||||||
|
|
|
@ -11,15 +11,26 @@ from note.models import NoteUser
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument("--spam", "-s", action='store_true', help="Spam negative users")
|
||||||
|
parser.add_argument("--report", "-r", action='store_true', help="Report the list of negative users to admins")
|
||||||
|
parser.add_argument("--negative-amount", "-n", action='store', type=int, default=1000,
|
||||||
|
help="Maximum amount to be considered as very negative")
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
|
activate('fr')
|
||||||
notes = NoteUser.objects.filter(
|
notes = NoteUser.objects.filter(
|
||||||
balance__lte=-1000,
|
balance__lte=-options["negative_amount"],
|
||||||
user__memberships__date_end__gte=timezone.now(),
|
user__memberships__date_end__gte=timezone.now(),
|
||||||
).order_by('balance').distinct().all()
|
).order_by('balance').distinct().all()
|
||||||
|
|
||||||
|
if options["spam"]:
|
||||||
for note in notes:
|
for note in notes:
|
||||||
note.send_mail_negative_balance()
|
note.send_mail_negative_balance()
|
||||||
activate('fr')
|
|
||||||
|
if options["report"]:
|
||||||
plain_text = render_to_string("note/mails/negative_notes_report.txt", context=dict(notes=notes))
|
plain_text = render_to_string("note/mails/negative_notes_report.txt", context=dict(notes=notes))
|
||||||
html = render_to_string("note/mails/negative_notes_report.html", context=dict(notes=notes))
|
html = render_to_string("note/mails/negative_notes_report.html", context=dict(notes=notes))
|
||||||
send_mail("[Note Kfet] Liste des négatifs", plain_text, "Note Kfet 2020 <notekfet2020@crans.org>",
|
send_mail("[Note Kfet] Liste des négatifs", plain_text, "Note Kfet 2020 <notekfet2020@crans.org>",
|
||||||
recipient_list=["respoinfo.bde@lists.crans.org", "tresorerie.bde@lists.crans.org"], html_message=html)
|
recipient_list=["respoinfo.bde@lists.crans.org", "tresorerie.bde@lists.crans.org"],
|
||||||
|
html_message=html)
|
||||||
|
|
|
@ -18,14 +18,20 @@ class Command(BaseCommand):
|
||||||
activate('fr')
|
activate('fr')
|
||||||
notes = NoteUser.objects.filter(
|
notes = NoteUser.objects.filter(
|
||||||
user__memberships__date_end__gte=timezone.now(),
|
user__memberships__date_end__gte=timezone.now(),
|
||||||
|
user__profile__report_frequency__gt=0,
|
||||||
).distinct().all()
|
).distinct().all()
|
||||||
for note in notes:
|
for note in notes:
|
||||||
now = timezone.now()
|
now = timezone.now()
|
||||||
last_week = now - timedelta(days=7)
|
last_report = note.user.profile.last_report
|
||||||
|
delta = now.date() - last_report
|
||||||
|
if delta.days < note.user.profile.report_frequency:
|
||||||
|
continue
|
||||||
|
note.user.profile.last_report = now.date()
|
||||||
|
note.user.profile.save()
|
||||||
last_transactions = Transaction.objects.filter(
|
last_transactions = Transaction.objects.filter(
|
||||||
Q(source=note) | Q(destination=note),
|
Q(source=note) | Q(destination=note),
|
||||||
created_at__gte=last_week,
|
created_at__gte=last_report,
|
||||||
).all()
|
).order_by("created_at").all()
|
||||||
if not last_transactions.exists():
|
if not last_transactions.exists():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -39,7 +45,7 @@ class Command(BaseCommand):
|
||||||
outcoming=outcoming,
|
outcoming=outcoming,
|
||||||
diff=incoming - outcoming,
|
diff=incoming - outcoming,
|
||||||
now=now,
|
now=now,
|
||||||
last_week=last_week,
|
last_report=last_report,
|
||||||
)
|
)
|
||||||
html = render_to_string("note/mails/weekly_report.html", context)
|
html = render_to_string("note/mails/weekly_report.html", context)
|
||||||
note.user.email_user("[Note Kfet] Rapport de la Note Kfet", html, html_message=html)
|
note.user.email_user("[Note Kfet] Rapport de la Note Kfet", html, html_message=html)
|
||||||
|
|
Loading…
Reference in New Issue