from django.db.models.signals import post_save from django.dispatch import receiver from AKModel.availability.models import Availability from AKModel.models import AK, AKSlot, Room, Event, AKOwner, ConstraintViolation @receiver(post_save, sender=AK) def ak_changed_handler(sender, instance: AK, **kwargs): # Changes might affect: Owner(s), Requirements, Conflicts, Prerequisites, Category, Interest print(f"{instance} changed") event = instance.event # Owner might have changed: Might affect multiple AKs by the same owner at the same time conflicts = [] violation_type = ConstraintViolation.ViolationType.OWNER_TWO_SLOTS # For all owners... for owner in instance.owners.all(): # ...find overlapping AKs... slots_by_owner : [AKSlot] = [] slots_by_owner_this_ak : [AKSlot] = [] aks_by_owner = owner.ak_set.all() for ak in aks_by_owner: if ak != instance: slots_by_owner.extend(ak.akslot_set.filter(start__isnull=False)) else: # ToDo Fill this outside of loop? slots_by_owner_this_ak.extend(ak.akslot_set.filter(start__isnull=False)) for slot in slots_by_owner_this_ak: for other_slot in slots_by_owner: if slot.overlaps(other_slot): c = ConstraintViolation( type=violation_type, level=ConstraintViolation.ViolationLevel.VIOLATION, event=event, ak_owner=owner ) c.aks_tmp.add(instance) c.aks_tmp.add(other_slot.ak) c.ak_slots_tmp.add(slot) c.ak_slots_tmp.add(other_slot) conflicts.append(c) print(f"{owner} has the following conflicts: {conflicts}") # ... and compare to/update list of existing violations of this type: current_violations = list(instance.constraintviolation_set.filter(type=violation_type)) print(current_violations) for conflict in conflicts: # eq_violation_index = -1 try: current_violations.remove(conflict) print(f"Found existing conflict {conflict}") except ValueError: conflict.save() """for i, other_violation in enumerate(current_violations): if conflict == other_violation: eq_violation_index = i break if eq_violation_index > -1:""" # TODO Remove from list of current_violations if an equal new one is found # TODO Otherwise, store this conflict in db # conflict.save() # TODO Remove all violations still in current_violations for old_violation in current_violations: old_violation.delete() @receiver(post_save, sender=AKSlot) def akslot_changed_handler(sender, instance, **kwargs): # Changes might affect: Duplicate parallel, Two in room print(f"{sender} changed") # TODO Replace with real handling @receiver(post_save, sender=Room) def room_changed_handler(sender, **kwargs): # Changes might affect: Room size, Requirement print(f"{sender} changed") # TODO Replace with real handling @receiver(post_save, sender=Availability) def availability_changed_handler(sender, **kwargs): # Changes might affect: category availability, AK availability, Room availability print(f"{sender} changed") # TODO Replace with real handling @receiver(post_save, sender=Event) def room_changed_handler(sender, **kwargs): # Changes might affect: Reso-Deadline print(f"{sender} changed") # TODO Replace with real handling