Projet

Général

Profil

0001-misc-split-some-manager-tests.patch

Lauréline Guérin, 17 juin 2022 15:23

Télécharger (61,7 ko)

Voir les différences:

Subject: [PATCH 1/2] misc: split some manager tests

 tests/manager/test_event.py           | 887 -------------------------
 tests/manager/test_event_timesheet.py | 898 ++++++++++++++++++++++++++
 2 files changed, 898 insertions(+), 887 deletions(-)
 create mode 100644 tests/manager/test_event_timesheet.py
tests/manager/test_event.py
2445 2445
    user_bookings = resp.pyquery.find('td.booking-username.waiting')
2446 2446
    assert len(user_bookings) == 1
2447 2447
    assert user_bookings[0].text == 'Jane Doe (2 places)'
2448

  
2449

  
2450
def test_events_timesheet_wrong_kind(app, admin_user):
2451
    agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
2452

  
2453
    app = login(app)
2454
    app.get('/manage/agendas/%s/events/timesheet' % agenda.id, status=404)
2455
    agenda.kind = 'virtual'
2456
    agenda.save()
2457
    app.get('/manage/agendas/%s/events/timesheet' % agenda.id, status=404)
2458

  
2459

  
2460
def test_events_timesheet_form(app, admin_user):
2461
    agenda = Agenda.objects.create(label='Events', kind='events')
2462

  
2463
    login(app)
2464
    resp = app.get('/manage/agendas/%s/events/timesheet' % agenda.pk)
2465
    resp.form['date_start'] = '2022-01-01'
2466
    resp.form['date_end'] = '2021-12-31'
2467
    resp = resp.form.submit()
2468
    assert resp.context['form'].errors['date_end'] == ['End date must be greater than start date.']
2469

  
2470
    resp.form['date_end'] = '2022-04-02'
2471
    resp = resp.form.submit()
2472
    assert resp.context['form'].errors['date_end'] == ['Please select an interval of no more than 3 months.']
2473

  
2474
    resp.form['date_end'] = '2022-04-01'
2475
    resp = resp.form.submit()
2476
    assert resp.context['form'].errors == {}
2477

  
2478

  
2479
@pytest.mark.freeze_time('2022-02-15')
2480
def test_events_timesheet_slots(app, admin_user):
2481
    start, end = (
2482
        now() - datetime.timedelta(days=15),
2483
        now() + datetime.timedelta(days=14),
2484
    )  # 2022-02-31, 2022-03-01
2485
    agenda = Agenda.objects.create(label='Events', kind='events')
2486
    Event.objects.create(label='event 1', start_datetime=start, places=10, agenda=agenda)
2487
    event2 = Event.objects.create(
2488
        label='event 2', start_datetime=start + datetime.timedelta(days=1), places=10, agenda=agenda
2489
    )
2490
    event3 = Event.objects.create(label='event 3', start_datetime=now(), places=10, agenda=agenda)
2491
    Event.objects.create(
2492
        label='event cancelled',
2493
        start_datetime=now() + datetime.timedelta(days=4),
2494
        places=10,
2495
        agenda=agenda,
2496
        cancelled=True,
2497
    )
2498
    event4 = Event.objects.create(
2499
        label='event 4', start_datetime=end - datetime.timedelta(days=1), places=10, agenda=agenda
2500
    )
2501
    Event.objects.create(label='event 5', start_datetime=end, places=10, agenda=agenda)
2502
    Subscription.objects.create(
2503
        agenda=agenda,
2504
        user_external_id='user:1',
2505
        user_first_name='Subscription',
2506
        user_last_name='42',
2507
        date_start=start,
2508
        date_end=end + datetime.timedelta(days=1),
2509
    )
2510
    recurring_event1 = Event.objects.create(
2511
        label='recurring 1',
2512
        start_datetime=start,
2513
        places=10,
2514
        agenda=agenda,
2515
        recurrence_days=[0, 1],
2516
        recurrence_end_date=end,
2517
    )
2518
    recurring_event1.create_all_recurrences()
2519
    recurring_event2 = Event.objects.create(
2520
        label='recurring 2',
2521
        start_datetime=start,
2522
        places=10,
2523
        agenda=agenda,
2524
        recurrence_days=[1, 2],
2525
        recurrence_end_date=end,
2526
    )
2527
    recurring_event2.create_all_recurrences()
2528

  
2529
    login(app)
2530
    resp = app.get('/manage/agendas/%s/events/timesheet' % agenda.pk)
2531
    resp.form['date_start'] = '2022-02-01'
2532
    resp.form['date_end'] = '2022-02-28'
2533
    with CaptureQueriesContext(connection) as ctx:
2534
        resp = resp.form.submit()
2535
        assert len(ctx.captured_queries) == 7
2536

  
2537
    slots = resp.context['form'].get_slots()
2538
    assert slots['dates'] == [
2539
        [
2540
            datetime.date(2022, 2, 1),
2541
            datetime.date(2022, 2, 2),
2542
            datetime.date(2022, 2, 7),
2543
            datetime.date(2022, 2, 8),
2544
            datetime.date(2022, 2, 9),
2545
            datetime.date(2022, 2, 14),
2546
            datetime.date(2022, 2, 15),
2547
            datetime.date(2022, 2, 16),
2548
            datetime.date(2022, 2, 21),
2549
            datetime.date(2022, 2, 22),
2550
            datetime.date(2022, 2, 23),
2551
            datetime.date(2022, 2, 28),
2552
        ]
2553
    ]
2554
    assert slots['events'] == [
2555
        event2,
2556
        recurring_event1,
2557
        recurring_event2,
2558
        event3,
2559
        event4,
2560
    ]
2561
    assert slots['users'][0]['users'] == [
2562
        {
2563
            'user_id': 'user:1',
2564
            'user_first_name': 'Subscription',
2565
            'user_last_name': '42',
2566
            'extra_data': {},
2567
            'events': [
2568
                {
2569
                    'event': event2,
2570
                    'dates': {date: False for date in slots['dates'][0] if date == datetime.date(2022, 2, 1)},
2571
                },
2572
                {
2573
                    'event': recurring_event1,
2574
                    'dates': {date: False for date in slots['dates'][0] if date.weekday() in [0, 1]},
2575
                },
2576
                {
2577
                    'event': recurring_event2,
2578
                    'dates': {date: False for date in slots['dates'][0] if date.weekday() in [1, 2]},
2579
                },
2580
                {
2581
                    'event': event3,
2582
                    'dates': {
2583
                        date: False for date in slots['dates'][0] if date == datetime.date(2022, 2, 15)
2584
                    },
2585
                },
2586
                {
2587
                    'event': event4,
2588
                    'dates': {
2589
                        date: False for date in slots['dates'][0] if date == datetime.date(2022, 2, 28)
2590
                    },
2591
                },
2592
            ],
2593
        },
2594
    ]
2595
    assert slots['extra_data'] == []
2596

  
2597

  
2598
@pytest.mark.freeze_time('2022-02-15')
2599
def test_events_timesheet_subscription_limits(app, admin_user):
2600
    agenda = Agenda.objects.create(label='Events', kind='events')
2601
    event1 = Event.objects.create(
2602
        start_datetime=make_aware(datetime.datetime(2022, 2, 1, 17, 0)), places=10, agenda=agenda
2603
    )
2604
    event2 = Event.objects.create(
2605
        start_datetime=make_aware(datetime.datetime(2022, 2, 15, 17, 0)), places=10, agenda=agenda
2606
    )
2607
    event3 = Event.objects.create(
2608
        start_datetime=make_aware(datetime.datetime(2022, 2, 28, 17, 0)), places=10, agenda=agenda
2609
    )
2610

  
2611
    dates = [
2612
        ('2022-01-31', '2022-02-01'),
2613
        ('2022-02-01', '2022-02-02'),
2614
        ('2022-02-01', '2022-02-15'),
2615
        ('2022-02-01', '2022-02-16'),
2616
        ('2022-02-15', '2022-02-28'),
2617
        ('2022-02-15', '2022-03-01'),
2618
        ('2022-02-16', '2022-03-01'),
2619
        ('2022-02-01', '2022-03-01'),
2620
        ('2022-02-28', '2022-03-01'),
2621
        ('2022-03-01', '2022-03-02'),
2622
    ]
2623

  
2624
    for start, end in dates:
2625
        Subscription.objects.create(
2626
            agenda=agenda,
2627
            user_external_id='user:%s-%s' % (start, end),
2628
            user_first_name='Subscription',
2629
            user_last_name='%s - %s' % (start, end),
2630
            date_start=datetime.datetime.strptime(start, '%Y-%m-%d'),
2631
            date_end=datetime.datetime.strptime(end, '%Y-%m-%d'),
2632
        )
2633

  
2634
    login(app)
2635
    resp = app.get('/manage/agendas/%s/events/timesheet' % agenda.pk)
2636
    resp.form['date_start'] = '2022-02-01'
2637
    resp.form['date_end'] = '2022-02-28'
2638
    resp = resp.form.submit()
2639

  
2640
    slots = resp.context['form'].get_slots()
2641
    assert slots['dates'] == [
2642
        [
2643
            datetime.date(2022, 2, 1),
2644
            datetime.date(2022, 2, 15),
2645
            datetime.date(2022, 2, 28),
2646
        ]
2647
    ]
2648

  
2649
    assert slots['events'] == [
2650
        event1,
2651
        event2,
2652
        event3,
2653
    ]
2654
    users = slots['users'][0]['users']
2655
    assert len(users) == 8
2656
    assert users[0]['user_id'] == 'user:2022-02-01-2022-02-02'
2657
    assert users[1]['user_id'] == 'user:2022-02-01-2022-02-15'
2658
    assert users[2]['user_id'] == 'user:2022-02-01-2022-02-16'
2659
    assert users[3]['user_id'] == 'user:2022-02-01-2022-03-01'
2660
    assert users[4]['user_id'] == 'user:2022-02-15-2022-02-28'
2661
    assert users[5]['user_id'] == 'user:2022-02-15-2022-03-01'
2662
    assert users[6]['user_id'] == 'user:2022-02-16-2022-03-01'
2663
    assert users[7]['user_id'] == 'user:2022-02-28-2022-03-01'
2664

  
2665

  
2666
def test_events_timesheet_users(app, admin_user):
2667
    agenda = Agenda.objects.create(label='Events', kind='events')
2668
    event = Event.objects.create(
2669
        start_datetime=make_aware(datetime.datetime(2022, 2, 15, 17, 0)), places=10, agenda=agenda
2670
    )
2671

  
2672
    booking1 = Booking.objects.create(
2673
        event=event, user_external_id='user:1', user_first_name='User', user_last_name='42'
2674
    )
2675
    Booking.objects.create(
2676
        event=event, user_external_id='user:2', user_first_name='User', user_last_name='01'
2677
    )
2678
    Booking.objects.create(
2679
        event=event, user_external_id='user:3', user_first_name='User', user_last_name='17'
2680
    )
2681
    Booking.objects.create(
2682
        event=event, user_external_id='user:4', user_first_name='User', user_last_name='35'
2683
    )
2684
    Booking.objects.create(
2685
        event=event, user_external_id='user:5', user_first_name='User', user_last_name='05'
2686
    )
2687
    booking6 = Booking.objects.create(
2688
        event=event, user_external_id='user:6', user_first_name='User', user_last_name='12 Cancelled'
2689
    )
2690
    booking6.cancel()
2691
    Booking.objects.create(
2692
        event=event,
2693
        user_external_id='user:7',
2694
        user_first_name='User',
2695
        user_last_name='Waiting',
2696
        in_waiting_list=True,
2697
    )
2698
    booking8 = Booking.objects.create(
2699
        event=event,
2700
        user_external_id='user:8',
2701
        user_first_name='User',
2702
        user_last_name='Waiting and Cancelled',
2703
        in_waiting_list=True,
2704
    )
2705
    booking8.cancel()
2706
    Booking.objects.create(
2707
        event=event,
2708
        user_external_id='user:1',
2709
        user_first_name='User',
2710
        user_last_name='Secondary',
2711
        primary_booking=booking1,
2712
    )
2713

  
2714
    login(app)
2715
    resp = app.get('/manage/agendas/%s/events/timesheet' % agenda.pk)
2716
    resp.form['date_start'] = '2022-02-01'
2717
    resp.form['date_end'] = '2022-02-28'
2718
    resp = resp.form.submit()
2719
    slots = resp.context['form'].get_slots()
2720
    assert [u['user_id'] for u in slots['users'][0]['users']] == [
2721
        'user:2',
2722
        'user:5',
2723
        'user:3',
2724
        'user:4',
2725
        'user:1',
2726
    ]
2727

  
2728
    start = datetime.date(2022, 2, 1)
2729
    end = datetime.date(2022, 3, 1)
2730
    Subscription.objects.create(
2731
        agenda=agenda,
2732
        user_external_id='user:1',
2733
        user_first_name='Subscription',
2734
        user_last_name='42',
2735
        date_start=start,
2736
        date_end=end,
2737
    )
2738
    Subscription.objects.create(
2739
        agenda=agenda,
2740
        user_external_id='user:9',
2741
        user_first_name='Subscription',
2742
        user_last_name='43',
2743
        date_start=start,
2744
        date_end=end,
2745
    )
2746
    Subscription.objects.create(
2747
        agenda=agenda,
2748
        user_external_id='user:10',
2749
        user_first_name='Subscription',
2750
        user_last_name='14',
2751
        date_start=start,
2752
        date_end=end,
2753
    )
2754
    Subscription.objects.create(
2755
        agenda=agenda,
2756
        user_external_id='user:7',
2757
        user_first_name='Subscription',
2758
        user_last_name='Waiting',
2759
        date_start=start,
2760
        date_end=end,
2761
    )
2762
    Subscription.objects.create(
2763
        agenda=agenda,
2764
        user_external_id='user:42',
2765
        user_first_name='Subscription',
2766
        user_last_name='Too soon',
2767
        date_start=start - datetime.timedelta(days=1),
2768
        date_end=start,
2769
    )
2770
    Subscription.objects.create(
2771
        agenda=agenda,
2772
        user_external_id='user:43',
2773
        user_first_name='Subscription',
2774
        user_last_name='Too late',
2775
        date_start=end + datetime.timedelta(days=1),
2776
        date_end=end + datetime.timedelta(days=2),
2777
    )
2778

  
2779
    resp = resp.form.submit()
2780
    slots = resp.context['form'].get_slots()
2781
    assert [u['user_id'] for u in slots['users'][0]['users']] == [
2782
        'user:2',
2783
        'user:5',
2784
        'user:6',
2785
        'user:10',
2786
        'user:3',
2787
        'user:4',
2788
        'user:1',
2789
        'user:9',
2790
        'user:7',
2791
    ]
2792

  
2793

  
2794
def test_events_timesheet_user_ids(app, admin_user):
2795
    agenda = Agenda.objects.create(label='Events', kind='events')
2796
    event = Event.objects.create(
2797
        start_datetime=make_aware(datetime.datetime(2022, 2, 15, 17, 0)), places=10, agenda=agenda
2798
    )
2799
    booking = Booking.objects.create(event=event, user_first_name='User', user_last_name='42')
2800

  
2801
    login(app)
2802
    resp = app.get('/manage/agendas/%s/events/timesheet' % agenda.pk)
2803
    resp.form['date_start'] = '2022-02-01'
2804
    resp.form['date_end'] = '2022-02-28'
2805
    resp = resp.form.submit()
2806
    slots = resp.context['form'].get_slots()
2807
    # no user_id found
2808
    assert [u['user_id'] for u in slots['users'][0]['users']] == []
2809
    assert [u['user_first_name'] for u in slots['users'][0]['users']] == []
2810
    assert [u['user_last_name'] for u in slots['users'][0]['users']] == []
2811

  
2812
    booking.user_external_id = 'user:1'
2813
    booking.save()
2814

  
2815
    resp = resp.form.submit()
2816
    slots = resp.context['form'].get_slots()
2817
    assert [u['user_id'] for u in slots['users'][0]['users']] == [
2818
        'user:1',
2819
    ]
2820
    assert [u['user_first_name'] for u in slots['users'][0]['users']] == ['User']
2821
    assert [u['user_last_name'] for u in slots['users'][0]['users']] == ['42']
2822

  
2823
    Subscription.objects.create(
2824
        agenda=agenda,
2825
        user_external_id='user:1',
2826
        user_first_name='Subscription',
2827
        user_last_name='41',
2828
        date_start=datetime.date(2022, 2, 1),
2829
        date_end=datetime.date(2022, 3, 1),
2830
    )
2831

  
2832
    resp = resp.form.submit()
2833
    slots = resp.context['form'].get_slots()
2834
    assert [u['user_id'] for u in slots['users'][0]['users']] == [
2835
        'user:1',
2836
    ]
2837
    assert [u['user_first_name'] for u in slots['users'][0]['users']] == [
2838
        'Subscription',
2839
    ]
2840
    assert [u['user_last_name'] for u in slots['users'][0]['users']] == [
2841
        '41',
2842
    ]
2843

  
2844

  
2845
@pytest.mark.freeze_time('2022-02-01')
2846
def test_events_timesheet_booked(app, admin_user):
2847
    agenda = Agenda.objects.create(label='Events', kind='events')
2848
    event_date = make_aware(datetime.datetime(2022, 2, 15, 17, 0))
2849
    event1 = Event.objects.create(label='event 1', start_datetime=event_date, places=10, agenda=agenda)
2850
    event2 = Event.objects.create(label='event 2', start_datetime=event_date, places=10, agenda=agenda)
2851
    event3 = Event.objects.create(label='event 3', start_datetime=event_date, places=10, agenda=agenda)
2852
    recurring_event1 = Event.objects.create(
2853
        label='recurring 1',
2854
        start_datetime=event_date,
2855
        places=10,
2856
        agenda=agenda,
2857
        recurrence_days=[1],
2858
        recurrence_end_date=event_date + datetime.timedelta(days=1),
2859
    )
2860
    recurring_event1.create_all_recurrences()
2861
    recurring_event1_occurence = recurring_event1.recurrences.first()
2862
    recurring_event2 = Event.objects.create(
2863
        label='recurring 2',
2864
        start_datetime=event_date,
2865
        places=10,
2866
        agenda=agenda,
2867
        recurrence_days=[1],
2868
        recurrence_end_date=event_date + datetime.timedelta(days=1),
2869
    )
2870
    recurring_event2.create_all_recurrences()
2871
    recurring_event2_occurence = recurring_event2.recurrences.first()
2872

  
2873
    Subscription.objects.create(
2874
        agenda=agenda,
2875
        user_external_id='user:1',
2876
        user_first_name='Subscription',
2877
        user_last_name='42',
2878
        date_start=datetime.date(2022, 2, 1),
2879
        date_end=datetime.date(2022, 3, 1),
2880
    )
2881
    Booking.objects.create(
2882
        event=event1,
2883
        user_external_id='user:1',
2884
        user_first_name='User',
2885
        user_last_name='42',
2886
    )
2887
    Booking.objects.create(
2888
        event=event2,
2889
        user_external_id='user:1',
2890
        user_first_name='User',
2891
        user_last_name='42',
2892
        cancellation_datetime=now(),
2893
    )
2894
    Booking.objects.create(
2895
        event=recurring_event1_occurence,
2896
        user_external_id='user:1',
2897
        user_first_name='User',
2898
        user_last_name='42',
2899
    )
2900
    Booking.objects.create(
2901
        event=recurring_event2_occurence,
2902
        user_external_id='user:1',
2903
        user_first_name='User',
2904
        user_last_name='42',
2905
        cancellation_datetime=now(),
2906
    )
2907

  
2908
    login(app)
2909
    resp = app.get('/manage/agendas/%s/events/timesheet' % agenda.pk)
2910
    resp.form['date_start'] = '2022-02-01'
2911
    resp.form['date_end'] = '2022-02-28'
2912
    resp = resp.form.submit()
2913
    slots = resp.context['form'].get_slots()
2914

  
2915
    assert slots['events'] == [
2916
        event1,
2917
        event2,
2918
        event3,
2919
        recurring_event1,
2920
        recurring_event2,
2921
    ]
2922
    assert len(slots['users'][0]['users']) == 1
2923
    assert slots['users'][0]['users'][0]['events'] == [
2924
        {
2925
            'event': event1,
2926
            'dates': {datetime.date(2022, 2, 15): True},
2927
        },
2928
        {
2929
            'event': event2,
2930
            'dates': {datetime.date(2022, 2, 15): False},
2931
        },
2932
        {
2933
            'event': event3,
2934
            'dates': {datetime.date(2022, 2, 15): False},
2935
        },
2936
        {
2937
            'event': recurring_event1,
2938
            'dates': {datetime.date(2022, 2, 15): True},
2939
        },
2940
        {
2941
            'event': recurring_event2,
2942
            'dates': {datetime.date(2022, 2, 15): False},
2943
        },
2944
    ]
2945

  
2946

  
2947
def test_events_timesheet_extra_data(app, admin_user):
2948
    agenda = Agenda.objects.create(label='Events', kind='events')
2949
    event = Event.objects.create(
2950
        start_datetime=make_aware(datetime.datetime(2022, 2, 15, 17, 0)), places=10, agenda=agenda
2951
    )
2952
    Booking.objects.create(
2953
        event=event,
2954
        user_first_name='User',
2955
        user_last_name='42',
2956
        user_external_id='user:1',
2957
        extra_data={'foo': 'bar', 'baz': 'blah'},
2958
    )
2959

  
2960
    login(app)
2961
    resp = app.get('/manage/agendas/%s/events/timesheet' % agenda.pk)
2962
    resp.form['date_start'] = '2022-02-01'
2963
    resp.form['date_end'] = '2022-02-28'
2964
    resp.form['extra_data'] = ' foo '
2965
    resp = resp.form.submit()
2966
    slots = resp.context['form'].get_slots()
2967
    assert resp.text.count('<div class="page_break">') == 0
2968

  
2969
    assert len(slots['users']) == 1
2970
    assert slots['users'][0]['grouper'] == ''
2971
    assert len(slots['users'][0]['users']) == 1
2972
    assert slots['extra_data'] == ['foo']
2973
    assert slots['users'][0]['users'][0]['extra_data']['foo'] == 'bar'
2974

  
2975
    resp.form['extra_data'] = ' foo ,baz,,'
2976
    resp = resp.form.submit()
2977
    slots = resp.context['form'].get_slots()
2978

  
2979
    assert len(slots['users'][0]['users']) == 1
2980
    assert slots['extra_data'] == ['foo', 'baz']
2981
    assert slots['users'][0]['users'][0]['extra_data']['foo'] == 'bar'
2982
    assert slots['users'][0]['users'][0]['extra_data']['baz'] == 'blah'
2983

  
2984
    resp.form['extra_data'] = 'unknown'
2985
    resp = resp.form.submit()
2986
    slots = resp.context['form'].get_slots()
2987

  
2988
    assert len(slots['users'][0]['users']) == 1
2989
    assert slots['extra_data'] == ['unknown']
2990
    assert slots['users'][0]['users'][0]['extra_data']['unknown'] == ''
2991

  
2992
    Subscription.objects.create(
2993
        agenda=agenda,
2994
        user_external_id='user:1',
2995
        user_first_name='Subscription',
2996
        user_last_name='41',
2997
        date_start=datetime.date(2022, 2, 1),
2998
        date_end=datetime.date(2022, 3, 1),
2999
        extra_data={'foo': 'baz'},
3000
    )
3001

  
3002
    resp.form['extra_data'] = ' foo '
3003
    resp = resp.form.submit()
3004
    slots = resp.context['form'].get_slots()
3005

  
3006
    assert len(slots['users'][0]['users']) == 1
3007
    assert slots['extra_data'] == ['foo']
3008
    assert slots['users'][0]['users'][0]['extra_data']['foo'] == 'baz'
3009

  
3010
    resp.form['extra_data'] = ' foo ,baz,,'
3011
    resp = resp.form.submit()
3012
    slots = resp.context['form'].get_slots()
3013

  
3014
    assert len(slots['users'][0]['users']) == 1
3015
    assert slots['extra_data'] == ['foo', 'baz']
3016
    assert slots['users'][0]['users'][0]['extra_data']['foo'] == 'baz'
3017
    assert slots['users'][0]['users'][0]['extra_data']['baz'] == ''
3018

  
3019
    Booking.objects.create(
3020
        event=event,
3021
        user_first_name='User',
3022
        user_last_name='43',
3023
        user_external_id='user:2',
3024
        extra_data={'foo': 'bar', 'baz': 'aa'},
3025
    )
3026
    Booking.objects.create(
3027
        event=event,
3028
        user_first_name='User',
3029
        user_last_name='44',
3030
        user_external_id='user:3',
3031
        extra_data={'foo': 'bar2', 'baz': 'aa'},
3032
    )
3033

  
3034
    resp.form['extra_data'] = ''
3035
    resp.form['group_by'] = 'foo'
3036
    resp = resp.form.submit()
3037
    slots = resp.context['form'].get_slots()
3038
    assert resp.text.count('<div class="page_break">') == 0
3039

  
3040
    assert len(slots['users']) == 3
3041
    assert slots['users'][0]['grouper'] == 'bar'
3042
    assert len(slots['users'][0]['users']) == 1
3043
    assert slots['users'][0]['users'][0]['user_id'] == 'user:2'
3044
    assert slots['users'][1]['grouper'] == 'bar2'
3045
    assert len(slots['users'][1]['users']) == 1
3046
    assert slots['users'][1]['users'][0]['user_id'] == 'user:3'
3047
    assert slots['users'][2]['grouper'] == 'baz'
3048
    assert len(slots['users'][2]['users']) == 1
3049
    assert slots['users'][2]['users'][0]['user_id'] == 'user:1'
3050

  
3051
    resp.form['with_page_break'] = True
3052
    resp = resp.form.submit()
3053
    assert resp.text.count('<div class="page_break">') == 2
3054

  
3055
    resp.form['group_by'] = 'baz'
3056
    resp = resp.form.submit()
3057
    slots = resp.context['form'].get_slots()
3058

  
3059
    assert len(slots['users']) == 2
3060
    assert slots['users'][0]['grouper'] == 'aa'
3061
    assert len(slots['users'][0]['users']) == 2
3062
    assert slots['users'][0]['users'][0]['user_id'] == 'user:2'
3063
    assert slots['users'][0]['users'][1]['user_id'] == 'user:3'
3064
    assert slots['users'][1]['grouper'] == ''
3065
    assert len(slots['users'][1]['users']) == 1
3066
    assert slots['users'][1]['users'][0]['user_id'] == 'user:1'
3067

  
3068
    Subscription.objects.update(extra_data={'foo': 'baz', 'baz': 'blah'})
3069
    resp = resp.form.submit()
3070
    slots = resp.context['form'].get_slots()
3071

  
3072
    assert len(slots['users']) == 2
3073
    assert slots['users'][0]['grouper'] == 'aa'
3074
    assert len(slots['users'][0]['users']) == 2
3075
    assert slots['users'][0]['users'][0]['user_id'] == 'user:2'
3076
    assert slots['users'][0]['users'][1]['user_id'] == 'user:3'
3077
    assert slots['users'][1]['grouper'] == 'blah'
3078
    assert len(slots['users'][1]['users']) == 1
3079
    assert slots['users'][1]['users'][0]['user_id'] == 'user:1'
3080

  
3081
    resp.form['group_by'] = 'unknown'
3082
    resp = resp.form.submit()
3083
    slots = resp.context['form'].get_slots()
3084

  
3085
    assert len(slots['users']) == 1
3086
    assert slots['users'][0]['grouper'] == ''
3087
    assert len(slots['users'][0]['users']) == 3
3088

  
3089

  
3090
def test_events_timesheet_ordering(app, admin_user):
3091
    agenda = Agenda.objects.create(label='Events', kind='events')
3092
    event = Event.objects.create(
3093
        start_datetime=make_aware(datetime.datetime(2022, 2, 15, 17, 0)), places=10, agenda=agenda
3094
    )
3095
    Booking.objects.create(
3096
        event=event,
3097
        user_first_name='BB',
3098
        user_last_name='XX',
3099
        user_external_id='user:1',
3100
    )
3101
    Booking.objects.create(
3102
        event=event,
3103
        user_first_name='AA',
3104
        user_last_name='YY',
3105
        user_external_id='user:2',
3106
        cancellation_datetime=now(),
3107
    )
3108
    Subscription.objects.create(
3109
        agenda=agenda,
3110
        user_first_name='CC',
3111
        user_last_name='WW',
3112
        user_external_id='user:3',
3113
        date_start=datetime.date(2022, 2, 1),
3114
        date_end=datetime.date(2022, 3, 1),
3115
    )
3116

  
3117
    login(app)
3118
    resp = app.get('/manage/agendas/%s/events/timesheet' % agenda.pk)
3119
    resp.form['date_start'] = '2022-02-01'
3120
    resp.form['date_end'] = '2022-02-28'
3121
    resp = resp.form.submit()
3122
    slots = resp.context['form'].get_slots()
3123
    assert slots['users'][0]['users'][0]['user_id'] == 'user:3'
3124
    assert slots['users'][0]['users'][1]['user_id'] == 'user:1'
3125
    assert slots['users'][0]['users'][2]['user_id'] == 'user:2'
3126

  
3127
    resp.form['sort'] = 'lastname,firstname'
3128
    resp = resp.form.submit()
3129
    slots = resp.context['form'].get_slots()
3130
    assert slots['users'][0]['users'][0]['user_id'] == 'user:3'
3131
    assert slots['users'][0]['users'][1]['user_id'] == 'user:1'
3132
    assert slots['users'][0]['users'][2]['user_id'] == 'user:2'
3133

  
3134
    resp.form['sort'] = 'firstname,lastname'
3135
    resp = resp.form.submit()
3136
    slots = resp.context['form'].get_slots()
3137
    assert slots['users'][0]['users'][0]['user_id'] == 'user:2'
3138
    assert slots['users'][0]['users'][1]['user_id'] == 'user:1'
3139
    assert slots['users'][0]['users'][2]['user_id'] == 'user:3'
3140

  
3141

  
3142
@pytest.mark.freeze_time('2022-04-01')
3143
def test_events_timesheet_date_display(app, admin_user):
3144
    agenda = Agenda.objects.create(label='Events', kind='events')
3145
    recurring_event = Event.objects.create(
3146
        label='recurring 1',
3147
        start_datetime=make_aware(datetime.datetime(2022, 1, 1, 12, 0)),
3148
        places=10,
3149
        agenda=agenda,
3150
        recurrence_days=[0],
3151
        recurrence_end_date=datetime.date(2022, 4, 1),
3152
    )
3153
    recurring_event.create_all_recurrences()
3154
    Subscription.objects.create(
3155
        agenda=agenda,
3156
        user_external_id='user:1',
3157
        user_first_name='Subscription',
3158
        user_last_name='42',
3159
        date_start=datetime.date(2022, 1, 1),
3160
        date_end=datetime.date(2022, 4, 1),
3161
        extra_data={'foo': 'bar'},
3162
    )
3163

  
3164
    login(app)
3165
    resp = app.get('/manage/agendas/%s/events/timesheet' % agenda.pk)
3166
    resp.form['date_start'] = '2022-01-01'
3167
    resp.form['date_end'] = '2022-03-31'
3168
    resp = resp.form.submit()
3169
    slots = resp.context['form'].get_slots()
3170

  
3171
    assert slots['dates'] == [
3172
        [
3173
            datetime.date(2022, 1, 3),
3174
            datetime.date(2022, 1, 10),
3175
            datetime.date(2022, 1, 17),
3176
            datetime.date(2022, 1, 24),
3177
            datetime.date(2022, 1, 31),
3178
            datetime.date(2022, 2, 7),
3179
            datetime.date(2022, 2, 14),
3180
            datetime.date(2022, 2, 21),
3181
            datetime.date(2022, 2, 28),
3182
            datetime.date(2022, 3, 7),
3183
            datetime.date(2022, 3, 14),
3184
            datetime.date(2022, 3, 21),
3185
            datetime.date(2022, 3, 28),
3186
        ]
3187
    ]
3188

  
3189
    resp.form['date_display'] = 'month'
3190
    resp = resp.form.submit()
3191
    slots = resp.context['form'].get_slots()
3192

  
3193
    assert slots['dates'] == [
3194
        [
3195
            datetime.date(2022, 1, 3),
3196
            datetime.date(2022, 1, 10),
3197
            datetime.date(2022, 1, 17),
3198
            datetime.date(2022, 1, 24),
3199
            datetime.date(2022, 1, 31),
3200
        ],
3201
        [
3202
            datetime.date(2022, 2, 7),
3203
            datetime.date(2022, 2, 14),
3204
            datetime.date(2022, 2, 21),
3205
            datetime.date(2022, 2, 28),
3206
        ],
3207
        [
3208
            datetime.date(2022, 3, 7),
3209
            datetime.date(2022, 3, 14),
3210
            datetime.date(2022, 3, 21),
3211
            datetime.date(2022, 3, 28),
3212
        ],
3213
    ]
3214

  
3215
    resp.form['date_display'] = 'week'
3216
    resp = resp.form.submit()
3217
    slots = resp.context['form'].get_slots()
3218
    assert resp.text.count('<div class="page_break">') == 12
3219

  
3220
    assert slots['dates'] == [
3221
        [datetime.date(2022, 1, 3)],
3222
        [datetime.date(2022, 1, 10)],
3223
        [datetime.date(2022, 1, 17)],
3224
        [datetime.date(2022, 1, 24)],
3225
        [datetime.date(2022, 1, 31)],
3226
        [datetime.date(2022, 2, 7)],
3227
        [datetime.date(2022, 2, 14)],
3228
        [datetime.date(2022, 2, 21)],
3229
        [datetime.date(2022, 2, 28)],
3230
        [datetime.date(2022, 3, 7)],
3231
        [datetime.date(2022, 3, 14)],
3232
        [datetime.date(2022, 3, 21)],
3233
        [datetime.date(2022, 3, 28)],
3234
    ]
3235

  
3236
    resp.form['date_display'] = 'custom'
3237
    resp = resp.form.submit()
3238
    assert resp.context['form'].errors['custom_nb_dates_per_page'] == ['This field is required.']
3239

  
3240
    resp.form['custom_nb_dates_per_page'] = 10
3241
    resp = resp.form.submit()
3242
    slots = resp.context['form'].get_slots()
3243

  
3244
    assert slots['dates'] == [
3245
        [
3246
            datetime.date(2022, 1, 3),
3247
            datetime.date(2022, 1, 10),
3248
            datetime.date(2022, 1, 17),
3249
            datetime.date(2022, 1, 24),
3250
            datetime.date(2022, 1, 31),
3251
            datetime.date(2022, 2, 7),
3252
            datetime.date(2022, 2, 14),
3253
            datetime.date(2022, 2, 21),
3254
            datetime.date(2022, 2, 28),
3255
            datetime.date(2022, 3, 7),
3256
        ],
3257
        [
3258
            datetime.date(2022, 3, 14),
3259
            datetime.date(2022, 3, 21),
3260
            datetime.date(2022, 3, 28),
3261
        ],
3262
    ]
3263

  
3264
    resp.form['custom_nb_dates_per_page'] = 3
3265
    resp = resp.form.submit()
3266
    slots = resp.context['form'].get_slots()
3267

  
3268
    assert slots['dates'] == [
3269
        [
3270
            datetime.date(2022, 1, 3),
3271
            datetime.date(2022, 1, 10),
3272
            datetime.date(2022, 1, 17),
3273
        ],
3274
        [
3275
            datetime.date(2022, 1, 24),
3276
            datetime.date(2022, 1, 31),
3277
            datetime.date(2022, 2, 7),
3278
        ],
3279
        [
3280
            datetime.date(2022, 2, 14),
3281
            datetime.date(2022, 2, 21),
3282
            datetime.date(2022, 2, 28),
3283
        ],
3284
        [
3285
            datetime.date(2022, 3, 7),
3286
            datetime.date(2022, 3, 14),
3287
            datetime.date(2022, 3, 21),
3288
        ],
3289
        [
3290
            datetime.date(2022, 3, 28),
3291
        ],
3292
    ]
3293

  
3294
    Subscription.objects.create(
3295
        agenda=agenda,
3296
        user_external_id='user:2',
3297
        user_first_name='Subscription',
3298
        user_last_name='43',
3299
        date_start=datetime.date(2022, 1, 1),
3300
        date_end=datetime.date(2022, 4, 1),
3301
        extra_data={'foo': 'baz'},
3302
    )
3303

  
3304
    resp.form['date_display'] = 'week'
3305
    resp.form['group_by'] = 'foo'
3306
    resp = resp.form.submit()
3307
    slots = resp.context['form'].get_slots()
3308
    assert resp.text.count('<div class="page_break">') == 12
3309

  
3310
    resp.form['with_page_break'] = True
3311
    resp = resp.form.submit()
3312
    assert resp.text.count('<div class="page_break">') == 25
3313

  
3314

  
3315
def test_events_timesheet_pdf(app, admin_user):
3316
    agenda = Agenda.objects.create(label='Events', kind='events')
3317

  
3318
    login(app)
3319
    resp = app.get(
3320
        '/manage/agendas/%s/events/timesheet?pdf=&date_start=2022-02-01&date_end=2022-02-28&sort=lastname,firstname&date_display=all&orientation=portrait'
3321
        % agenda.pk
3322
    )
3323
    assert resp.headers['Content-Type'] == 'application/pdf'
3324
    assert (
3325
        resp.headers['Content-Disposition']
3326
        == 'attachment; filename="timesheet_events_2022-02-01_2022-02-28.pdf"'
3327
    )
3328

  
3329
    # form invalid
3330
    resp = app.get(
3331
        '/manage/agendas/%s/events/timesheet?pdf=&date_start=2022-02-01&date_end=2022-02-28&sort=lastname,firstname&date_display=all'
3332
        % agenda.pk
3333
    )
3334
    assert resp.context['form'].errors['orientation'] == ['This field is required.']
tests/manager/test_event_timesheet.py
1
import datetime
2

  
3
import pytest
4
from django.db import connection
5
from django.test.utils import CaptureQueriesContext
6
from django.utils.timezone import make_aware, now
7

  
8
from chrono.agendas.models import Agenda, Booking, Event, Subscription
9
from tests.utils import login
10

  
11
pytestmark = pytest.mark.django_db
12

  
13

  
14
def test_events_timesheet_wrong_kind(app, admin_user):
15
    agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
16

  
17
    app = login(app)
18
    app.get('/manage/agendas/%s/events/timesheet' % agenda.id, status=404)
19
    agenda.kind = 'virtual'
20
    agenda.save()
21
    app.get('/manage/agendas/%s/events/timesheet' % agenda.id, status=404)
22

  
23

  
24
def test_events_timesheet_form(app, admin_user):
25
    agenda = Agenda.objects.create(label='Events', kind='events')
26

  
27
    login(app)
28
    resp = app.get('/manage/agendas/%s/events/timesheet' % agenda.pk)
29
    resp.form['date_start'] = '2022-01-01'
30
    resp.form['date_end'] = '2021-12-31'
31
    resp = resp.form.submit()
32
    assert resp.context['form'].errors['date_end'] == ['End date must be greater than start date.']
33

  
34
    resp.form['date_end'] = '2022-04-02'
35
    resp = resp.form.submit()
36
    assert resp.context['form'].errors['date_end'] == ['Please select an interval of no more than 3 months.']
37

  
38
    resp.form['date_end'] = '2022-04-01'
39
    resp = resp.form.submit()
40
    assert resp.context['form'].errors == {}
41

  
42

  
43
@pytest.mark.freeze_time('2022-02-15')
44
def test_events_timesheet_slots(app, admin_user):
45
    start, end = (
46
        now() - datetime.timedelta(days=15),
47
        now() + datetime.timedelta(days=14),
48
    )  # 2022-02-31, 2022-03-01
49
    agenda = Agenda.objects.create(label='Events', kind='events')
50
    Event.objects.create(label='event 1', start_datetime=start, places=10, agenda=agenda)
51
    event2 = Event.objects.create(
52
        label='event 2', start_datetime=start + datetime.timedelta(days=1), places=10, agenda=agenda
53
    )
54
    event3 = Event.objects.create(label='event 3', start_datetime=now(), places=10, agenda=agenda)
55
    Event.objects.create(
56
        label='event cancelled',
57
        start_datetime=now() + datetime.timedelta(days=4),
58
        places=10,
59
        agenda=agenda,
60
        cancelled=True,
61
    )
62
    event4 = Event.objects.create(
63
        label='event 4', start_datetime=end - datetime.timedelta(days=1), places=10, agenda=agenda
64
    )
65
    Event.objects.create(label='event 5', start_datetime=end, places=10, agenda=agenda)
66
    Subscription.objects.create(
67
        agenda=agenda,
68
        user_external_id='user:1',
69
        user_first_name='Subscription',
70
        user_last_name='42',
71
        date_start=start,
72
        date_end=end + datetime.timedelta(days=1),
73
    )
74
    recurring_event1 = Event.objects.create(
75
        label='recurring 1',
76
        start_datetime=start,
77
        places=10,
78
        agenda=agenda,
79
        recurrence_days=[0, 1],
80
        recurrence_end_date=end,
81
    )
82
    recurring_event1.create_all_recurrences()
83
    recurring_event2 = Event.objects.create(
84
        label='recurring 2',
85
        start_datetime=start,
86
        places=10,
87
        agenda=agenda,
88
        recurrence_days=[1, 2],
89
        recurrence_end_date=end,
90
    )
91
    recurring_event2.create_all_recurrences()
92

  
93
    login(app)
94
    resp = app.get('/manage/agendas/%s/events/timesheet' % agenda.pk)
95
    resp.form['date_start'] = '2022-02-01'
96
    resp.form['date_end'] = '2022-02-28'
97
    with CaptureQueriesContext(connection) as ctx:
98
        resp = resp.form.submit()
99
        assert len(ctx.captured_queries) == 7
100

  
101
    slots = resp.context['form'].get_slots()
102
    assert slots['dates'] == [
103
        [
104
            datetime.date(2022, 2, 1),
105
            datetime.date(2022, 2, 2),
106
            datetime.date(2022, 2, 7),
107
            datetime.date(2022, 2, 8),
108
            datetime.date(2022, 2, 9),
109
            datetime.date(2022, 2, 14),
110
            datetime.date(2022, 2, 15),
111
            datetime.date(2022, 2, 16),
112
            datetime.date(2022, 2, 21),
113
            datetime.date(2022, 2, 22),
114
            datetime.date(2022, 2, 23),
115
            datetime.date(2022, 2, 28),
116
        ]
117
    ]
118
    assert slots['events'] == [
119
        event2,
120
        recurring_event1,
121
        recurring_event2,
122
        event3,
123
        event4,
124
    ]
125
    assert slots['users'][0]['users'] == [
126
        {
127
            'user_id': 'user:1',
128
            'user_first_name': 'Subscription',
129
            'user_last_name': '42',
130
            'extra_data': {},
131
            'events': [
132
                {
133
                    'event': event2,
134
                    'dates': {date: False for date in slots['dates'][0] if date == datetime.date(2022, 2, 1)},
135
                },
136
                {
137
                    'event': recurring_event1,
138
                    'dates': {date: False for date in slots['dates'][0] if date.weekday() in [0, 1]},
139
                },
140
                {
141
                    'event': recurring_event2,
142
                    'dates': {date: False for date in slots['dates'][0] if date.weekday() in [1, 2]},
143
                },
144
                {
145
                    'event': event3,
146
                    'dates': {
147
                        date: False for date in slots['dates'][0] if date == datetime.date(2022, 2, 15)
148
                    },
149
                },
150
                {
151
                    'event': event4,
152
                    'dates': {
153
                        date: False for date in slots['dates'][0] if date == datetime.date(2022, 2, 28)
154
                    },
155
                },
156
            ],
157
        },
158
    ]
159
    assert slots['extra_data'] == []
160

  
161

  
162
@pytest.mark.freeze_time('2022-02-15')
163
def test_events_timesheet_subscription_limits(app, admin_user):
164
    agenda = Agenda.objects.create(label='Events', kind='events')
165
    event1 = Event.objects.create(
166
        start_datetime=make_aware(datetime.datetime(2022, 2, 1, 17, 0)), places=10, agenda=agenda
167
    )
168
    event2 = Event.objects.create(
169
        start_datetime=make_aware(datetime.datetime(2022, 2, 15, 17, 0)), places=10, agenda=agenda
170
    )
171
    event3 = Event.objects.create(
172
        start_datetime=make_aware(datetime.datetime(2022, 2, 28, 17, 0)), places=10, agenda=agenda
173
    )
174

  
175
    dates = [
176
        ('2022-01-31', '2022-02-01'),
177
        ('2022-02-01', '2022-02-02'),
178
        ('2022-02-01', '2022-02-15'),
179
        ('2022-02-01', '2022-02-16'),
180
        ('2022-02-15', '2022-02-28'),
181
        ('2022-02-15', '2022-03-01'),
182
        ('2022-02-16', '2022-03-01'),
183
        ('2022-02-01', '2022-03-01'),
184
        ('2022-02-28', '2022-03-01'),
185
        ('2022-03-01', '2022-03-02'),
186
    ]
187

  
188
    for start, end in dates:
189
        Subscription.objects.create(
190
            agenda=agenda,
191
            user_external_id='user:%s-%s' % (start, end),
192
            user_first_name='Subscription',
193
            user_last_name='%s - %s' % (start, end),
194
            date_start=datetime.datetime.strptime(start, '%Y-%m-%d'),
195
            date_end=datetime.datetime.strptime(end, '%Y-%m-%d'),
196
        )
197

  
198
    login(app)
199
    resp = app.get('/manage/agendas/%s/events/timesheet' % agenda.pk)
200
    resp.form['date_start'] = '2022-02-01'
201
    resp.form['date_end'] = '2022-02-28'
202
    resp = resp.form.submit()
203

  
204
    slots = resp.context['form'].get_slots()
205
    assert slots['dates'] == [
206
        [
207
            datetime.date(2022, 2, 1),
208
            datetime.date(2022, 2, 15),
209
            datetime.date(2022, 2, 28),
210
        ]
211
    ]
212

  
213
    assert slots['events'] == [
214
        event1,
215
        event2,
216
        event3,
217
    ]
218
    users = slots['users'][0]['users']
219
    assert len(users) == 8
220
    assert users[0]['user_id'] == 'user:2022-02-01-2022-02-02'
221
    assert users[1]['user_id'] == 'user:2022-02-01-2022-02-15'
222
    assert users[2]['user_id'] == 'user:2022-02-01-2022-02-16'
223
    assert users[3]['user_id'] == 'user:2022-02-01-2022-03-01'
224
    assert users[4]['user_id'] == 'user:2022-02-15-2022-02-28'
225
    assert users[5]['user_id'] == 'user:2022-02-15-2022-03-01'
226
    assert users[6]['user_id'] == 'user:2022-02-16-2022-03-01'
227
    assert users[7]['user_id'] == 'user:2022-02-28-2022-03-01'
228

  
229

  
230
def test_events_timesheet_users(app, admin_user):
231
    agenda = Agenda.objects.create(label='Events', kind='events')
232
    event = Event.objects.create(
233
        start_datetime=make_aware(datetime.datetime(2022, 2, 15, 17, 0)), places=10, agenda=agenda
234
    )
235

  
236
    booking1 = Booking.objects.create(
237
        event=event, user_external_id='user:1', user_first_name='User', user_last_name='42'
238
    )
239
    Booking.objects.create(
240
        event=event, user_external_id='user:2', user_first_name='User', user_last_name='01'
241
    )
242
    Booking.objects.create(
243
        event=event, user_external_id='user:3', user_first_name='User', user_last_name='17'
244
    )
245
    Booking.objects.create(
246
        event=event, user_external_id='user:4', user_first_name='User', user_last_name='35'
247
    )
248
    Booking.objects.create(
249
        event=event, user_external_id='user:5', user_first_name='User', user_last_name='05'
250
    )
251
    booking6 = Booking.objects.create(
252
        event=event, user_external_id='user:6', user_first_name='User', user_last_name='12 Cancelled'
253
    )
254
    booking6.cancel()
255
    Booking.objects.create(
256
        event=event,
257
        user_external_id='user:7',
258
        user_first_name='User',
259
        user_last_name='Waiting',
260
        in_waiting_list=True,
261
    )
262
    booking8 = Booking.objects.create(
263
        event=event,
264
        user_external_id='user:8',
265
        user_first_name='User',
266
        user_last_name='Waiting and Cancelled',
267
        in_waiting_list=True,
268
    )
269
    booking8.cancel()
270
    Booking.objects.create(
271
        event=event,
272
        user_external_id='user:1',
273
        user_first_name='User',
274
        user_last_name='Secondary',
275
        primary_booking=booking1,
276
    )
277

  
278
    login(app)
279
    resp = app.get('/manage/agendas/%s/events/timesheet' % agenda.pk)
280
    resp.form['date_start'] = '2022-02-01'
281
    resp.form['date_end'] = '2022-02-28'
282
    resp = resp.form.submit()
283
    slots = resp.context['form'].get_slots()
284
    assert [u['user_id'] for u in slots['users'][0]['users']] == [
285
        'user:2',
286
        'user:5',
287
        'user:3',
288
        'user:4',
289
        'user:1',
290
    ]
291

  
292
    start = datetime.date(2022, 2, 1)
293
    end = datetime.date(2022, 3, 1)
294
    Subscription.objects.create(
295
        agenda=agenda,
296
        user_external_id='user:1',
297
        user_first_name='Subscription',
298
        user_last_name='42',
299
        date_start=start,
300
        date_end=end,
301
    )
302
    Subscription.objects.create(
303
        agenda=agenda,
304
        user_external_id='user:9',
305
        user_first_name='Subscription',
306
        user_last_name='43',
307
        date_start=start,
308
        date_end=end,
309
    )
310
    Subscription.objects.create(
311
        agenda=agenda,
312
        user_external_id='user:10',
313
        user_first_name='Subscription',
314
        user_last_name='14',
315
        date_start=start,
316
        date_end=end,
317
    )
318
    Subscription.objects.create(
319
        agenda=agenda,
320
        user_external_id='user:7',
321
        user_first_name='Subscription',
322
        user_last_name='Waiting',
323
        date_start=start,
324
        date_end=end,
325
    )
326
    Subscription.objects.create(
327
        agenda=agenda,
328
        user_external_id='user:42',
329
        user_first_name='Subscription',
330
        user_last_name='Too soon',
331
        date_start=start - datetime.timedelta(days=1),
332
        date_end=start,
333
    )
334
    Subscription.objects.create(
335
        agenda=agenda,
336
        user_external_id='user:43',
337
        user_first_name='Subscription',
338
        user_last_name='Too late',
339
        date_start=end + datetime.timedelta(days=1),
340
        date_end=end + datetime.timedelta(days=2),
341
    )
342

  
343
    resp = resp.form.submit()
344
    slots = resp.context['form'].get_slots()
345
    assert [u['user_id'] for u in slots['users'][0]['users']] == [
346
        'user:2',
347
        'user:5',
348
        'user:6',
349
        'user:10',
350
        'user:3',
351
        'user:4',
352
        'user:1',
353
        'user:9',
354
        'user:7',
355
    ]
356

  
357

  
358
def test_events_timesheet_user_ids(app, admin_user):
359
    agenda = Agenda.objects.create(label='Events', kind='events')
360
    event = Event.objects.create(
361
        start_datetime=make_aware(datetime.datetime(2022, 2, 15, 17, 0)), places=10, agenda=agenda
362
    )
363
    booking = Booking.objects.create(event=event, user_first_name='User', user_last_name='42')
364

  
365
    login(app)
366
    resp = app.get('/manage/agendas/%s/events/timesheet' % agenda.pk)
367
    resp.form['date_start'] = '2022-02-01'
368
    resp.form['date_end'] = '2022-02-28'
369
    resp = resp.form.submit()
370
    slots = resp.context['form'].get_slots()
371
    # no user_id found
372
    assert [u['user_id'] for u in slots['users'][0]['users']] == []
373
    assert [u['user_first_name'] for u in slots['users'][0]['users']] == []
374
    assert [u['user_last_name'] for u in slots['users'][0]['users']] == []
375

  
376
    booking.user_external_id = 'user:1'
377
    booking.save()
378

  
379
    resp = resp.form.submit()
380
    slots = resp.context['form'].get_slots()
381
    assert [u['user_id'] for u in slots['users'][0]['users']] == [
382
        'user:1',
383
    ]
384
    assert [u['user_first_name'] for u in slots['users'][0]['users']] == ['User']
385
    assert [u['user_last_name'] for u in slots['users'][0]['users']] == ['42']
386

  
387
    Subscription.objects.create(
388
        agenda=agenda,
389
        user_external_id='user:1',
390
        user_first_name='Subscription',
391
        user_last_name='41',
392
        date_start=datetime.date(2022, 2, 1),
393
        date_end=datetime.date(2022, 3, 1),
394
    )
395

  
396
    resp = resp.form.submit()
397
    slots = resp.context['form'].get_slots()
398
    assert [u['user_id'] for u in slots['users'][0]['users']] == [
399
        'user:1',
400
    ]
401
    assert [u['user_first_name'] for u in slots['users'][0]['users']] == [
402
        'Subscription',
403
    ]
404
    assert [u['user_last_name'] for u in slots['users'][0]['users']] == [
405
        '41',
406
    ]
407

  
408

  
409
@pytest.mark.freeze_time('2022-02-01')
410
def test_events_timesheet_booked(app, admin_user):
411
    agenda = Agenda.objects.create(label='Events', kind='events')
412
    event_date = make_aware(datetime.datetime(2022, 2, 15, 17, 0))
413
    event1 = Event.objects.create(label='event 1', start_datetime=event_date, places=10, agenda=agenda)
414
    event2 = Event.objects.create(label='event 2', start_datetime=event_date, places=10, agenda=agenda)
415
    event3 = Event.objects.create(label='event 3', start_datetime=event_date, places=10, agenda=agenda)
416
    recurring_event1 = Event.objects.create(
417
        label='recurring 1',
418
        start_datetime=event_date,
419
        places=10,
420
        agenda=agenda,
421
        recurrence_days=[1],
422
        recurrence_end_date=event_date + datetime.timedelta(days=1),
423
    )
424
    recurring_event1.create_all_recurrences()
425
    recurring_event1_occurence = recurring_event1.recurrences.first()
426
    recurring_event2 = Event.objects.create(
427
        label='recurring 2',
428
        start_datetime=event_date,
429
        places=10,
430
        agenda=agenda,
431
        recurrence_days=[1],
432
        recurrence_end_date=event_date + datetime.timedelta(days=1),
433
    )
434
    recurring_event2.create_all_recurrences()
435
    recurring_event2_occurence = recurring_event2.recurrences.first()
436

  
437
    Subscription.objects.create(
438
        agenda=agenda,
439
        user_external_id='user:1',
440
        user_first_name='Subscription',
441
        user_last_name='42',
442
        date_start=datetime.date(2022, 2, 1),
443
        date_end=datetime.date(2022, 3, 1),
444
    )
445
    Booking.objects.create(
446
        event=event1,
447
        user_external_id='user:1',
448
        user_first_name='User',
449
        user_last_name='42',
450
    )
451
    Booking.objects.create(
452
        event=event2,
453
        user_external_id='user:1',
454
        user_first_name='User',
455
        user_last_name='42',
456
        cancellation_datetime=now(),
457
    )
458
    Booking.objects.create(
459
        event=recurring_event1_occurence,
460
        user_external_id='user:1',
461
        user_first_name='User',
462
        user_last_name='42',
463
    )
464
    Booking.objects.create(
465
        event=recurring_event2_occurence,
466
        user_external_id='user:1',
467
        user_first_name='User',
468
        user_last_name='42',
469
        cancellation_datetime=now(),
470
    )
471

  
472
    login(app)
473
    resp = app.get('/manage/agendas/%s/events/timesheet' % agenda.pk)
474
    resp.form['date_start'] = '2022-02-01'
475
    resp.form['date_end'] = '2022-02-28'
476
    resp = resp.form.submit()
477
    slots = resp.context['form'].get_slots()
478

  
479
    assert slots['events'] == [
480
        event1,
481
        event2,
482
        event3,
483
        recurring_event1,
484
        recurring_event2,
485
    ]
486
    assert len(slots['users'][0]['users']) == 1
487
    assert slots['users'][0]['users'][0]['events'] == [
488
        {
489
            'event': event1,
490
            'dates': {datetime.date(2022, 2, 15): True},
491
        },
492
        {
493
            'event': event2,
494
            'dates': {datetime.date(2022, 2, 15): False},
495
        },
496
        {
497
            'event': event3,
498
            'dates': {datetime.date(2022, 2, 15): False},
499
        },
500
        {
501
            'event': recurring_event1,
502
            'dates': {datetime.date(2022, 2, 15): True},
503
        },
504
        {
505
            'event': recurring_event2,
506
            'dates': {datetime.date(2022, 2, 15): False},
507
        },
508
    ]
509

  
510

  
511
def test_events_timesheet_extra_data(app, admin_user):
512
    agenda = Agenda.objects.create(label='Events', kind='events')
513
    event = Event.objects.create(
514
        start_datetime=make_aware(datetime.datetime(2022, 2, 15, 17, 0)), places=10, agenda=agenda
515
    )
516
    Booking.objects.create(
517
        event=event,
518
        user_first_name='User',
519
        user_last_name='42',
520
        user_external_id='user:1',
521
        extra_data={'foo': 'bar', 'baz': 'blah'},
522
    )
523

  
524
    login(app)
525
    resp = app.get('/manage/agendas/%s/events/timesheet' % agenda.pk)
526
    resp.form['date_start'] = '2022-02-01'
527
    resp.form['date_end'] = '2022-02-28'
528
    resp.form['extra_data'] = ' foo '
529
    resp = resp.form.submit()
530
    slots = resp.context['form'].get_slots()
531
    assert resp.text.count('<div class="page_break">') == 0
532

  
533
    assert len(slots['users']) == 1
534
    assert slots['users'][0]['grouper'] == ''
535
    assert len(slots['users'][0]['users']) == 1
536
    assert slots['extra_data'] == ['foo']
537
    assert slots['users'][0]['users'][0]['extra_data']['foo'] == 'bar'
538

  
539
    resp.form['extra_data'] = ' foo ,baz,,'
540
    resp = resp.form.submit()
541
    slots = resp.context['form'].get_slots()
542

  
543
    assert len(slots['users'][0]['users']) == 1
544
    assert slots['extra_data'] == ['foo', 'baz']
545
    assert slots['users'][0]['users'][0]['extra_data']['foo'] == 'bar'
546
    assert slots['users'][0]['users'][0]['extra_data']['baz'] == 'blah'
547

  
548
    resp.form['extra_data'] = 'unknown'
549
    resp = resp.form.submit()
550
    slots = resp.context['form'].get_slots()
551

  
552
    assert len(slots['users'][0]['users']) == 1
553
    assert slots['extra_data'] == ['unknown']
554
    assert slots['users'][0]['users'][0]['extra_data']['unknown'] == ''
555

  
556
    Subscription.objects.create(
557
        agenda=agenda,
558
        user_external_id='user:1',
559
        user_first_name='Subscription',
560
        user_last_name='41',
561
        date_start=datetime.date(2022, 2, 1),
562
        date_end=datetime.date(2022, 3, 1),
563
        extra_data={'foo': 'baz'},
564
    )
565

  
566
    resp.form['extra_data'] = ' foo '
567
    resp = resp.form.submit()
568
    slots = resp.context['form'].get_slots()
569

  
570
    assert len(slots['users'][0]['users']) == 1
571
    assert slots['extra_data'] == ['foo']
572
    assert slots['users'][0]['users'][0]['extra_data']['foo'] == 'baz'
573

  
574
    resp.form['extra_data'] = ' foo ,baz,,'
575
    resp = resp.form.submit()
576
    slots = resp.context['form'].get_slots()
577

  
578
    assert len(slots['users'][0]['users']) == 1
579
    assert slots['extra_data'] == ['foo', 'baz']
580
    assert slots['users'][0]['users'][0]['extra_data']['foo'] == 'baz'
581
    assert slots['users'][0]['users'][0]['extra_data']['baz'] == ''
582

  
583
    Booking.objects.create(
584
        event=event,
585
        user_first_name='User',
586
        user_last_name='43',
587
        user_external_id='user:2',
588
        extra_data={'foo': 'bar', 'baz': 'aa'},
589
    )
590
    Booking.objects.create(
591
        event=event,
592
        user_first_name='User',
593
        user_last_name='44',
594
        user_external_id='user:3',
595
        extra_data={'foo': 'bar2', 'baz': 'aa'},
596
    )
597

  
598
    resp.form['extra_data'] = ''
599
    resp.form['group_by'] = 'foo'
600
    resp = resp.form.submit()
601
    slots = resp.context['form'].get_slots()
602
    assert resp.text.count('<div class="page_break">') == 0
603

  
604
    assert len(slots['users']) == 3
605
    assert slots['users'][0]['grouper'] == 'bar'
606
    assert len(slots['users'][0]['users']) == 1
607
    assert slots['users'][0]['users'][0]['user_id'] == 'user:2'
608
    assert slots['users'][1]['grouper'] == 'bar2'
609
    assert len(slots['users'][1]['users']) == 1
610
    assert slots['users'][1]['users'][0]['user_id'] == 'user:3'
611
    assert slots['users'][2]['grouper'] == 'baz'
612
    assert len(slots['users'][2]['users']) == 1
613
    assert slots['users'][2]['users'][0]['user_id'] == 'user:1'
614

  
615
    resp.form['with_page_break'] = True
616
    resp = resp.form.submit()
617
    assert resp.text.count('<div class="page_break">') == 2
618

  
619
    resp.form['group_by'] = 'baz'
620
    resp = resp.form.submit()
621
    slots = resp.context['form'].get_slots()
622

  
623
    assert len(slots['users']) == 2
624
    assert slots['users'][0]['grouper'] == 'aa'
625
    assert len(slots['users'][0]['users']) == 2
626
    assert slots['users'][0]['users'][0]['user_id'] == 'user:2'
627
    assert slots['users'][0]['users'][1]['user_id'] == 'user:3'
628
    assert slots['users'][1]['grouper'] == ''
629
    assert len(slots['users'][1]['users']) == 1
630
    assert slots['users'][1]['users'][0]['user_id'] == 'user:1'
631

  
632
    Subscription.objects.update(extra_data={'foo': 'baz', 'baz': 'blah'})
633
    resp = resp.form.submit()
634
    slots = resp.context['form'].get_slots()
635

  
636
    assert len(slots['users']) == 2
637
    assert slots['users'][0]['grouper'] == 'aa'
638
    assert len(slots['users'][0]['users']) == 2
639
    assert slots['users'][0]['users'][0]['user_id'] == 'user:2'
640
    assert slots['users'][0]['users'][1]['user_id'] == 'user:3'
641
    assert slots['users'][1]['grouper'] == 'blah'
642
    assert len(slots['users'][1]['users']) == 1
643
    assert slots['users'][1]['users'][0]['user_id'] == 'user:1'
644

  
645
    resp.form['group_by'] = 'unknown'
646
    resp = resp.form.submit()
647
    slots = resp.context['form'].get_slots()
648

  
649
    assert len(slots['users']) == 1
650
    assert slots['users'][0]['grouper'] == ''
651
    assert len(slots['users'][0]['users']) == 3
652

  
653

  
654
def test_events_timesheet_ordering(app, admin_user):
655
    agenda = Agenda.objects.create(label='Events', kind='events')
656
    event = Event.objects.create(
657
        start_datetime=make_aware(datetime.datetime(2022, 2, 15, 17, 0)), places=10, agenda=agenda
658
    )
659
    Booking.objects.create(
660
        event=event,
661
        user_first_name='BB',
662
        user_last_name='XX',
663
        user_external_id='user:1',
664
    )
665
    Booking.objects.create(
666
        event=event,
667
        user_first_name='AA',
668
        user_last_name='YY',
669
        user_external_id='user:2',
670
        cancellation_datetime=now(),
671
    )
672
    Subscription.objects.create(
673
        agenda=agenda,
674
        user_first_name='CC',
675
        user_last_name='WW',
676
        user_external_id='user:3',
677
        date_start=datetime.date(2022, 2, 1),
678
        date_end=datetime.date(2022, 3, 1),
679
    )
680

  
681
    login(app)
682
    resp = app.get('/manage/agendas/%s/events/timesheet' % agenda.pk)
683
    resp.form['date_start'] = '2022-02-01'
684
    resp.form['date_end'] = '2022-02-28'
685
    resp = resp.form.submit()
686
    slots = resp.context['form'].get_slots()
687
    assert slots['users'][0]['users'][0]['user_id'] == 'user:3'
688
    assert slots['users'][0]['users'][1]['user_id'] == 'user:1'
689
    assert slots['users'][0]['users'][2]['user_id'] == 'user:2'
690

  
691
    resp.form['sort'] = 'lastname,firstname'
692
    resp = resp.form.submit()
693
    slots = resp.context['form'].get_slots()
694
    assert slots['users'][0]['users'][0]['user_id'] == 'user:3'
695
    assert slots['users'][0]['users'][1]['user_id'] == 'user:1'
696
    assert slots['users'][0]['users'][2]['user_id'] == 'user:2'
697

  
698
    resp.form['sort'] = 'firstname,lastname'
699
    resp = resp.form.submit()
700
    slots = resp.context['form'].get_slots()
701
    assert slots['users'][0]['users'][0]['user_id'] == 'user:2'
702
    assert slots['users'][0]['users'][1]['user_id'] == 'user:1'
703
    assert slots['users'][0]['users'][2]['user_id'] == 'user:3'
704

  
705

  
706
@pytest.mark.freeze_time('2022-04-01')
707
def test_events_timesheet_date_display(app, admin_user):
708
    agenda = Agenda.objects.create(label='Events', kind='events')
709
    recurring_event = Event.objects.create(
710
        label='recurring 1',
711
        start_datetime=make_aware(datetime.datetime(2022, 1, 1, 12, 0)),
712
        places=10,
713
        agenda=agenda,
714
        recurrence_days=[0],
715
        recurrence_end_date=datetime.date(2022, 4, 1),
716
    )
717
    recurring_event.create_all_recurrences()
718
    Subscription.objects.create(
719
        agenda=agenda,
720
        user_external_id='user:1',
721
        user_first_name='Subscription',
722
        user_last_name='42',
723
        date_start=datetime.date(2022, 1, 1),
724
        date_end=datetime.date(2022, 4, 1),
725
        extra_data={'foo': 'bar'},
726
    )
727

  
728
    login(app)
729
    resp = app.get('/manage/agendas/%s/events/timesheet' % agenda.pk)
730
    resp.form['date_start'] = '2022-01-01'
731
    resp.form['date_end'] = '2022-03-31'
732
    resp = resp.form.submit()
733
    slots = resp.context['form'].get_slots()
734

  
735
    assert slots['dates'] == [
736
        [
737
            datetime.date(2022, 1, 3),
738
            datetime.date(2022, 1, 10),
739
            datetime.date(2022, 1, 17),
740
            datetime.date(2022, 1, 24),
741
            datetime.date(2022, 1, 31),
742
            datetime.date(2022, 2, 7),
743
            datetime.date(2022, 2, 14),
744
            datetime.date(2022, 2, 21),
745
            datetime.date(2022, 2, 28),
746
            datetime.date(2022, 3, 7),
747
            datetime.date(2022, 3, 14),
748
            datetime.date(2022, 3, 21),
749
            datetime.date(2022, 3, 28),
750
        ]
751
    ]
752

  
753
    resp.form['date_display'] = 'month'
754
    resp = resp.form.submit()
755
    slots = resp.context['form'].get_slots()
756

  
757
    assert slots['dates'] == [
758
        [
759
            datetime.date(2022, 1, 3),
760
            datetime.date(2022, 1, 10),
761
            datetime.date(2022, 1, 17),
762
            datetime.date(2022, 1, 24),
763
            datetime.date(2022, 1, 31),
764
        ],
765
        [
766
            datetime.date(2022, 2, 7),
767
            datetime.date(2022, 2, 14),
768
            datetime.date(2022, 2, 21),
769
            datetime.date(2022, 2, 28),
770
        ],
771
        [
772
            datetime.date(2022, 3, 7),
773
            datetime.date(2022, 3, 14),
774
            datetime.date(2022, 3, 21),
775
            datetime.date(2022, 3, 28),
776
        ],
777
    ]
778

  
779
    resp.form['date_display'] = 'week'
780
    resp = resp.form.submit()
781
    slots = resp.context['form'].get_slots()
782
    assert resp.text.count('<div class="page_break">') == 12
783

  
784
    assert slots['dates'] == [
785
        [datetime.date(2022, 1, 3)],
786
        [datetime.date(2022, 1, 10)],
787
        [datetime.date(2022, 1, 17)],
788
        [datetime.date(2022, 1, 24)],
789
        [datetime.date(2022, 1, 31)],
790
        [datetime.date(2022, 2, 7)],
791
        [datetime.date(2022, 2, 14)],
792
        [datetime.date(2022, 2, 21)],
793
        [datetime.date(2022, 2, 28)],
794
        [datetime.date(2022, 3, 7)],
795
        [datetime.date(2022, 3, 14)],
796
        [datetime.date(2022, 3, 21)],
797
        [datetime.date(2022, 3, 28)],
798
    ]
799

  
800
    resp.form['date_display'] = 'custom'
801
    resp = resp.form.submit()
802
    assert resp.context['form'].errors['custom_nb_dates_per_page'] == ['This field is required.']
803

  
804
    resp.form['custom_nb_dates_per_page'] = 10
805
    resp = resp.form.submit()
806
    slots = resp.context['form'].get_slots()
807

  
808
    assert slots['dates'] == [
809
        [
810
            datetime.date(2022, 1, 3),
811
            datetime.date(2022, 1, 10),
812
            datetime.date(2022, 1, 17),
813
            datetime.date(2022, 1, 24),
814
            datetime.date(2022, 1, 31),
815
            datetime.date(2022, 2, 7),
816
            datetime.date(2022, 2, 14),
817
            datetime.date(2022, 2, 21),
818
            datetime.date(2022, 2, 28),
819
            datetime.date(2022, 3, 7),
820
        ],
821
        [
822
            datetime.date(2022, 3, 14),
823
            datetime.date(2022, 3, 21),
824
            datetime.date(2022, 3, 28),
825
        ],
826
    ]
827

  
828
    resp.form['custom_nb_dates_per_page'] = 3
829
    resp = resp.form.submit()
830
    slots = resp.context['form'].get_slots()
831

  
832
    assert slots['dates'] == [
833
        [
834
            datetime.date(2022, 1, 3),
835
            datetime.date(2022, 1, 10),
836
            datetime.date(2022, 1, 17),
837
        ],
838
        [
839
            datetime.date(2022, 1, 24),
840
            datetime.date(2022, 1, 31),
841
            datetime.date(2022, 2, 7),
842
        ],
843
        [
844
            datetime.date(2022, 2, 14),
845
            datetime.date(2022, 2, 21),
846
            datetime.date(2022, 2, 28),
847
        ],
848
        [
849
            datetime.date(2022, 3, 7),
850
            datetime.date(2022, 3, 14),
851
            datetime.date(2022, 3, 21),
852
        ],
853
        [
854
            datetime.date(2022, 3, 28),
855
        ],
856
    ]
857

  
858
    Subscription.objects.create(
859
        agenda=agenda,
860
        user_external_id='user:2',
861
        user_first_name='Subscription',
862
        user_last_name='43',
863
        date_start=datetime.date(2022, 1, 1),
864
        date_end=datetime.date(2022, 4, 1),
865
        extra_data={'foo': 'baz'},
866
    )
867

  
868
    resp.form['date_display'] = 'week'
869
    resp.form['group_by'] = 'foo'
870
    resp = resp.form.submit()
871
    slots = resp.context['form'].get_slots()
872
    assert resp.text.count('<div class="page_break">') == 12
873

  
874
    resp.form['with_page_break'] = True
875
    resp = resp.form.submit()
876
    assert resp.text.count('<div class="page_break">') == 25
877

  
878

  
879
def test_events_timesheet_pdf(app, admin_user):
880
    agenda = Agenda.objects.create(label='Events', kind='events')
881

  
882
    login(app)
883
    resp = app.get(
884
        '/manage/agendas/%s/events/timesheet?pdf=&date_start=2022-02-01&date_end=2022-02-28&sort=lastname,firstname&date_display=all&orientation=portrait'
885
        % agenda.pk
886
    )
887
    assert resp.headers['Content-Type'] == 'application/pdf'
888
    assert (
889
        resp.headers['Content-Disposition']
890
        == 'attachment; filename="timesheet_events_2022-02-01_2022-02-28.pdf"'
891
    )
892

  
893
    # form invalid
894
    resp = app.get(
895
        '/manage/agendas/%s/events/timesheet?pdf=&date_start=2022-02-01&date_end=2022-02-28&sort=lastname,firstname&date_display=all'
896
        % agenda.pk
897
    )
898
    assert resp.context['form'].errors['orientation'] == ['This field is required.']
0
-