agendas: add kind field to CheckType model (#63810)
This commit is contained in:
parent
4547d00787
commit
ae28ec5858
|
@ -0,0 +1,21 @@
|
|||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('agendas', '0119_check_types'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='checktype',
|
||||
name='kind',
|
||||
field=models.CharField(
|
||||
choices=[('absence', 'Absence'), ('presence', 'Presence')],
|
||||
default='absence',
|
||||
max_length=8,
|
||||
verbose_name='Kind',
|
||||
),
|
||||
),
|
||||
]
|
|
@ -3075,10 +3075,25 @@ class CheckTypeGroup(models.Model):
|
|||
}
|
||||
|
||||
|
||||
class CheckTypeManager(models.Manager):
|
||||
def absences(self):
|
||||
return self.filter(kind='absence')
|
||||
|
||||
def presences(self):
|
||||
return self.filter(kind='presence')
|
||||
|
||||
|
||||
class CheckType(models.Model):
|
||||
group = models.ForeignKey(CheckTypeGroup, on_delete=models.CASCADE, related_name='check_types')
|
||||
slug = models.SlugField(_('Identifier'), max_length=160)
|
||||
label = models.CharField(_('Label'), max_length=150)
|
||||
kind = models.CharField(
|
||||
_('Kind'),
|
||||
max_length=8,
|
||||
choices=[('absence', _('Absence')), ('presence', _('Presence'))],
|
||||
default='absence',
|
||||
)
|
||||
objects = CheckTypeManager()
|
||||
|
||||
class Meta:
|
||||
ordering = ['label']
|
||||
|
@ -3105,6 +3120,7 @@ class CheckType(models.Model):
|
|||
return {
|
||||
'label': self.label,
|
||||
'slug': self.slug,
|
||||
'kind': self.kind,
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ class BookingSerializer(serializers.ModelSerializer):
|
|||
if not self.instance.event.agenda.check_type_group:
|
||||
raise serializers.ValidationError(_('unknown absence reason'))
|
||||
|
||||
check_types_qs = self.instance.event.agenda.check_type_group.check_types
|
||||
check_types_qs = self.instance.event.agenda.check_type_group.check_types.absences()
|
||||
try:
|
||||
check_type = check_types_qs.get(slug=value)
|
||||
value = check_type.label
|
||||
|
|
|
@ -383,6 +383,7 @@ def get_agenda_detail(request, agenda, check_events=False):
|
|||
agenda_detail['absence_reasons'] = [
|
||||
{'id': r.slug, 'slug': r.slug, 'text': r.label, 'label': r.label}
|
||||
for r in agenda.check_type_group.check_types.all()
|
||||
if r.kind == 'absence'
|
||||
]
|
||||
elif agenda.accept_meetings():
|
||||
agenda_detail['api'] = {
|
||||
|
@ -2328,6 +2329,10 @@ class BookingAPI(APIView):
|
|||
):
|
||||
raise APIErrorBadRequest(N_('event is marked as checked'), err=5)
|
||||
|
||||
user_was_present = serializer.validated_data.get('user_was_present', self.booking.user_was_present)
|
||||
if user_was_present is True and 'user_absence_reason' in request.data:
|
||||
raise APIErrorBadRequest(N_('user is marked as present, can not set absence reason'), err=6)
|
||||
|
||||
serializer.save()
|
||||
extra_data = {k: v for k, v in request.data.items() if k not in serializer.validated_data}
|
||||
if extra_data:
|
||||
|
|
|
@ -447,7 +447,7 @@ class BookingCheckFilterSet(django_filters.FilterSet):
|
|||
if self.agenda.check_type_group:
|
||||
status_choices += [
|
||||
('absence-%s' % r.label, _('Absence (%s)') % r.label)
|
||||
for r in self.agenda.check_type_group.check_types.all()
|
||||
for r in self.agenda.check_type_group.check_types.absences()
|
||||
]
|
||||
self.filters['booking-status'] = django_filters.ChoiceFilter(
|
||||
label=_('Filter by status'),
|
||||
|
@ -499,7 +499,7 @@ class BookingCheckAbsenceForm(forms.Form):
|
|||
super().__init__(*args, **kwargs)
|
||||
if agenda.check_type_group:
|
||||
self.fields['check_type'].choices = [('', '---------')] + [
|
||||
(r.label, r.label) for r in agenda.check_type_group.check_types.all()
|
||||
(r.label, r.label) for r in agenda.check_type_group.check_types.absences()
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -28,9 +28,15 @@
|
|||
</h3>
|
||||
<div>
|
||||
<ul class="objects-list single-links">
|
||||
{% for check_type in object.check_types.all %}
|
||||
{% for check_type in object.check_types.absences %}
|
||||
<li>
|
||||
<a rel="popup" href="{% url 'chrono-manager-check-type-edit' object.pk check_type.pk %}">{{ check_type }}</a>
|
||||
<a rel="popup" href="{% url 'chrono-manager-check-type-edit' object.pk check_type.pk %}">{% trans "Absence" %} - {{ check_type }}</a>
|
||||
<a class="delete" rel="popup" href="{% url 'chrono-manager-check-type-delete' object.pk check_type.pk %}">{% trans "delete"%}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% for check_type in object.check_types.presences %}
|
||||
<li>
|
||||
<a rel="popup" href="{% url 'chrono-manager-check-type-edit' object.pk check_type.pk %}">{% trans "Presence" %} - {{ check_type }}</a>
|
||||
<a class="delete" rel="popup" href="{% url 'chrono-manager-check-type-delete' object.pk check_type.pk %}">{% trans "delete"%}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<button class="submit-button"
|
||||
{% if booking.user_was_present is False %}disabled{% endif %}
|
||||
>{% trans "Absence" %}</button>
|
||||
{% if booking.form.reason.field.choices.1 %}{{ booking.form.reason }}{% endif %}
|
||||
{% if booking.form.check_type.field.choices.1 %}{{ booking.form.check_type }}{% endif %}
|
||||
<script>
|
||||
$(function() {
|
||||
$('td[data-booking-id="{{ booking.id }}"] select').on('change',
|
||||
|
|
|
@ -40,9 +40,24 @@
|
|||
{% if agenda.check_type_group %}
|
||||
<li>{% trans "Check type group:" %} {{ agenda.check_type_group }}
|
||||
<ul>
|
||||
{% for check_type in agenda.check_type_group.check_types.all %}
|
||||
<li>{{ check_type }}</li>
|
||||
{% endfor %}
|
||||
<li>{% trans "Absences:" %}
|
||||
<ul>
|
||||
{% for check_type in agenda.check_type_group.check_types.absences %}
|
||||
<li>{{ check_type }}</li>
|
||||
{% empty %}
|
||||
<li>({% trans "No absence check type defined" %})</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
<li>{% trans "Presences:" %}
|
||||
<ul>
|
||||
{% for check_type in agenda.check_type_group.check_types.presences %}
|
||||
<li>{{ check_type }}</li>
|
||||
{% empty %}
|
||||
<li>({% trans "No presence check type defined" %})</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
{% else %}
|
||||
|
|
|
@ -522,7 +522,7 @@ def test_booking_patch_api_present(app, user, flag):
|
|||
def test_booking_patch_api_absence_reason(app, user):
|
||||
agenda = Agenda.objects.create(kind='events')
|
||||
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
|
||||
booking = Booking.objects.create(event=event, user_was_present=True)
|
||||
booking = Booking.objects.create(event=event, user_was_present=False)
|
||||
|
||||
app.authorization = ('Basic', ('john.doe', 'password'))
|
||||
|
||||
|
@ -534,7 +534,8 @@ def test_booking_patch_api_absence_reason(app, user):
|
|||
assert resp.json['err_desc'] == 'invalid payload'
|
||||
|
||||
group = CheckTypeGroup.objects.create(label='Foo')
|
||||
check_type = CheckType.objects.create(group=group, label='Foo bar')
|
||||
check_type_absence = CheckType.objects.create(group=group, label='Foo bar', kind='absence')
|
||||
check_type_presence = CheckType.objects.create(group=group, label='Foo baz', kind='presence')
|
||||
|
||||
resp = app.patch_json(
|
||||
'/api/booking/%s/' % booking.pk, params={'user_absence_reason': 'foobar'}, status=400
|
||||
|
@ -542,23 +543,32 @@ def test_booking_patch_api_absence_reason(app, user):
|
|||
assert resp.json['err'] == 4
|
||||
assert resp.json['err_desc'] == 'invalid payload'
|
||||
|
||||
# wrong kind
|
||||
resp = app.patch_json(
|
||||
'/api/booking/%s/' % booking.pk, params={'user_absence_reason': 'Foo baz'}, status=400
|
||||
)
|
||||
assert resp.json['err'] == 4
|
||||
assert resp.json['err_desc'] == 'invalid payload'
|
||||
resp = app.patch_json(
|
||||
'/api/booking/%s/' % booking.pk, params={'user_absence_reason': check_type_presence.slug}, status=400
|
||||
)
|
||||
assert resp.json['err'] == 4
|
||||
assert resp.json['err_desc'] == 'invalid payload'
|
||||
|
||||
# set check_type
|
||||
agenda.check_type_group = group
|
||||
agenda.save()
|
||||
# it works with label
|
||||
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_absence_reason': 'Foo bar'})
|
||||
booking.refresh_from_db()
|
||||
assert booking.user_was_present is True # not changed
|
||||
assert booking.user_check_type == 'Foo bar'
|
||||
|
||||
# reset
|
||||
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_absence_reason': ''})
|
||||
booking.refresh_from_db()
|
||||
assert booking.user_was_present is True # not changed
|
||||
assert booking.user_check_type == ''
|
||||
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_absence_reason': None})
|
||||
booking.refresh_from_db()
|
||||
assert booking.user_was_present is True # not changed
|
||||
assert booking.user_check_type == ''
|
||||
|
||||
# make secondary bookings
|
||||
|
@ -568,33 +578,48 @@ def test_booking_patch_api_absence_reason(app, user):
|
|||
other_booking = Booking.objects.create(event=event)
|
||||
|
||||
# it works also with slug
|
||||
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_absence_reason': check_type.slug})
|
||||
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_absence_reason': check_type_absence.slug})
|
||||
booking.refresh_from_db()
|
||||
assert booking.user_was_present is True # not changed
|
||||
assert booking.user_check_type == 'Foo bar'
|
||||
# all secondary bookings are upadted
|
||||
# all secondary bookings are updated
|
||||
assert list(booking.secondary_booking_set.values_list('user_check_type', flat=True)) == [
|
||||
'Foo bar',
|
||||
'Foo bar',
|
||||
]
|
||||
assert list(booking.secondary_booking_set.values_list('user_was_present', flat=True)) == [
|
||||
False,
|
||||
False,
|
||||
] # not changed
|
||||
other_booking.refresh_from_db()
|
||||
assert other_booking.user_check_type == '' # not changed
|
||||
|
||||
# user_was_present is True, can not set user_absence_reason
|
||||
Booking.objects.update(user_was_present=True)
|
||||
resp = app.patch_json(
|
||||
'/api/booking/%s/' % booking.pk, params={'user_absence_reason': check_type_absence.slug}, status=400
|
||||
)
|
||||
assert resp.json['err'] == 6
|
||||
assert resp.json['err_desc'] == 'user is marked as present, can not set absence reason'
|
||||
|
||||
# but it's ok if user_was_present is set to False
|
||||
resp = app.patch_json(
|
||||
'/api/booking/%s/' % booking.pk,
|
||||
params={'user_absence_reason': check_type_absence.slug, 'user_was_present': False},
|
||||
)
|
||||
assert resp.json['err'] == 0
|
||||
booking.refresh_from_db()
|
||||
assert booking.user_was_present is False
|
||||
assert booking.user_check_type == 'Foo bar'
|
||||
|
||||
# mark the event as checked
|
||||
event.checked = True
|
||||
event.save()
|
||||
resp = app.patch_json('/api/booking/%s/' % booking.pk, params={'user_absence_reason': check_type.slug})
|
||||
resp = app.patch_json(
|
||||
'/api/booking/%s/' % booking.pk, params={'user_absence_reason': check_type_absence.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': check_type.slug}, status=400
|
||||
'/api/booking/%s/' % booking.pk, params={'user_absence_reason': check_type_absence.slug}, status=400
|
||||
)
|
||||
assert resp.json['err'] == 5
|
||||
assert resp.json['err_desc'] == 'event is marked as checked'
|
||||
|
|
|
@ -101,6 +101,7 @@ def test_add_check_type(app, admin_user):
|
|||
assert check_type.label == 'Foo reason'
|
||||
assert check_type.group == group
|
||||
assert check_type.slug == 'foo-reason'
|
||||
assert check_type.kind == 'absence'
|
||||
|
||||
|
||||
def test_add_check_type_as_manager(app, manager_user, agenda_with_restrictions):
|
||||
|
@ -112,7 +113,7 @@ def test_add_check_type_as_manager(app, manager_user, agenda_with_restrictions):
|
|||
|
||||
def test_edit_check_type(app, admin_user):
|
||||
group = CheckTypeGroup.objects.create(label='Foo bar')
|
||||
check_type = CheckType.objects.create(label='Foo reason', group=group)
|
||||
check_type = CheckType.objects.create(label='Foo reason', group=group, kind='presence')
|
||||
check_type2 = CheckType.objects.create(label='Baz', group=group)
|
||||
group2 = CheckTypeGroup.objects.create(label='Foo bar')
|
||||
check_type3 = CheckType.objects.create(label='Foo bar reason', group=group2)
|
||||
|
@ -131,6 +132,7 @@ def test_edit_check_type(app, admin_user):
|
|||
check_type.refresh_from_db()
|
||||
assert check_type.label == 'Foo bar reason'
|
||||
assert check_type.slug == 'foo-bar-reason'
|
||||
assert check_type.kind == 'presence'
|
||||
|
||||
app.get('/manage/check-type/group/%s/%s/edit/' % (group2.pk, check_type.pk), status=404)
|
||||
|
||||
|
|
Loading…
Reference in New Issue