agenda: option to have min delay in working days (#55049)

This commit is contained in:
Lauréline Guérin 2021-07-05 16:04:30 +02:00
parent bd51c5138a
commit eb2f8b8d48
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
9 changed files with 94 additions and 11 deletions

View File

@ -1,5 +1,3 @@
# Generated by Django 2.2.19 on 2021-05-19 12:23
from django.db import migrations, models
import chrono.agendas.models

View File

@ -0,0 +1,16 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('agendas', '0096_checked'),
]
operations = [
migrations.AddField(
model_name='agenda',
name='minimal_booking_delay_in_working_days',
field=models.BooleanField(default=False, verbose_name='Minimal booking delay in working days'),
),
]

View File

@ -164,6 +164,10 @@ class Agenda(models.Model):
blank=True,
validators=[MaxValueValidator(10000)],
)
minimal_booking_delay_in_working_days = models.BooleanField(
_('Minimal booking delay in working days'),
default=False,
)
maximal_booking_delay = models.PositiveIntegerField(
_('Maximal booking delay (in days)'),
default=None,
@ -392,6 +396,7 @@ class Agenda(models.Model):
self.absence_reasons_group.slug if self.absence_reasons_group else None
)
agenda['exceptions_desk'] = self.desk_set.get().export_json()
agenda['minimal_booking_delay_in_working_days'] = self.minimal_booking_delay_in_working_days
elif self.kind == 'meetings':
agenda['meetingtypes'] = [x.export_json() for x in self.meetingtype_set.filter(deleted=False)]
agenda['desks'] = [desk.export_json() for desk in self.desk_set.all()]
@ -613,9 +618,16 @@ class Agenda(models.Model):
# compute middle of today with localtime
# 28 Mar 2021 12:00 +01:00
t = localtime(now()).replace(hour=12, minute=0)
# advance of self.maximal_booking_delay - 1 days
# advance of self.minimal_booking_delay - 1 days
# 28 Mar 2021 12:00 +01:00 == 28 Mars 2021 13:00 +02:00 as DST happend on 28 Mar 2021.
t += datetime.timedelta(days=self.minimal_booking_delay)
if settings.WORKING_DAY_CALENDAR is not None and self.minimal_booking_delay_in_working_days:
source_class = import_string(settings.WORKING_DAY_CALENDAR)
calendar = source_class()
t = calendar.add_working_days(t, self.minimal_booking_delay, keep_datetime=True)
else:
t += datetime.timedelta(days=self.minimal_booking_delay)
# move to midnight of the day before, DST happen between 2h/3h so it
# always exists because +/- timedelta does not move the timezone, only
# localtime() does it.

View File

@ -121,6 +121,7 @@ class AgendaBookingDelaysForm(forms.ModelForm):
model = Agenda
fields = [
'minimal_booking_delay',
'minimal_booking_delay_in_working_days',
'maximal_booking_delay',
]
@ -129,6 +130,8 @@ class AgendaBookingDelaysForm(forms.ModelForm):
if kwargs['instance'].kind != 'virtual':
self.fields['minimal_booking_delay'].required = True
self.fields['maximal_booking_delay'].required = True
if kwargs['instance'].kind != 'events' or settings.WORKING_DAY_CALENDAR is None:
del self.fields['minimal_booking_delay_in_working_days']
class AgendaRolesForm(AgendaAddForm):

View File

@ -85,10 +85,16 @@
<div>
<ul>
<li>{% trans "Minimal booking delay:" %}
{% if agenda.minimal_booking_delay is not None %}{{ agenda.minimal_booking_delay }} {% trans "days" %}
{% if agenda.minimal_booking_delay is not None %}
{% if agenda.minimal_booking_delay_in_working_days %}
{% blocktrans count count=agenda.minimal_booking_delay %}{{ count }} working day{% plural %}{{ count }} working days{% endblocktrans %}
{% else %}
{% blocktrans count count=agenda.minimal_booking_delay %}{{ count }} day{% plural %}{{ count }} days{% endblocktrans %}
{% endif %}
{% else %}<i>{% trans "undefined" %}</i>{% endif %}</li>
<li>{% trans "Maximal booking delay:" %}
{% if agenda.maximal_booking_delay is not None %}{{ agenda.maximal_booking_delay }} {% trans "days" %}
{% if agenda.maximal_booking_delay is not None %}
{% blocktrans count count=agenda.maximal_booking_delay %}{{ count }} day{% plural %}{{ count }} days{% endblocktrans %}
{% else %}<i>{% trans "undefined" %}</i>{% endif %}</li>
</ul>
</div>

View File

@ -176,10 +176,12 @@ REQUESTS_TIMEOUT = 28
try:
import workalendar
WORKING_DAY_CALENDAR = 'workalendar.europe.France'
EXCEPTIONS_SOURCES = {
'holidays': {'class': 'workalendar.europe.France', 'label': _('Holidays')},
'holidays': {'class': WORKING_DAY_CALENDAR, 'label': _('Holidays')},
}
except ImportError:
WORKING_DAY_CALENDAR = None
EXCEPTIONS_SOURCES = {}
TEMPLATE_VARS = {}

View File

@ -499,27 +499,50 @@ def test_options_agenda(app, admin_user):
assert 'open_events' not in [k for k, v in resp.context['form'].fields['default_view'].choices]
def test_options_agenda_cant_unset_delays(app, admin_user):
def test_options_events_agenda_delays(settings, app, admin_user):
settings.WORKING_DAY_CALENDAR = None
agenda = Agenda.objects.create(label=u'Foo bar')
assert agenda.minimal_booking_delay == 1
app = login(app)
url = '/manage/agendas/%s/booking-delays' % agenda.pk
resp = app.get(url)
assert 'minimal_booking_delay_in_working_days' not in resp.context['form'].fields
resp.form['minimal_booking_delay'] = None
resp = resp.form.submit()
agenda = Agenda.objects.get(label=u'Foo bar')
agenda.refresh_from_db()
assert agenda.minimal_booking_delay == 1
settings.WORKING_DAY_CALENDAR = 'workalendar.europe.France'
resp = app.get(url)
resp.form['minimal_booking_delay_in_working_days'] = True
resp = resp.form.submit()
agenda.refresh_from_db()
assert agenda.minimal_booking_delay_in_working_days is True
def test_options_virtual_agenda_can_unset_delays(app, admin_user):
def test_options_meetings_agenda_delays(app, admin_user):
agenda = Agenda.objects.create(label=u'Foo bar', kind='meetings', maximal_booking_delay=2)
assert agenda.maximal_booking_delay == 2
app = login(app)
url = '/manage/agendas/%s/booking-delays' % agenda.pk
resp = app.get(url)
assert 'minimal_booking_delay_in_working_days' not in resp.context['form'].fields
resp.form['maximal_booking_delay'] = None
resp = resp.form.submit()
agenda.refresh_from_db()
assert agenda.maximal_booking_delay == 2
def test_options_virtual_agenda_delays(app, admin_user):
agenda = Agenda.objects.create(label=u'Foo bar', kind='virtual', maximal_booking_delay=2)
assert agenda.maximal_booking_delay == 2
app = login(app)
url = '/manage/agendas/%s/booking-delays' % agenda.pk
resp = app.get(url)
assert 'minimal_booking_delay_in_working_days' not in resp.context['form'].fields
resp.form['maximal_booking_delay'] = None
resp = resp.form.submit()
agenda = Agenda.objects.get(label=u'Foo bar')
agenda.refresh_from_db()
assert agenda.maximal_booking_delay is None

View File

@ -196,6 +196,27 @@ def test_absence_reason_group_duplicate_slugs():
assert group.slug == 'foo-baz-2'
@pytest.mark.freeze_time('2021-07-09')
def test_agenda_minimal_booking_delay_in_working_days(settings):
agenda = Agenda.objects.create(label='Agenda', minimal_booking_delay=1)
settings.WORKING_DAY_CALENDAR = None
agenda.minimal_booking_delay_in_working_days = True
agenda.save()
assert agenda.min_booking_datetime.date() == datetime.date(2021, 7, 10)
agenda.minimal_booking_delay_in_working_days = False
agenda.save()
assert agenda.min_booking_datetime.date() == datetime.date(2021, 7, 10)
settings.WORKING_DAY_CALENDAR = 'workalendar.europe.France'
agenda.minimal_booking_delay_in_working_days = True
agenda.save()
assert agenda.min_booking_datetime.date() == datetime.date(2021, 7, 12)
agenda.minimal_booking_delay_in_working_days = False
agenda.save()
assert agenda.min_booking_datetime.date() == datetime.date(2021, 7, 10)
@pytest.mark.parametrize('with_prefetch', [True, False])
def test_agenda_is_available_for_simple_management(settings, with_prefetch):
settings.EXCEPTIONS_SOURCES = {

View File

@ -150,6 +150,7 @@ def test_import_export_events_agenda_options(app):
kind='events',
default_view='open_events',
booking_form_url='{{ eservices_url }}backoffice/submission/inscription-aux-activites/',
minimal_booking_delay_in_working_days=True,
)
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
@ -166,6 +167,7 @@ def test_import_export_events_agenda_options(app):
agenda = Agenda.objects.first()
assert agenda.default_view == 'open_events'
assert agenda.booking_form_url == '{{ eservices_url }}backoffice/submission/inscription-aux-activites/'
assert agenda.minimal_booking_delay_in_working_days is True
def test_import_export_event_details(app):