diff --git a/AKModel/models.py b/AKModel/models.py index 972953a9c77cf669f6c8dd23a6a2dbaced2939a4..88e8e13b7f7706e8bd527a203cda3bd853cdc759 100644 --- a/AKModel/models.py +++ b/AKModel/models.py @@ -472,6 +472,7 @@ class ConstraintViolation(models.Model): :rtype: str """ output = [] + """ # Stringify all ManyToMany fields for field_mm in self.fields_mm: output.append(f"{field_mm}: {', '.join(str(a) for a in getattr(self, field_mm).all())}") @@ -480,6 +481,7 @@ class ConstraintViolation(models.Model): a = getattr(self, field, None) if a is not None: output.append(f"{field}: {a}") + """ return ", ".join(output) get_details.short_description = _('Details') @@ -536,9 +538,31 @@ class ConstraintViolation(models.Model): return set(self.ak_slots.all()) return self.ak_slots_tmp + def save(self, *args, **kwargs): + super().save(*args, **kwargs) + # Store temporary m2m-relations in db + for ak in self.aks_tmp: + self.aks.add(ak) + for ak_slot in self.ak_slots_tmp: + self.ak_slots.add(ak_slot) + def __str__(self): return f"{self.get_level_display()}: {self.get_type_display()} [{self.get_details()}]" def __eq__(self, other): - # TODO Check if FIELDS and FIELDS_MM are equal - return super().__eq__(other) + if not isinstance(other, ConstraintViolation): + return False + if self.type != other.type: + return False + for field_mm in self.fields_mm: + s: set = getattr(self, field_mm) + o: set = getattr(other, field_mm) + if len(s) != len(o): + return False + #if len(s.intersection(o)) != len(s): + # return False + for field in self.fields: + if getattr(self, field) != getattr(other, field): + return False + return True + diff --git a/AKScheduling/models.py b/AKScheduling/models.py index 990bcd4a74b6efebdc865830abd5cafb8600ae21..8493b12ff10b2b314ecc040643e7b9b50a00683d 100644 --- a/AKScheduling/models.py +++ b/AKScheduling/models.py @@ -14,25 +14,26 @@ def ak_changed_handler(sender, instance: AK, **kwargs): # Owner might have changed: Might affect multiple AKs by the same owner at the same time conflicts = [] - type = ConstraintViolation.ViolationType.OWNER_TWO_SLOTS + violation_type = ConstraintViolation.ViolationType.OWNER_TWO_SLOTS + + slots_of_this_ak: [AKSlot] = instance.akslot_set.filter(start__isnull=False) + # For all owners... for owner in instance.owners.all(): # ...find overlapping AKs... - slots_by_owner : [AKSlot] = [] - slots_by_owner_this_ak : [AKSlot] = [] + slots_by_owner: [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 slot in slots_of_this_ak: for other_slot in slots_by_owner: if slot.overlaps(other_slot): - # TODO Create ConstraintViolation here c = ConstraintViolation( - type=type, + type=violation_type, level=ConstraintViolation.ViolationLevel.VIOLATION, event=event, ak_owner=owner @@ -44,17 +45,31 @@ def ak_changed_handler(sender, instance: AK, **kwargs): conflicts.append(c) print(f"{owner} has the following conflicts: {conflicts}") # ... and compare to/update list of existing violations of this type: - current_violations = instance.constraintviolation_set.filter(type=type) + current_violations = list(instance.constraintviolation_set.filter(type=violation_type)) + print(current_violations) for conflict in conflicts: - pass + # 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 outdated_violation in current_violations: + outdated_violation.delete() @receiver(post_save, sender=AKSlot) def akslot_changed_handler(sender, instance, **kwargs): - # Changes might affect: Duplicate parallel, Two in room + # Changes might affect: Duplicate parallel, Two in room, Resodeadline print(f"{sender} changed") # TODO Replace with real handling