Projet

Général

Profil

0001-agendas-add-a-disabled-flag-on-MeetingType-44132.patch

Emmanuel Cazenave, 17 juin 2020 13:17

Télécharger (9,9 ko)

Voir les différences:

Subject: [PATCH] agendas: add a 'disabled' flag on MeetingType (#44132)

 .../0047_meeting_type_disabled_flag.py        | 21 +++++++++++
 chrono/agendas/models.py                      |  9 ++---
 chrono/api/views.py                           |  2 +-
 chrono/manager/forms.py                       | 14 ++++++--
 tests/test_api.py                             | 35 ++++++++++++++++++-
 tests/test_manager.py                         | 33 +++++++++++++++--
 6 files changed, 102 insertions(+), 12 deletions(-)
 create mode 100644 chrono/agendas/migrations/0047_meeting_type_disabled_flag.py
chrono/agendas/migrations/0047_meeting_type_disabled_flag.py
1
# -*- coding: utf-8 -*-
2
# Generated by Django 1.11.18 on 2020-06-16 11:52
3
from __future__ import unicode_literals
4

  
5
from django.db import migrations, models
6

  
7

  
8
class Migration(migrations.Migration):
9

  
10
    dependencies = [
11
        ('agendas', '0046_event_duration'),
12
    ]
13

  
14
    operations = [
15
        migrations.AddField(
16
            model_name='meetingtype',
17
            name='disabled',
18
            field=models.BooleanField(default=False),
19
            verbose_name='Disabled',
20
        ),
21
    ]
chrono/agendas/models.py
172 172
        the real ones shared by every real agendas.
173 173
        """
174 174
        if self.kind == 'virtual':
175
            base_qs = MeetingType.objects.filter(agenda__virtual_agendas__in=[self])
175
            base_qs = MeetingType.objects.filter(agenda__virtual_agendas__in=[self], disabled=False)
176 176
            real_agendas = self.real_agendas
177 177
            if excluded_agenda:
178 178
                base_qs = base_qs.exclude(agenda=excluded_agenda)
......
187 187
                for mt in queryset.order_by('slug')
188 188
            ]
189 189

  
190
        return self.meetingtype_set.all().order_by('slug')
190
        return self.meetingtype_set.filter(disabled=False).all().order_by('slug')
191 191

  
192 192
    def get_meetingtype(self, id_=None, slug=None):
193 193
        match = id_ or slug
......
205 205
            return meeting_type
206 206

  
207 207
        if id_:
208
            return MeetingType.objects.get(id=id_, agenda=self)
209
        return MeetingType.objects.get(slug=slug, agenda=self)
208
            return MeetingType.objects.get(id=id_, agenda=self, disabled=False)
209
        return MeetingType.objects.get(slug=slug, agenda=self, disabled=False)
210 210

  
211 211
    def get_virtual_members(self):
212 212
        return VirtualMember.objects.filter(virtual_agenda=self)
......
637 637
    label = models.CharField(_('Label'), max_length=150)
638 638
    slug = models.SlugField(_('Identifier'), max_length=160)
639 639
    duration = models.IntegerField(_('Duration (in minutes)'), default=30)
640
    disabled = models.BooleanField(_('Disabled'), default=False)
640 641

  
641 642
    class Meta:
642 643
        ordering = ['duration', 'label']
chrono/api/views.py
451 451
        try:
452 452
            if agenda_identifier is None:
453 453
                # legacy access by meeting id
454
                meeting_type = MeetingType.objects.get(id=meeting_identifier)
454
                meeting_type = MeetingType.objects.get(id=meeting_identifier, disabled=False)
455 455
                agenda = meeting_type.agenda
456 456
            else:
457 457
                agenda = Agenda.objects.get(slug=agenda_identifier)
chrono/manager/forms.py
148 148
                    and mt.slug == self.instance.slug
149 149
                    and mt.duration == self.instance.duration
150 150
                ):
151
                    raise ValidationError(
152
                        _('This meetingtype is used by a virtual agenda: %s' % virtual_agenda)
153
                    )
151
                    # edited meeting type is used by a virtual agenda
152
                    # can't change it
153
                    if (
154
                        self.cleaned_data['disabled'] is True
155
                        or mt.label != self.cleaned_data['label']
156
                        or mt.slug != self.cleaned_data['slug']
157
                        or mt.duration != self.cleaned_data['duration']
158
                    ):
159
                        raise ValidationError(
160
                            _('This meetingtype is used by a virtual agenda: %s' % virtual_agenda)
161
                        )
154 162

  
155 163

  
156 164
class TimePeriodAddForm(forms.Form):
tests/test_api.py
231 231

  
232 232
def test_agendas_meetingtypes_api(app, some_data, meetings_agenda):
233 233
    resp = app.get('/api/agenda/%s/meetings/' % meetings_agenda.slug)
234
    assert resp.json == {
234
    expected_resp = {
235 235
        'data': [
236 236
            {
237 237
                'text': 'Blah',
......
243 243
            }
244 244
        ]
245 245
    }
246
    assert resp.json == expected_resp
247

  
248
    # disabled meeting type does not show up
249
    MeetingType.objects.create(
250
        agenda=meetings_agenda, slug='disabled-meeting-type', duration=43, disabled=True
251
    )
252
    resp = app.get('/api/agenda/%s/meetings/' % meetings_agenda.slug)
253
    assert resp.json == expected_resp
246 254

  
247 255
    # wrong kind
248 256
    agenda1 = Agenda.objects.filter(label=u'Foo bar')[0]
......
2950 2958
    assert len(resp.json['data']) == 0
2951 2959

  
2952 2960

  
2961
def test_agenda_meeting_disabled_meetingtype(app, meetings_agenda, user):
2962
    MeetingType.objects.all().delete()
2963
    meeting_type = MeetingType.objects.create(
2964
        agenda=meetings_agenda, label='Blah 20', duration=20, disabled=True
2965
    )
2966
    resp = app.get(
2967
        '/api/agenda/%s/meetings/%s/datetimes/' % (meetings_agenda.slug, meeting_type.slug), status=404
2968
    )
2969

  
2970
    meeting_type.disabled = False
2971
    meeting_type.save()
2972
    resp = app.get('/api/agenda/%s/meetings/%s/datetimes/' % (meetings_agenda.slug, meeting_type.slug))
2973
    data = resp.json['data']
2974
    assert len(data) == 216
2975

  
2976
    # try to book if disabled
2977
    meeting_type.disabled = True
2978
    meeting_type.save()
2979

  
2980
    fillslot_url = data[0]['api']['fillslot_url']
2981
    app.authorization = ('Basic', ('john.doe', 'password'))
2982
    resp_booking = app.post(fillslot_url, status=400)
2983
    assert 'invalid meeting type id' in resp_booking.json['err_desc']
2984

  
2985

  
2953 2986
def test_datetimes_api_meetings_agenda_start_hour_change(app, meetings_agenda):
2954 2987
    meeting_type = MeetingType.objects.get(agenda=meetings_agenda)
2955 2988
    api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (meeting_type.agenda.slug, meeting_type.slug)
tests/test_manager.py
1385 1385
    resp.form['label'] = 'Blah'
1386 1386
    resp.form['duration'] = '60'
1387 1387
    resp = resp.form.submit()
1388
    assert MeetingType.objects.get(agenda=agenda).label == 'Blah'
1389
    assert MeetingType.objects.get(agenda=agenda).duration == 60
1388
    meeeting_type = MeetingType.objects.get(agenda=agenda)
1389
    assert meeeting_type.label == 'Blah'
1390
    assert meeeting_type.duration == 60
1391
    assert meeeting_type.disabled is False
1390 1392
    resp = resp.follow()
1391 1393
    assert 'Blah' in resp.text
1392 1394

  
1393 1395
    # and edit
1394 1396
    resp = resp.click('Blah')
1395 1397
    resp.form['duration'] = '30'
1398
    resp.form['disabled'] = True
1396 1399
    resp = resp.form.submit()
1397
    assert MeetingType.objects.get(agenda=agenda).duration == 30
1400
    meeeting_type = MeetingType.objects.get(agenda=agenda)
1401
    assert meeeting_type.duration == 30
1402
    assert meeeting_type.disabled is True
1398 1403

  
1399 1404

  
1400 1405
def test_meetings_agenda_delete_meeting_type(app, admin_user):
......
3230 3235
    assert mt.label == 'MTT'
3231 3236

  
3232 3237

  
3238
def test_cant_disable_meetingtype_used_by_virtual_agenda(app, admin_user):
3239
    agenda = Agenda.objects.create(label='My Virtual agenda', kind='virtual')
3240
    meeting_agenda_1 = Agenda.objects.create(label='Meeting agenda 1', kind='meetings')
3241
    meeting_agenda_2 = Agenda.objects.create(label='Meeting agenda 1', kind='meetings')
3242
    MeetingType.objects.create(agenda=meeting_agenda_1, label='MT', slug='mt', duration=10)
3243
    mt2 = MeetingType.objects.create(agenda=meeting_agenda_2, label='MT', slug='mt', duration=10)
3244
    VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=meeting_agenda_1)
3245
    VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=meeting_agenda_2)
3246

  
3247
    app = login(app)
3248
    # can't disable a meeting type used by virtual agenda
3249
    resp = app.get('/manage/meetingtypes/%s/edit' % mt2.pk)
3250
    resp.form['disabled'].value = True
3251
    resp = resp.form.submit()
3252
    assert 'This meetingtype is used by a virtual agenda' in resp.text
3253

  
3254
    # enable it back
3255
    resp.form['disabled'].value = False
3256
    resp = resp.form.submit()
3257
    assert 'This meetingtype is used by a virtual agenda' not in resp.text
3258

  
3259

  
3233 3260
def test_cant_add_meetingtype_if_virtual_agenda(app, admin_user):
3234 3261
    agenda = Agenda.objects.create(label='My Virtual agenda', kind='virtual')
3235 3262
    meeting_agenda_1 = Agenda.objects.create(label='Meeting agenda 1', kind='meetings')
3236
-