Projet

Général

Profil

0009-manager-simple-desk-management-exceptions-48924.patch

Lauréline Guérin, 05 février 2021 10:19

Télécharger (25,5 ko)

Voir les différences:

Subject: [PATCH 09/11] manager: simple desk management & exceptions (#48924)

 chrono/manager/forms.py |  69 ++++++++++--
 chrono/manager/views.py |  53 +++++----
 tests/test_manager.py   | 243 ++++++++++++++++++++++++++++++----------
 3 files changed, 280 insertions(+), 85 deletions(-)
chrono/manager/forms.py
345 345

  
346 346

  
347 347
class TimePeriodExceptionForm(forms.ModelForm):
348
    all_desks = forms.BooleanField(label=_('Apply exception on all desks of the agenda'), required=False)
349

  
350 348
    class Meta:
351 349
        model = TimePeriodException
352 350
        fields = ['start_datetime', 'end_datetime', 'label']
......
357 355

  
358 356
    def __init__(self, *args, **kwargs):
359 357
        super().__init__(*args, **kwargs)
360
        if self.instance.pk is not None:
361
            del self.fields['all_desks']
362
        elif self.instance.unavailability_calendar:
363
            del self.fields['all_desks']
364
        elif self.instance.desk_id and self.instance.desk.agenda.desk_set.count() == 1:
365
            del self.fields['all_desks']
358
        self.old_label = self.instance.label
359
        self.old_start_datetime = self.instance.start_datetime
360
        self.old_end_datetime = self.instance.end_datetime
366 361

  
367 362
    def clean(self):
368 363
        cleaned_data = super().clean()
......
373 368

  
374 369
        return cleaned_data
375 370

  
371
    def save(self):
372
        super().save()
373

  
374
        self.exceptions = [self.instance]
375
        desk_simple_management = False
376
        if self.instance.desk_id:
377
            desk_simple_management = self.instance.desk.agenda.desk_simple_management
378
        if desk_simple_management:
379
            for desk in self.instance.desk.agenda.desk_set.exclude(pk=self.instance.desk_id):
380
                exception = desk.timeperiodexception_set.filter(
381
                    source__isnull=True,
382
                    label=self.old_label,
383
                    start_datetime=self.old_start_datetime,
384
                    end_datetime=self.old_end_datetime,
385
                ).first()
386
                if exception is not None:
387
                    exception.label = self.instance.label
388
                    exception.start_datetime = self.instance.start_datetime
389
                    exception.end_datetime = self.instance.end_datetime
390
                    exception.save()
391
                    self.exceptions.append(exception)
392

  
393
        return self.instance
394

  
395

  
396
class NewTimePeriodExceptionForm(TimePeriodExceptionForm):
397
    all_desks = forms.BooleanField(label=_('Apply exception on all desks of the agenda'), required=False)
398

  
399
    def __init__(self, *args, **kwargs):
400
        super().__init__(*args, **kwargs)
401
        if self.instance.unavailability_calendar:
402
            del self.fields['all_desks']
403
        elif self.instance.desk_id and self.instance.desk.agenda.desk_set.count() == 1:
404
            del self.fields['all_desks']
405
        elif self.instance.desk_id and self.instance.desk.agenda.desk_simple_management:
406
            del self.fields['all_desks']
407

  
408
    def save(self):
409
        super().save()
410

  
411
        self.exceptions = [self.instance]
412
        all_desks = self.cleaned_data.get('all_desks')
413
        desk_simple_management = False
414
        if self.instance.desk_id:
415
            desk_simple_management = self.instance.desk.agenda.desk_simple_management
416
        if all_desks or desk_simple_management:
417
            for desk in self.instance.desk.agenda.desk_set.exclude(pk=self.instance.desk_id):
418
                self.exceptions.append(
419
                    TimePeriodException.objects.create(
420
                        desk=desk,
421
                        label=self.instance.label,
422
                        start_datetime=self.instance.start_datetime,
423
                        end_datetime=self.instance.end_datetime,
424
                    )
425
                )
426

  
427
        return self.instance
428

  
376 429

  
377 430
class VirtualMemberForm(forms.ModelForm):
378 431
    class Meta:
chrono/manager/views.py
86 86
    ImportEventsForm,
87 87
    NewDeskForm,
88 88
    DeskForm,
89
    NewTimePeriodExceptionForm,
89 90
    TimePeriodExceptionForm,
90 91
    ExceptionsImportForm,
91 92
    AgendasImportForm,
......
2040 2041
class AgendaAddTimePeriodExceptionView(ManagedDeskMixin, CreateView):
2041 2042
    template_name = 'chrono/manager_time_period_exception_form.html'
2042 2043
    model = TimePeriodException
2043
    form_class = TimePeriodExceptionForm
2044
    form_class = NewTimePeriodExceptionForm
2044 2045

  
2045 2046
    def get_context_data(self, **kwargs):
2046 2047
        context = super().get_context_data(**kwargs)
......
2050 2051

  
2051 2052
    def form_valid(self, form):
2052 2053
        result = super().form_valid(form)
2053
        exceptions = [self.object]
2054
        if form.cleaned_data.get('all_desks'):
2055
            for desk in Desk.objects.filter(agenda=self.object.desk.agenda_id):
2056
                if desk == self.object.desk:
2057
                    continue
2058
                exceptions.append(
2059
                    TimePeriodException.objects.create(
2060
                        desk=desk,
2061
                        label=self.object.label,
2062
                        start_datetime=self.object.start_datetime,
2063
                        end_datetime=self.object.end_datetime,
2064
                    )
2065
                )
2054
        all_desks = form.cleaned_data.get('all_desks')
2066 2055
        message = ungettext(
2067 2056
            'Exception added.',
2068 2057
            'Exceptions added.',
2069
            len(exceptions),
2058
            len(form.exceptions) if all_desks else 1,
2070 2059
        )
2071 2060
        messages.info(self.request, message)
2072
        for exception in exceptions:
2061
        for exception in form.exceptions:
2073 2062
            if exception.has_booking_within_time_slot():
2074 2063
                messages.warning(self.request, _('One or several bookings exists within this time slot.'))
2075 2064
                break
......
2101 2090

  
2102 2091
    def form_valid(self, form):
2103 2092
        result = super().form_valid(form)
2104
        if self.object.has_booking_within_time_slot():
2105
            messages.info(self.request, _('Exception updated.'))
2106
            messages.warning(self.request, _('One or several bookings exists within this time slot.'))
2093
        messages.info(self.request, _('Exception updated.'))
2094
        for exception in form.exceptions:
2095
            if exception.has_booking_within_time_slot():
2096
                messages.warning(self.request, _('One or several bookings exists within this time slot.'))
2097
                break
2107 2098
        return result
2108 2099

  
2109 2100

  
......
2159 2150
    def get_queryset(self):
2160 2151
        return super().get_queryset().filter(source__settings_slug__isnull=True)
2161 2152

  
2153
    def delete(self, request, *args, **kwargs):
2154
        exception = self.get_object()
2155
        response = super().delete(request, *args, **kwargs)
2156

  
2157
        if not exception.desk_id:
2158
            return response
2159

  
2160
        if not exception.desk.agenda.desk_simple_management:
2161
            return response
2162

  
2163
        for desk in exception.desk.agenda.desk_set.exclude(pk=exception.desk.pk):
2164
            exc = desk.timeperiodexception_set.filter(
2165
                source__isnull=True,
2166
                label=exception.label,
2167
                start_datetime=exception.start_datetime,
2168
                end_datetime=exception.end_datetime,
2169
            ).first()
2170
            if exc is not None:
2171
                exc.delete()
2172

  
2173
        return response
2174

  
2162 2175

  
2163 2176
time_period_exception_delete = TimePeriodExceptionDeleteView.as_view()
2164 2177

  
......
2565 2578

  
2566 2579
class UnavailabilityCalendarAddUnavailabilityView(ManagedUnavailabilityCalendarMixin, CreateView):
2567 2580
    template_name = 'chrono/manager_time_period_exception_form.html'
2568
    form_class = TimePeriodExceptionForm
2581
    form_class = NewTimePeriodExceptionForm
2569 2582
    model = TimePeriodException
2570 2583

  
2571 2584
    def get_form_kwargs(self):
tests/test_manager.py
2384 2384
def test_meetings_agenda_add_time_period_exception(app, admin_user):
2385 2385
    agenda = Agenda.objects.create(label=u'Foo bar', kind='meetings')
2386 2386
    desk = Desk.objects.create(agenda=agenda, label='Desk A')
2387
    meeting_type = MeetingType.objects.create(agenda=agenda, label='Blah')
2387
    desk2 = Desk.objects.create(agenda=agenda, label='Desk B')
2388

  
2388 2389
    app = login(app)
2389 2390
    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
2390
    resp = resp.click('Add a time period exception')
2391
    resp = resp.click('Add a time period exception', index=0)
2391 2392
    today = datetime.datetime.today().replace(hour=0, minute=0, second=0, microsecond=0)
2392 2393
    tomorrow = make_aware(today + datetime.timedelta(days=1))
2393 2394
    dt_format = '%Y-%m-%d %H:%M'
......
2398 2399
    resp.form['end_datetime_1'] = '16:00'
2399 2400
    resp = resp.form.submit().follow()
2400 2401
    assert TimePeriodException.objects.count() == 1
2402
    assert desk2.timeperiodexception_set.exists() is False
2401 2403
    time_period_exception = TimePeriodException.objects.first()
2402 2404
    assert localtime(time_period_exception.start_datetime).strftime(dt_format) == tomorrow.replace(
2403 2405
        hour=8
......
2421 2423
    assert 'Exception 1' in resp.text
2422 2424
    assert 'Exception 2' in resp.text
2423 2425

  
2426

  
2427
def test_meetings_agenda_add_time_period_exception_booking_overlaps(app, admin_user):
2428
    agenda = Agenda.objects.create(label=u'Foo bar', kind='meetings')
2429
    desk = Desk.objects.create(agenda=agenda, label='Desk A')
2430
    meeting_type = MeetingType.objects.create(agenda=agenda, label='Blah')
2431

  
2432
    # different type of overlap
2433
    # event.start_datetime <= exception.start_datetime < event.start_datetime + meeting_type.duration
2434
    event = Event.objects.create(
2435
        agenda=agenda,
2436
        places=1,
2437
        desk=desk,
2438
        meeting_type=meeting_type,
2439
        start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 30)),
2440
    )
2441
    Booking.objects.create(event=event)
2442
    app = login(app)
2443
    resp = app.get('/manage/agendas/%s/desk/%s/add-time-period-exception' % (agenda.pk, desk.pk))
2444
    resp.form['label'] = 'Exception'
2445
    resp.form['start_datetime_0'] = '2017-05-22'
2446
    resp.form['start_datetime_1'] = '10:45'
2447
    resp.form['end_datetime_0'] = '2017-05-22'
2448
    resp.form['end_datetime_1'] = '17:30'
2449
    resp = resp.form.submit().follow()
2450
    assert TimePeriodException.objects.count() == 1
2451
    assert 'Exception added.' in resp.text
2452
    assert 'One or several bookings exists within this time slot.' in resp.text
2453

  
2454

  
2455
def test_meetings_agenda_add_time_period_exception_all_desks(app, admin_user):
2456
    agenda = Agenda.objects.create(label=u'Foo bar', kind='meetings')
2457
    desk = Desk.objects.create(agenda=agenda, label='Desk A')
2458

  
2424 2459
    # add global time exception
2425 2460
    # only one desk: no option to apply to all desks
2461
    app = login(app)
2426 2462
    resp = app.get('/manage/agendas/%s/desk/%s/add-time-period-exception' % (agenda.pk, desk.pk))
2427 2463
    assert 'all_desks' not in resp.context['form'].fields
2428 2464
    # more than one desk
2465
    Desk.objects.create(agenda=agenda, label='Desk B')
2429 2466
    agenda2 = Agenda.objects.create(label='Foo bar', kind='meetings')
2430 2467
    Desk.objects.create(agenda=agenda2, label='Other Desk')  # check exception is not created for this one
2431
    desk2 = Desk.objects.create(agenda=agenda, label='Desk B')
2432 2468
    event = Event.objects.create(
2433
        agenda=agenda, places=1, desk=desk2, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 30))
2469
        agenda=agenda, places=1, desk=desk, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 30))
2434 2470
    )
2435 2471
    Booking.objects.create(event=event)
2436 2472
    resp = app.get('/manage/agendas/%s/desk/%s/add-time-period-exception' % (agenda.pk, desk.pk))
2437
    future = tomorrow + datetime.timedelta(days=35)
2438
    resp.form['label'] = 'Exception 3'
2473
    resp.form['label'] = 'Exception'
2439 2474
    resp.form['start_datetime_0'] = '2017-05-22'
2440 2475
    resp.form['start_datetime_1'] = '08:00'
2441 2476
    resp.form['end_datetime_0'] = '2017-05-26'
2442 2477
    resp.form['end_datetime_1'] = '17:30'
2443 2478
    resp.form['all_desks'] = True
2444 2479
    resp = resp.form.submit().follow()
2445
    assert TimePeriodException.objects.count() == 4
2480
    assert TimePeriodException.objects.count() == 2
2446 2481
    assert 'Exceptions added.' in resp.text
2447 2482
    assert 'One or several bookings exists within this time slot.' in resp.text
2448 2483

  
......
2450 2485
    resp = app.get('/manage/time-period-exceptions/%s/edit' % exception.pk)
2451 2486
    assert 'all_desks' not in resp.context['form'].fields
2452 2487

  
2453
    # different type of overlap
2454
    # event.start_datetime <= exception.start_datetime < event.start_datetime + meeting_type.duration
2455
    event = Event.objects.create(
2456
        agenda=agenda,
2457
        places=1,
2458
        desk=desk2,
2459
        meeting_type=meeting_type,
2460
        start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 30)),
2461
    )
2462
    Booking.objects.create(event=event)
2463
    resp = app.get('/manage/agendas/%s/desk/%s/add-time-period-exception' % (agenda.pk, desk2.pk))
2464
    resp.form['label'] = 'Exception 4'
2465
    resp.form['start_datetime_0'] = '2017-05-22'
2466
    resp.form['start_datetime_1'] = '10:45'
2467
    resp.form['end_datetime_0'] = '2017-05-22'
2468
    resp.form['end_datetime_1'] = '17:30'
2469
    resp.form['all_desks'] = False
2470
    resp = resp.form.submit().follow()
2471
    assert TimePeriodException.objects.count() == 5
2472
    assert 'Exception added.' in resp.text
2473
    assert 'One or several bookings exists within this time slot.' in resp.text
2474

  
2475 2488

  
2476 2489
def test_meetings_agenda_add_time_period_exception_when_booking_exists(app, admin_user):
2477 2490
    agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
......
2522 2535
    resp.form['end_datetime_0'] = '2017-05-26'
2523 2536
    resp.form['end_datetime_1'] = '17:30'
2524 2537
    resp = resp.form.submit().follow()
2525
    assert 'Exception added. Note: one or several bookings exists within this time slot.' not in resp.text
2538
    assert 'Exception added' in resp.text
2539
    assert 'One or several bookings exists within this time slot.' not in resp.text
2526 2540
    assert TimePeriodException.objects.count() == 1
2527 2541

  
2528 2542

  
2543
def test_meetings_agenda_add_time_period_exception_desk_simple_management(app, admin_user):
2544
    agenda = Agenda.objects.create(label='Foo bar', kind='meetings', desk_simple_management=True)
2545
    desk = Desk.objects.create(agenda=agenda, label='Desk A')
2546
    desk2 = Desk.objects.create(agenda=agenda, label='Desk B')
2547
    event = Event.objects.create(
2548
        agenda=agenda, places=1, desk=desk2, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 30))
2549
    )
2550
    Booking.objects.create(event=event)
2551
    assert agenda.is_available_for_simple_management() is True
2552

  
2553
    login(app)
2554
    resp = app.get('/manage/agendas/%s/desk/%s/add-time-period-exception' % (agenda.pk, desk.pk))
2555
    assert 'all_desks' not in resp.form.fields
2556
    resp.form['label'] = 'Exception'
2557
    resp.form['start_datetime_0'] = '2017-05-22'
2558
    resp.form['start_datetime_1'] = '8:00'
2559
    resp.form['end_datetime_0'] = '2017-05-22'
2560
    resp.form['end_datetime_1'] = '17:30'
2561
    resp = resp.form.submit().follow()
2562
    assert 'Exception added' in resp.text
2563
    assert 'One or several bookings exists within this time slot.' in resp.text
2564
    assert TimePeriodException.objects.count() == 2
2565
    assert agenda.is_available_for_simple_management() is True
2566

  
2567

  
2529 2568
def test_meetings_agenda_edit_time_period_exception(app, admin_user):
2569
    agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
2570
    desk = Desk.objects.create(agenda=agenda, label='Desk A')
2571
    exception = TimePeriodException.objects.create(
2572
        label='Exception',
2573
        desk=desk,
2574
        start_datetime=make_aware(datetime.datetime(2018, 12, 16, 5, 0)),
2575
        end_datetime=make_aware(datetime.datetime(2018, 12, 16, 23, 0)),
2576
    )
2577
    desk2 = desk.duplicate()
2578
    exception2 = desk2.timeperiodexception_set.get()
2579

  
2580
    login(app)
2581
    resp = app.get('/manage/time-period-exceptions/%s/edit' % exception.pk)
2582
    resp.form['start_datetime_1'] = '8:00'
2583
    resp.form.submit()
2584
    exception.refresh_from_db()
2585
    assert exception.start_datetime == make_aware(datetime.datetime(2018, 12, 16, 8, 0))
2586
    exception2.refresh_from_db()
2587
    assert exception2.start_datetime == make_aware(datetime.datetime(2018, 12, 16, 5, 0))
2588

  
2589

  
2590
def test_meetings_agenda_edit_time_period_exception_overlaps(app, admin_user):
2530 2591
    agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
2531 2592
    desk = Desk.objects.create(agenda=agenda, label='Desk A')
2532 2593
    calendar = UnavailabilityCalendar.objects.create(label='foo')
......
2543 2604
        start_datetime=make_aware(datetime.datetime(2018, 12, 16, 5, 0)),
2544 2605
        end_datetime=make_aware(datetime.datetime(2018, 12, 16, 23, 0)),
2545 2606
    )
2607
    login(app)
2546 2608
    for time_period_exception in (time_period_exception_desk, time_period_exception_calendar):
2547 2609
        event = Event.objects.create(
2548 2610
            agenda=agenda,
......
2551 2613
            start_datetime=make_aware(datetime.datetime(2018, 12, 16, 10, 30)),
2552 2614
        )
2553 2615

  
2554
        login(app)
2555 2616
        resp = app.get('/manage/time-period-exceptions/%s/edit' % time_period_exception.pk)
2556 2617
        resp = resp.form.submit().follow()
2557
        assert 'Exception updated.' not in resp.text
2558 2618
        assert 'One or several bookings exists within this time slot.' not in resp.text
2559 2619

  
2560 2620
        booking = Booking.objects.create(event=event)
2561 2621
        resp = app.get('/manage/time-period-exceptions/%s/edit' % time_period_exception.pk)
2562 2622
        resp = resp.form.submit().follow()
2563
        assert 'Exception updated.' in resp.text
2564 2623
        assert 'One or several bookings exists within this time slot.' in resp.text
2565 2624

  
2566 2625
        booking.cancel()
2567 2626
        resp = app.get('/manage/time-period-exceptions/%s/edit' % time_period_exception.pk)
2568 2627
        resp = resp.form.submit().follow()
2569
        assert 'Exception updated.' not in resp.text
2570 2628
        assert 'One or several bookings exists within this time slot.' not in resp.text
2571 2629

  
2572 2630
        booking.delete()
2573 2631
        event.delete()
2574 2632

  
2575 2633

  
2634
def test_meetings_agenda_edit_time_period_exception_desk_simple_management(app, admin_user):
2635
    agenda = Agenda.objects.create(label='Foo bar', kind='meetings', desk_simple_management=True)
2636
    desk = Desk.objects.create(agenda=agenda, label='Desk A')
2637
    exception = TimePeriodException.objects.create(
2638
        label='Exception',
2639
        desk=desk,
2640
        start_datetime=make_aware(datetime.datetime(2017, 5, 21, 5, 0)),
2641
        end_datetime=make_aware(datetime.datetime(2017, 5, 21, 23, 0)),
2642
    )
2643
    desk2 = desk.duplicate()
2644
    event = Event.objects.create(
2645
        agenda=agenda, places=1, desk=desk2, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 30))
2646
    )
2647
    Booking.objects.create(event=event)
2648
    exception2 = desk2.timeperiodexception_set.get()
2649
    assert agenda.is_available_for_simple_management() is True
2650

  
2651
    login(app)
2652
    resp = app.get('/manage/time-period-exceptions/%s/edit' % exception.pk)
2653
    resp.form['label'] = 'Exception foo bar'
2654
    resp.form['start_datetime_0'] = '2017-05-22'
2655
    resp.form['start_datetime_1'] = '8:00'
2656
    resp.form['end_datetime_0'] = '2017-05-22'
2657
    resp.form['end_datetime_1'] = '17:30'
2658
    resp = resp.form.submit().follow()
2659
    assert 'One or several bookings exists within this time slot.' in resp.text
2660
    exception.refresh_from_db()
2661
    exception2.refresh_from_db()
2662
    assert exception.label == 'Exception foo bar'
2663
    assert exception.start_datetime == make_aware(datetime.datetime(2017, 5, 22, 8, 0))
2664
    assert exception.end_datetime == make_aware(datetime.datetime(2017, 5, 22, 17, 30))
2665
    assert exception2.label == 'Exception foo bar'
2666
    assert exception2.start_datetime == make_aware(datetime.datetime(2017, 5, 22, 8, 0))
2667
    assert exception2.end_datetime == make_aware(datetime.datetime(2017, 5, 22, 17, 30))
2668
    assert agenda.is_available_for_simple_management() is True
2669

  
2670
    # should not happen: corresponding exception does not exist
2671
    exception2.delete()
2672
    resp = app.get('/manage/time-period-exceptions/%s/edit' % exception.pk)
2673
    resp.form['label'] = 'Exception'
2674
    resp.form['start_datetime_0'] = '2017-05-21'
2675
    resp.form['start_datetime_1'] = '9:00'
2676
    resp.form['end_datetime_0'] = '2017-05-21'
2677
    resp.form['end_datetime_1'] = '18:30'
2678
    # no error
2679
    resp.form.submit()
2680
    exception.refresh_from_db()
2681
    assert exception.label == 'Exception'
2682
    assert exception.start_datetime == make_aware(datetime.datetime(2017, 5, 21, 9, 0))
2683
    assert exception.end_datetime == make_aware(datetime.datetime(2017, 5, 21, 18, 30))
2684

  
2685

  
2576 2686
def test_meetings_agenda_add_invalid_time_period_exception():
2577 2687
    form = TimePeriodExceptionForm(
2578 2688
        data={
......
2611 2721
def test_meetings_agenda_delete_time_period_exception(app, admin_user):
2612 2722
    agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
2613 2723
    desk = Desk.objects.create(agenda=agenda, label='Desk A')
2614
    MeetingType(agenda=agenda, label='Blah').save()
2615
    TimePeriod.objects.create(
2616
        weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)
2724
    TimePeriodException.objects.create(
2725
        label='Exception Foo',
2726
        desk=desk,
2727
        start_datetime=now() + datetime.timedelta(days=1),
2728
        end_datetime=now() + datetime.timedelta(days=2),
2617 2729
    )
2730
    desk.duplicate()
2731
    assert TimePeriodException.objects.count() == 2
2732

  
2618 2733
    login(app)
2619 2734
    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
2620
    resp = resp.click('Add a time period exception')
2621
    today = datetime.datetime.today().replace(hour=0, minute=0, second=0, microsecond=0)
2622
    tomorrow = make_aware(today + datetime.timedelta(days=15))
2623
    dt_format = '%Y-%m-%d %H:%M'
2624
    resp.form['label'] = 'Exception 1'
2625
    resp.form['start_datetime_0'] = tomorrow.strftime('%Y-%m-%d')
2626
    resp.form['start_datetime_1'] = '08:00'
2627
    resp.form['end_datetime_0'] = tomorrow.strftime('%Y-%m-%d')
2628
    resp.form['end_datetime_1'] = '16:00'
2629
    resp = resp.form.submit().follow()
2630
    assert TimePeriodException.objects.count() == 1
2631
    time_period_exception = TimePeriodException.objects.first()
2632
    assert localtime(time_period_exception.start_datetime).strftime(dt_format) == tomorrow.replace(
2633
        hour=8
2634
    ).strftime(dt_format)
2635
    assert localtime(time_period_exception.end_datetime).strftime(dt_format) == tomorrow.replace(
2636
        hour=16
2637
    ).strftime(dt_format)
2638
    resp = resp.click(href='/manage/time-period-exceptions/%d/edit' % time_period_exception.id)
2735
    resp = resp.click('Exception Foo', index=0)
2639 2736
    resp = resp.click('Delete')
2640 2737
    resp = resp.form.submit().follow()
2641
    assert TimePeriodException.objects.count() == 0
2738
    assert TimePeriodException.objects.count() == 1
2642 2739
    assert resp.request.url.endswith('/manage/agendas/%d/settings' % agenda.pk)
2643 2740

  
2644 2741
    # stay on exception list
......
2656 2753
    assert resp.request.url.endswith('/manage/time-period-exceptions/%d/exception-list' % desk.pk)
2657 2754

  
2658 2755

  
2756
def test_meetings_agenda_delete_time_period_exception_desk_simple_management(app, admin_user):
2757
    agenda = Agenda.objects.create(label='Foo bar', kind='meetings', desk_simple_management=True)
2758
    desk = Desk.objects.create(agenda=agenda, label='Desk A')
2759
    exception = TimePeriodException.objects.create(
2760
        label='Exception',
2761
        desk=desk,
2762
        start_datetime=make_aware(datetime.datetime(2017, 5, 21, 5, 0)),
2763
        end_datetime=make_aware(datetime.datetime(2017, 5, 21, 23, 0)),
2764
    )
2765
    desk.duplicate()
2766
    assert TimePeriodException.objects.count() == 2
2767
    assert agenda.is_available_for_simple_management() is True
2768

  
2769
    login(app)
2770
    resp = app.get('/manage/time-period-exceptions/%d/delete' % exception.pk)
2771
    resp.form.submit()
2772
    assert TimePeriodException.objects.count() == 0
2773
    assert agenda.is_available_for_simple_management() is True
2774

  
2775
    # should not happen: corresponding exception does not exist
2776
    exception = TimePeriodException.objects.create(
2777
        label='Exception',
2778
        desk=desk,
2779
        start_datetime=make_aware(datetime.datetime(2017, 5, 21, 5, 0)),
2780
        end_datetime=make_aware(datetime.datetime(2017, 5, 21, 23, 0)),
2781
    )
2782
    assert TimePeriodException.objects.count() == 1
2783
    resp = app.get('/manage/time-period-exceptions/%d/delete' % exception.pk)
2784
    resp.form.submit()
2785
    assert TimePeriodException.objects.count() == 0
2786

  
2787

  
2659 2788
@override_settings(
2660 2789
    EXCEPTIONS_SOURCES={
2661 2790
        'holidays': {'class': 'workalendar.europe.France', 'label': 'Holidays'},
2662
-