agendas: forbid having more than two checks on booking (#83544)
This commit is contained in:
parent
d9a93ac2e3
commit
46e6fbcf5b
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.2.21 on 2023-11-22 09:59
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('agendas', '0166_lease'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddConstraint(
|
||||
model_name='bookingcheck',
|
||||
constraint=models.UniqueConstraint(
|
||||
fields=('booking', 'presence'), name='max_2_checks_on_booking'
|
||||
),
|
||||
),
|
||||
]
|
|
@ -3021,28 +3021,18 @@ class Booking(models.Model):
|
|||
def refresh_computed_times(self, commit=False):
|
||||
to_update = []
|
||||
user_checks = sorted(self.user_checks.all(), key=lambda a: a.start_time or datetime.time(0))
|
||||
many_user_checks = len(user_checks) > 1
|
||||
assert len(user_checks) < 3 # 2 user_checks max !
|
||||
|
||||
if user_checks and not many_user_checks:
|
||||
# only one user_check
|
||||
if len(user_checks) == 1:
|
||||
user_check = user_checks[0]
|
||||
changed = user_check._refresh_computed_times()
|
||||
if changed:
|
||||
to_update.append(user_check)
|
||||
|
||||
elif many_user_checks:
|
||||
# two user_checks
|
||||
user_check1 = user_checks[0]
|
||||
user_check2 = user_checks[1]
|
||||
compute_one_first = True
|
||||
if user_check1.presence != user_check2.presence:
|
||||
# one user check is presence, the other is absence
|
||||
if user_check1.presence is False:
|
||||
# the second check is presence, it should be computed first
|
||||
compute_one_first = False
|
||||
elif len(user_checks) == 2:
|
||||
user_check1, user_check2 = user_checks
|
||||
|
||||
if compute_one_first:
|
||||
if user_check1.presence is True:
|
||||
# first check is presence, compute it first
|
||||
changed = user_check1._refresh_computed_times(adjust_end_to_booking=False)
|
||||
if changed:
|
||||
to_update.append(user_check1)
|
||||
|
@ -3050,6 +3040,7 @@ class Booking(models.Model):
|
|||
if changed:
|
||||
to_update.append(user_check2)
|
||||
else:
|
||||
# second check is presence, compute it first
|
||||
changed = user_check2._refresh_computed_times(adjust_start_to_booking=False)
|
||||
if changed:
|
||||
to_update.append(user_check2)
|
||||
|
@ -3166,6 +3157,11 @@ class BookingCheck(models.Model):
|
|||
type_slug = models.CharField(max_length=160, blank=True, null=True)
|
||||
type_label = models.CharField(max_length=150, blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
constraints = [
|
||||
models.UniqueConstraint(fields=['booking', 'presence'], name='max_2_checks_on_booking')
|
||||
]
|
||||
|
||||
def _get_previous_and_next_slots(self, _time):
|
||||
minutes = {
|
||||
'hour': 60,
|
||||
|
|
|
@ -4119,56 +4119,6 @@ def test_booking_refresh_computed_times_only_one_user_check():
|
|||
datetime.time(12, 30),
|
||||
datetime.time(17, 0),
|
||||
),
|
||||
# both absence
|
||||
(
|
||||
True,
|
||||
datetime.time(7, 45),
|
||||
datetime.time(12, 15),
|
||||
True,
|
||||
datetime.time(13, 0), # no overlapping
|
||||
datetime.time(15, 0),
|
||||
datetime.time(7, 30),
|
||||
datetime.time(12, 30),
|
||||
datetime.time(12, 30),
|
||||
datetime.time(17, 0),
|
||||
),
|
||||
(
|
||||
True,
|
||||
datetime.time(7, 45),
|
||||
datetime.time(12, 15),
|
||||
True,
|
||||
datetime.time(12, 15), # computed start should be 12H00
|
||||
datetime.time(15, 0),
|
||||
datetime.time(7, 30),
|
||||
datetime.time(12, 30),
|
||||
datetime.time(12, 30), # but it is adjusted to 12H30
|
||||
datetime.time(17, 0),
|
||||
),
|
||||
# both presence
|
||||
(
|
||||
False,
|
||||
datetime.time(7, 45),
|
||||
datetime.time(12, 15),
|
||||
False,
|
||||
datetime.time(13, 0), # no overlapping
|
||||
datetime.time(15, 0),
|
||||
datetime.time(7, 30),
|
||||
datetime.time(12, 30),
|
||||
datetime.time(12, 30),
|
||||
datetime.time(17, 0),
|
||||
),
|
||||
(
|
||||
False,
|
||||
datetime.time(7, 45),
|
||||
datetime.time(12, 15),
|
||||
False,
|
||||
datetime.time(12, 15), # computed start should be 12H00
|
||||
datetime.time(15, 0),
|
||||
datetime.time(7, 30),
|
||||
datetime.time(12, 30),
|
||||
datetime.time(12, 30), # but it is adjusted to 12H30
|
||||
datetime.time(17, 0),
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_booking_refresh_computed_times_two_user_check(
|
||||
|
@ -4209,25 +4159,6 @@ def test_booking_refresh_computed_times_two_user_check(
|
|||
assert user_check2.computed_end_time == expected_end2
|
||||
|
||||
|
||||
def test_booking_refresh_computed_times_more_than_two_user_check():
|
||||
agenda = Agenda.objects.create(
|
||||
label='Agenda', kind='events', invoicing_unit='half_hour', invoicing_tolerance=10
|
||||
)
|
||||
event = Event.objects.create(
|
||||
agenda=agenda,
|
||||
start_datetime=make_aware(datetime.datetime(2023, 5, 1, 14, 00)),
|
||||
places=10,
|
||||
)
|
||||
booking = Booking.objects.create(
|
||||
event=event, start_time=datetime.time(8, 0), end_time=datetime.time(17, 0)
|
||||
)
|
||||
BookingCheck.objects.create(booking=booking, presence=True)
|
||||
BookingCheck.objects.create(booking=booking, presence=True)
|
||||
BookingCheck.objects.create(booking=booking, presence=True)
|
||||
with pytest.raises(AssertionError):
|
||||
booking.refresh_computed_times(commit=True)
|
||||
|
||||
|
||||
def test_agenda_refresh_booking_computed_times():
|
||||
agenda = Agenda.objects.create(
|
||||
label='Agenda',
|
||||
|
@ -4437,3 +4368,24 @@ def test_agenda_booking_user_check_property():
|
|||
with pytest.raises(AttributeError):
|
||||
# pylint: disable=pointless-statement
|
||||
booking.user_check
|
||||
|
||||
|
||||
def test_agenda_booking_max_two_user_checks():
|
||||
agenda = Agenda.objects.create(label='Agenda', kind='events')
|
||||
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
|
||||
booking = Booking.objects.create(event=event)
|
||||
|
||||
BookingCheck.objects.create(booking=booking, presence=True)
|
||||
|
||||
# cannot create second check with presence=True
|
||||
with pytest.raises(IntegrityError):
|
||||
with transaction.atomic():
|
||||
BookingCheck.objects.create(booking=booking, presence=True)
|
||||
|
||||
# allow to create second check with presence=False
|
||||
BookingCheck.objects.create(booking=booking, presence=False)
|
||||
|
||||
# cannot create second check with presence=False
|
||||
with pytest.raises(IntegrityError):
|
||||
with transaction.atomic():
|
||||
BookingCheck.objects.create(booking=booking, presence=False)
|
||||
|
|
Loading…
Reference in New Issue