agenda: option to disable check update when event is checked (#53933)

This commit is contained in:
Lauréline Guérin 2021-06-29 16:43:26 +02:00
parent 8104efa1e2
commit e8c683fb91
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
12 changed files with 171 additions and 18 deletions

View File

@ -2,6 +2,8 @@
from django.db import migrations, models
import chrono.agendas.models
class Migration(migrations.Migration):
@ -15,8 +17,15 @@ class Migration(migrations.Migration):
name='event_display_template',
field=models.CharField(
blank=True,
help_text='By default event labels will be displayed to users. This allows for a custom template to include additional informations. For example, "{{ event.label }} - {{ event.start_datetime }}" will show event datetime after label. Available variables: event.label (label), event.start_datetime (start date/time), event.places (places), event.remaining_places (remaining places), event.duration (duration), event.pricing (pricing).',
help_text=(
'By default event labels will be displayed to users. '
'This allows for a custom template to include additional informations. '
'For example, "{{ event.label }} - {{ event.start_datetime }}" will show event datetime after label. '
'Available variables: event.label (label), event.start_datetime (start date/time), event.places (places), '
'event.remaining_places (remaining places), event.duration (duration), event.pricing (pricing).'
),
max_length=256,
validators=[chrono.agendas.models.event_template_validator],
verbose_name='Event display template',
),
),

View File

@ -0,0 +1,18 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('agendas', '0095_checked'),
]
operations = [
migrations.AddField(
model_name='agenda',
name='disable_check_update',
field=models.BooleanField(
default=False, verbose_name='Prevent the check of bookings when event was marked as checked'
),
),
]

View File

@ -223,6 +223,9 @@ class Agenda(models.Model):
mark_event_checked_auto = models.BooleanField(
_('Automatically mark event as checked when all bookings have been checked'), default=False
)
disable_check_update = models.BooleanField(
_('Prevent the check of bookings when event was marked as checked'), default=False
)
booking_check_filters = models.CharField(
_('Filters'),
max_length=250,

View File

@ -1798,6 +1798,21 @@ class BookingAPI(APIView):
status=status.HTTP_400_BAD_REQUEST,
)
if (
self.booking.event.checked
and self.booking.event.agenda.disable_check_update
and ('user_was_present' in request.data or 'user_absence_reason' in request.data)
):
return Response(
{
'err': 5,
'err_class': 'event is marked as checked',
'err_desc': _('event is marked as checked'),
'errors': serializer.errors,
},
status=status.HTTP_400_BAD_REQUEST,
)
if 'extra_data' in serializer.validated_data:
extra_data = self.booking.extra_data or {}
extra_data.update(serializer.validated_data['extra_data'] or {})

View File

@ -837,6 +837,7 @@ class AgendaBookingCheckSettingsForm(forms.ModelForm):
'booking_check_filters',
'booking_user_block_template',
'mark_event_checked_auto',
'disable_check_update',
]
widgets = {'booking_user_block_template': forms.Textarea(attrs={'rows': 3})}

View File

@ -38,6 +38,7 @@
</tr>
{% endif %}
{% if booked_without_status %}
{% if not event.checked or not agenda.disable_check_update %}
<tr class="booking all-bookings">
<td colspan="2"><b>{% trans "Mark all bookings without status:" %}</b></td>
<td class="booking-actions">
@ -60,6 +61,7 @@
</form>
</td>
</tr>
{% endif %}
{% endif %}
{% for booking in booked %}
<tr class="booking">

View File

@ -7,6 +7,7 @@
({{ booking.user_absence_reason }})
{% endif %}
</td>
{% if not event.checked or not agenda.disable_check_update %}
<td class="booking-actions" data-booking-id="{{ booking.id }}">
<form method="post" action="{% url 'chrono-manager-booking-presence' pk=agenda.pk booking_pk=booking.pk %}" class="with-ajax">
{% csrf_token %}
@ -30,3 +31,4 @@
</script>
</form>
</td>
{% endif %}

View File

@ -35,36 +35,43 @@
<a rel="popup" class="button" href="{% url 'chrono-manager-agenda-booking-check-settings' pk=object.pk %}">{% trans 'Configure' %}</a>
</h3>
<div>
<ul>
{% if has_absence_reasons %}
{% if agenda.absence_reasons_group %}
<p>{% trans "Absence reasons group:" %} {{ agenda.absence_reasons_group }}</p>
<ul>
{% for reason in agenda.absence_reasons_group.absence_reasons.all %}
<li>{{ reason }}</li>
{% endfor %}
</ul>
<li>{% trans "Absence reasons group:" %} {{ agenda.absence_reasons_group }}
<ul>
{% for reason in agenda.absence_reasons_group.absence_reasons.all %}
<li>{{ reason }}</li>
{% endfor %}
</ul>
</li>
{% else %}
<p>{% trans "No absence reasons configured for this agenda." %}</p>
<li>{% trans "No absence reasons configured for this agenda." %}</li>
{% endif %}
{% endif %}
{% with agenda.get_booking_check_filters as check_filters %}
{% if check_filters %}
<p>{% trans "Filters:" %}</p>
<ul>
{% for key in check_filters %}
<li>{{ key }}</li>
{% endfor %}
</ul>
<li>{% trans "Filters:" %}
<ul>
{% for key in check_filters %}
<li>{{ key }}</li>
{% endfor %}
</ul>
</li>
{% else %}
<p>{% trans "No filters configured for this agenda." %}</p>
<li>{% trans "No filters configured for this agenda." %}</li>
{% endif %}
{% endwith %}
<p>{% trans "User block template:" %}</p>
<pre>{{ agenda.get_booking_user_block_template }}</pre>
<li>
{% trans "User block template:" %}
<pre>{{ agenda.get_booking_user_block_template }}</pre>
</li>
<p>{% trans "Automatically mark events when they are checked:" %} {{ agenda.mark_event_checked_auto|yesno }}</p>
<li>{% trans "Automatically mark event as checked when all bookings have been checked:" %} {{ agenda.mark_event_checked_auto|yesno }}</li>
<li>{% trans "Prevent the check of bookings when event was marked as checked:" %} {{ agenda.disable_check_update|yesno }}</li>
</ul>
</div>
</div>

View File

@ -2004,6 +2004,7 @@ class EventCheckMixin(object):
)
self.event = get_object_or_404(
Event,
Q(checked=False) | Q(agenda__disable_check_update=False),
pk=kwargs.get('event_pk'),
agenda=self.agenda,
start_datetime__date__lte=now().date(),
@ -2743,6 +2744,7 @@ class BookingCheckMixin(object):
def get_booking(self, **kwargs):
return get_object_or_404(
Booking,
Q(event__checked=False) | Q(event__agenda__disable_check_update=False),
pk=kwargs['booking_pk'],
event__agenda=self.agenda,
event__start_datetime__date__lte=now().date(),

View File

@ -448,6 +448,21 @@ def test_booking_patch_api_present(app, user, flag):
other_booking.refresh_from_db()
assert other_booking.user_was_present is None # not changed
# mark the event as checked
event.checked = True
event.save()
resp = app.patch_json('/api/booking/%s/' % booking.pk, params={'user_was_present': flag})
assert resp.json['err'] == 0
# now disable check update
agenda.disable_check_update = True
agenda.save()
resp = app.patch_json('/api/booking/%s/' % booking.pk, params={'user_was_present': flag}, status=400)
assert resp.json['err'] == 5
assert resp.json['err_desc'] == 'event is marked as checked'
resp = app.patch_json('/api/booking/%s/' % booking.pk)
assert resp.json['err'] == 0
def test_booking_patch_api_absence_reason(app, user):
agenda = Agenda.objects.create(kind='events')
@ -514,6 +529,23 @@ def test_booking_patch_api_absence_reason(app, user):
other_booking.refresh_from_db()
assert other_booking.user_absence_reason == '' # not changed
# mark the event as checked
event.checked = True
event.save()
resp = app.patch_json('/api/booking/%s/' % booking.pk, params={'user_absence_reason': reason.slug})
assert resp.json['err'] == 0
# now disable check update
agenda.disable_check_update = True
agenda.save()
resp = app.patch_json(
'/api/booking/%s/' % booking.pk, params={'user_absence_reason': reason.slug}, status=400
)
assert resp.json['err'] == 5
assert resp.json['err_desc'] == 'event is marked as checked'
resp = app.patch_json('/api/booking/%s/' % booking.pk)
assert resp.json['err'] == 0
def test_booking_patch_api_extra_data(app, user):
agenda = Agenda.objects.create(kind='events')

View File

@ -571,6 +571,14 @@ def test_options_agenda_booking_check_options(app, admin_user):
agenda.refresh_from_db()
assert agenda.mark_event_checked_auto is True
# check disable check
assert agenda.disable_check_update is False
resp = app.get(url)
resp.form['disable_check_update'] = True
resp = resp.form.submit()
agenda.refresh_from_db()
assert agenda.disable_check_update is True
# check kind
agenda.kind = 'meetings'
agenda.save()

View File

@ -1413,6 +1413,40 @@ def test_event_check_booking(app, admin_user):
assert booking.user_was_present is True
assert booking.user_absence_reason == ''
# mark the event as checked
event.checked = True
event.save()
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
assert '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk) in resp
assert '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk) in resp
resp = app.post(
'/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk),
params={'csrfmiddlewaretoken': token},
status=302,
)
app.post(
'/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk),
params={'csrfmiddlewaretoken': token},
status=302,
)
# now disable check update
agenda.disable_check_update = True
agenda.save()
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
assert '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk) not in resp
assert '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk) not in resp
resp = app.post(
'/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk),
params={'csrfmiddlewaretoken': token},
status=404,
)
app.post(
'/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk),
params={'csrfmiddlewaretoken': token},
status=404,
)
def test_event_check_booking_ajax(app, admin_user):
group = AbsenceReasonGroup.objects.create(label='Foo bar')
@ -1510,7 +1544,10 @@ def test_event_check_all_bookings(app, admin_user):
event.refresh_from_db()
assert event.checked is True
# event is checked
booking3 = Booking.objects.create(event=event, user_first_name='User', user_last_name='51')
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
assert 'Mark all bookings without status' in resp
app.post(
'/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk),
params={'csrfmiddlewaretoken': token, 'reason': 'Foo reason'},
@ -1524,3 +1561,20 @@ def test_event_check_all_bookings(app, admin_user):
booking3.refresh_from_db()
assert booking3.user_was_present is False
assert booking3.user_absence_reason == 'Foo reason'
# now disable check update
agenda.disable_check_update = True
agenda.save()
Booking.objects.create(event=event, user_first_name='User', user_last_name='52')
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
assert 'Mark all bookings without status' not in resp
app.post(
'/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk),
params={'csrfmiddlewaretoken': token, 'reason': 'Foo reason'},
status=404,
)
resp = app.post(
'/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk),
params={'csrfmiddlewaretoken': token},
status=404,
)