0001-agendas-add-a-disabled-flag-on-MeetingType-44132.patch
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 |
- |