agenda: option to disable check update when event is checked (#53933)
This commit is contained in:
parent
8104efa1e2
commit
e8c683fb91
|
@ -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',
|
||||
),
|
||||
),
|
||||
|
|
|
@ -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'
|
||||
),
|
||||
),
|
||||
]
|
|
@ -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,
|
||||
|
|
|
@ -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 {})
|
||||
|
|
|
@ -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})}
|
||||
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue