manager: detect partial booking checks overlap using only form data (#82231)
gitea/chrono/pipeline/head This commit looks good
Details
gitea/chrono/pipeline/head This commit looks good
Details
This commit is contained in:
parent
b7c5d4f675
commit
3161f47cd1
|
@ -3254,21 +3254,6 @@ class BookingCheck(models.Model):
|
|||
return False
|
||||
return True
|
||||
|
||||
def overlaps_existing_check(self, start_time, end_time):
|
||||
booking_checks = BookingCheck.objects.filter(booking=self.booking).exclude(pk=self.pk)
|
||||
if not booking_checks:
|
||||
return False
|
||||
|
||||
if len(booking_checks) > 1:
|
||||
raise ValueError('too many booking checks') # should not happen
|
||||
|
||||
booking_check = booking_checks[0]
|
||||
|
||||
if not start_time or not end_time:
|
||||
return bool(booking_check.start_time < (start_time or end_time) < booking_check.end_time)
|
||||
|
||||
return bool(start_time < booking_check.end_time and end_time > booking_check.start_time)
|
||||
|
||||
|
||||
OpeningHour = collections.namedtuple('OpeningHour', ['begin', 'end'])
|
||||
|
||||
|
|
|
@ -648,9 +648,6 @@ class PartialBookingCheckForm(forms.ModelForm):
|
|||
if start_time and end_time and end_time <= start_time:
|
||||
raise ValidationError(_('Arrival must be before departure.'))
|
||||
|
||||
if self.instance.overlaps_existing_check(start_time, end_time):
|
||||
raise ValidationError(_('Booking check hours overlap existing check.'))
|
||||
|
||||
if self.cleaned_data['presence'] is not None:
|
||||
kind = 'presence' if self.cleaned_data['presence'] else 'absence'
|
||||
if f'{kind}_check_type' in self.cleaned_data:
|
||||
|
|
|
@ -4637,13 +4637,34 @@ class PartialBookingCheckView(ViewableAgendaMixin, TemplateView):
|
|||
forms = self.get_forms()
|
||||
|
||||
all_valid = all(form.is_valid() for form in forms)
|
||||
if all_valid:
|
||||
if all_valid and not self.checks_overlap(forms):
|
||||
for form in forms:
|
||||
form.save()
|
||||
return HttpResponseRedirect(self.get_success_url())
|
||||
|
||||
return self.render_to_response(self.get_context_data(forms=forms))
|
||||
|
||||
def checks_overlap(self, forms):
|
||||
Interval = collections.namedtuple('Interval', ['start', 'end', 'form'])
|
||||
intervals = [
|
||||
Interval(
|
||||
# if check has no start/end time, take (time, time) as an interval
|
||||
form.cleaned_data['start_time'] or form.cleaned_data['end_time'],
|
||||
form.cleaned_data['end_time'] or form.cleaned_data['start_time'],
|
||||
form,
|
||||
)
|
||||
for form in forms
|
||||
if form.cleaned_data['presence'] is not None
|
||||
]
|
||||
intervals.sort(key=lambda x: x.start)
|
||||
|
||||
for i in range(1, len(intervals)):
|
||||
if intervals[i - 1].end > intervals[i].start:
|
||||
intervals[i].form.add_error(None, _('Booking check hours are overlapping.'))
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def get_success_url(self):
|
||||
date = self.event.start_datetime
|
||||
return reverse(
|
||||
|
|
|
@ -552,11 +552,11 @@ def test_manager_partial_bookings_multiple_checks(app, admin_user):
|
|||
resp.form['check-2-start_time'] = '11:30'
|
||||
resp.form['check-2-end_time'] = ''
|
||||
resp = resp.form.submit()
|
||||
assert 'Booking check hours overlap existing check.' in resp.text
|
||||
assert 'Booking check hours are overlapping.' in resp.text
|
||||
|
||||
resp.form['check-2-end_time'] = '17:30'
|
||||
resp = resp.form.submit()
|
||||
assert 'Booking check hours overlap existing check.' in resp.text
|
||||
assert 'Booking check hours are overlapping.' in resp.text
|
||||
|
||||
resp.form['check-2-start_time'] = '12:30'
|
||||
resp.form['check-2-presence'] = ''
|
||||
|
@ -578,6 +578,19 @@ def test_manager_partial_bookings_multiple_checks(app, admin_user):
|
|||
assert 'Arrival must be before departure.' in resp.text
|
||||
assert 'gadjo-folded' not in resp.text
|
||||
|
||||
# overlap is detected when 2 checks are created at the same time
|
||||
BookingCheck.objects.all().delete()
|
||||
|
||||
resp.form['presence'] = 'True'
|
||||
resp.form['start_time'] = '10:00'
|
||||
resp.form['end_time'] = '11:00'
|
||||
resp.form['check-2-presence'] = 'False'
|
||||
resp.form['check-2-start_time'] = '10:30'
|
||||
resp.form['check-2-end_time'] = '11:30'
|
||||
resp = resp.form.submit()
|
||||
|
||||
assert 'Booking check hours are overlapping.' in resp.text
|
||||
|
||||
|
||||
@pytest.mark.parametrize('subscription_only', (True, False))
|
||||
def test_manager_partial_bookings_incomplete_check(subscription_only, app, admin_user):
|
||||
|
|
Loading…
Reference in New Issue