diff --git a/management/commands/check_consistency.py b/management/commands/check_consistency.py new file mode 100644 index 0000000..67a40fb --- /dev/null +++ b/management/commands/check_consistency.py @@ -0,0 +1,39 @@ +# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later + +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') + + def handle(self, *args, **options): + 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) + 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(): + 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 + expected_balance = incoming - outcoming + if expected_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(expected_balance)))) + error = True + exit(1 if error else 0)