performed some stupid ass shit nested many to many count to fix broken ass numbers

This commit is contained in:
Valentin Moguérou 2024-05-05 07:46:23 +02:00
parent 4710dbe7ce
commit bd9fe4e735
2 changed files with 44 additions and 24 deletions

View File

@ -1,11 +1,12 @@
from datetime import date, datetime, timedelta
from pprint import pprint
from pytz import timezone
import aiohttp
from django.db import models
from django.db.models import F, Q, Count, QuerySet
from django.db.models import F, Q, Count, QuerySet, Subquery, OuterRef, Sum
from django.contrib.auth.models import User
from django.conf import settings
@ -144,25 +145,35 @@ class Term(models.Model):
.select_related("slot", "slot__term")
.prefetch_related("swap_set")
.filter(slot__term=self)
.annotate(adt_plus=Count("swap", filter=Q(swap__enroll=1)))
.annotate(adt_minus=Count("swap", filter=Q(swap__enroll=0)))
.annotate(volume=F("slot__capacity") + F("adt_plus") - F("adt_minus")))
.annotate(base_vol=Count("groups__members"))
.annotate(swap_plus=Count("swap", filter=Q(swap__enroll=1), distinct=True))
.annotate(swap_minus=Count("swap", filter=Q(swap__enroll=0), distinct=True))
.annotate(volume=F("base_vol") + F("swap_plus") - F("swap_minus")))
def query_colles_of_student(self, student) -> QuerySet:
has_student = ((Q(groups__student=student)
& ~Q(swap__enroll=0, swap__student=student))
| Q(swap__enroll=1, swap__student=student))
return (Colle.objects
.select_related("slot", "slot__term")
.prefetch_related("swap_set")
.filter(slot__term=self)
.filter((Q(groups__student=student)
& ~Q(swap__enroll=0, swap__student=student))
| Q(swap__enroll=1, swap__student=student))
.annotate(adt_plus=Count("swap", filter=Q(swap__enroll=1)))
.annotate(adt_minus=Count("swap", filter=Q(swap__enroll=0)))
.annotate(volume=F("slot__capacity") + F("adt_plus") - F("adt_minus")))
.annotate(base_vol=Count("groups__members", distinct=True))
.annotate(swap_plus=Count("pk", filter=Q(swap__enroll=1), distinct=True))
.annotate(swap_minus=Count("pk", filter=Q(swap__enroll=0), distinct=True))
.annotate(volume=F("base_vol") + F("swap_plus") - F("swap_minus"))
.filter(has_student)
)
def query_colles_not_full_excluding_student(self, student) -> QuerySet:
has_student = ((Q(groups__student=student)
& ~Q(swap__enroll=0, swap__student=student))
| Q(swap__enroll=1, swap__student=student))
def query_colles_not_full(self) -> QuerySet:
return (self.query_colles()
.filter(volume__lt=F("slot__capacity"), date__gte=date.today()))
.filter(volume__lt=F("slot__capacity"), date__gte=date.today())
.exclude(has_student))
def __str__(self) -> str:
return self.description
@ -295,7 +306,7 @@ class Colle(models.Model):
"slot__time"]
slot = models.ForeignKey(Slot, on_delete=models.CASCADE)
groups = models.ManyToManyField(Group)
groups = models.ManyToManyField(Group, blank=True)
date = models.DateField()
def initial_group(self):
@ -319,23 +330,22 @@ class Colle(models.Model):
def is_attendee(self, student):
return self.final_group().contains(student)
def volume(self):
def get_volume(self):
"""
Renvoie le nombre d'étudiants inscrits à la colle en tenant compte des swaps.
"""
n_base = sum(group.members.count() for group in self.groups.all())
n_plus = len(Swap.objects.filter(enroll=True, colle=self))
n_moins = len(Swap.objects.filter(enroll=False, colle=self))
return n_base + n_plus - n_moins
return (Student.objects
.filter(Q(groups__colle=self)
& ~Q(swap__colle=self, swap__enroll=False)
| Q(swap__colle=self, swap__enroll=True))
.distinct()
.count())
def is_full(self):
"""
Renvoie si la colle est pleine.
"""
eff = self.volume()
return eff >= self.slot.capacity
return self.get_volume() >= self.slot.capacity
def is_edited(self):
"""
@ -369,7 +379,7 @@ class Colle(models.Model):
# func()
def __str__(self):
return f"{self.slot} le {self.date} avec groupes {'+'.join(str(groupe) for groupe in self.groups.all())}"
return f"Colle {self.slot.subject} ({self.slot.colleur}); {self.date} {self.slot.time} {self.slot.room}. Groupe(s) {{{'; '.join(str(groupe) for groupe in self.groups.all())}}}"
def datetime(self):
return datetime.combine(self.date, self.slot.time, tzinfo=timezone("Europe/Paris"))
@ -425,3 +435,13 @@ class CalendarLink(models.Model):
fields=['student', 'term'], name='unique_student_term_combination'
)
]
def test():
valentin = Student.objects.get(pk=25)
term = Term.objects.get(pk=3)
colles = term.query_colles_of_student(valentin).order_by("-volume")
for c in colles:
print(f"* {c.slot} {c.volume} : {c.base_vol} + {c.swap_plus} - {c.swap_minus}")

View File

@ -131,7 +131,7 @@ def marketplace(request):
return HttpResponse("pas encore supporté")
term = student.cls.current_term()
colles = term.query_colles_not_full()
colles = term.query_colles_not_full_excluding_student(student)
context = {
"colles": colles,