# 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 from note.models import Note, Transaction 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: 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.")) notes = Note.objects.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 outcoming = Transaction.objects.filter(valid=True, source=note)\ .annotate(total=F("quantity") * F("amount")).aggregate(Sum("total"))["total__sum"] or 0 calculated_balance = incoming - outcoming if calculated_balance != 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)