diff --git a/management/commands/check_consistency.py b/management/commands/check_consistency.py index 72bbdfd..9e0b328 100644 --- a/management/commands/check_consistency.py +++ b/management/commands/check_consistency.py @@ -1,6 +1,6 @@ # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later - +from django.core.mail import send_mail from django.core.management import BaseCommand from django.db.models import Sum, F @@ -11,20 +11,30 @@ from note.templatetags.pretty_money import pretty_money class Command(BaseCommand): 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('--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('--mail', '-m', action='store_true', help='Send mail to admins if there is an error') def handle(self, *args, **options): + error = False + err_log = "" + if options["sum_all"]: s = Note.objects.aggregate(Sum("balance"))["balance__sum"] if s: - self.stderr.write(self.style.NOTICE("LA SOMME DES NOTES NE VAUT PAS ZÉRO : " + pretty_money(s))) - exit(-1) + err_log += self.style.NOTICE("LA SOMME DES NOTES NE VAUT PAS ZÉRO : " + pretty_money(s)) + "\n" + error = True else: self.stdout.write(self.style.SUCCESS("La somme des notes vaut bien zéro.")) - exit(0) - error = False - for note in Note.objects.all(): + notes = None + 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 incoming = Transaction.objects.filter(valid=True, destination=note)\ .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 calculated_balance = incoming - outcoming if calculated_balance != balance: - self.stderr.write(self.style.NOTICE("LA SOMME DES TRANSACTIONS DE LA NOTE {} NE CORRESPOND PAS " - "AVEC LE MONTANT RÉEL".format(str(note)))) - self.stderr.write(self.style.NOTICE("Attendu : {}, calculé : {}" - .format(pretty_money(balance), pretty_money(calculated_balance)))) + err_log += self.style.NOTICE("LA SOMME DES TRANSACTIONS DE LA NOTE {} NE CORRESPOND PAS " + "AVEC LE MONTANT RÉEL".format(str(note))) + "\n" + err_log += self.style.NOTICE("Attendu : {}, calculé : {}" + .format(pretty_money(balance), pretty_money(calculated_balance))) + "\n" if options["fix"]: note.balance = calculated_balance note.save() 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 ", ["respoinfo.bde@lists.crans.org"]) + exit(1 if error else 0) diff --git a/management/commands/import_account.py b/management/commands/import_account.py index 89946e6..05e9aa9 100644 --- a/management/commands/import_account.py +++ b/management/commands/import_account.py @@ -131,6 +131,8 @@ class Command(ImportCommand): "registration_valid": True, "email_confirmed": True, "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["polymorphic_ctype"] = note_user_type diff --git a/management/commands/send_mail_to_negative_balances.py b/management/commands/send_mail_to_negative_balances.py index 510de1c..86d9e52 100644 --- a/management/commands/send_mail_to_negative_balances.py +++ b/management/commands/send_mail_to_negative_balances.py @@ -11,15 +11,26 @@ from note.models import NoteUser 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): + activate('fr') notes = NoteUser.objects.filter( - balance__lte=-1000, + balance__lte=-options["negative_amount"], user__memberships__date_end__gte=timezone.now(), ).order_by('balance').distinct().all() - for note in notes: - note.send_mail_negative_balance() - activate('fr') - 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)) - send_mail("[Note Kfet] Liste des négatifs", plain_text, "Note Kfet 2020 ", - recipient_list=["respoinfo.bde@lists.crans.org", "tresorerie.bde@lists.crans.org"], html_message=html) + + if options["spam"]: + for note in notes: + note.send_mail_negative_balance() + + if options["report"]: + 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)) + send_mail("[Note Kfet] Liste des négatifs", plain_text, "Note Kfet 2020 ", + recipient_list=["respoinfo.bde@lists.crans.org", "tresorerie.bde@lists.crans.org"], + html_message=html) diff --git a/management/commands/send_reports.py b/management/commands/send_reports.py index 1762328..05d7133 100644 --- a/management/commands/send_reports.py +++ b/management/commands/send_reports.py @@ -18,14 +18,20 @@ class Command(BaseCommand): activate('fr') notes = NoteUser.objects.filter( user__memberships__date_end__gte=timezone.now(), + user__profile__report_frequency__gt=0, ).distinct().all() for note in notes: 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( Q(source=note) | Q(destination=note), - created_at__gte=last_week, - ).all() + created_at__gte=last_report, + ).order_by("created_at").all() if not last_transactions.exists(): continue @@ -39,7 +45,7 @@ class Command(BaseCommand): outcoming=outcoming, diff=incoming - outcoming, now=now, - last_week=last_week, + last_report=last_report, ) 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)