Projet

Général

Profil

0001-agendas-add-subscription-model-58444.patch

Valentin Deniaud, 25 novembre 2021 17:51

Télécharger (7,81 ko)

Voir les différences:

Subject: [PATCH] agendas: add subscription model (#58444)

 .../agendas/migrations/0104_subscription.py   | 34 +++++++++++++++++++
 chrono/agendas/models.py                      |  7 ++++
 chrono/api/serializers.py                     | 14 +++++++-
 chrono/api/urls.py                            |  5 +++
 chrono/api/views.py                           | 19 +++++++++++
 tests/api/test_all.py                         | 33 ++++++++++++++++++
 6 files changed, 111 insertions(+), 1 deletion(-)
 create mode 100644 chrono/agendas/migrations/0104_subscription.py
chrono/agendas/migrations/0104_subscription.py
1
# Generated by Django 2.2.19 on 2021-11-25 13:21
2

  
3
import django.db.models.deletion
4
from django.db import migrations, models
5

  
6

  
7
class Migration(migrations.Migration):
8

  
9
    dependencies = [
10
        ('agendas', '0103_publication_datetime'),
11
    ]
12

  
13
    operations = [
14
        migrations.CreateModel(
15
            name='Subscription',
16
            fields=[
17
                (
18
                    'id',
19
                    models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
20
                ),
21
                ('user_external_id', models.CharField(max_length=250)),
22
                ('date_start', models.DateField()),
23
                ('date_end', models.DateField()),
24
                (
25
                    'agenda',
26
                    models.ForeignKey(
27
                        on_delete=django.db.models.deletion.CASCADE,
28
                        related_name='subscriptions',
29
                        to='agendas.Agenda',
30
                    ),
31
                ),
32
            ],
33
        ),
34
    ]
chrono/agendas/models.py
2900 2900
            'label': self.label,
2901 2901
            'slug': self.slug,
2902 2902
        }
2903

  
2904

  
2905
class Subscription(models.Model):
2906
    agenda = models.ForeignKey(Agenda, on_delete=models.CASCADE, related_name='subscriptions')
2907
    user_external_id = models.CharField(max_length=250)
2908
    date_start = models.DateField()
2909
    date_end = models.DateField()
chrono/api/serializers.py
5 5
from rest_framework import serializers
6 6
from rest_framework.exceptions import ValidationError
7 7

  
8
from chrono.agendas.models import AbsenceReason, Agenda, Booking, Category, Event
8
from chrono.agendas.models import AbsenceReason, Agenda, Booking, Category, Event, Subscription
9 9

  
10 10

  
11 11
class StringOrListField(serializers.ListField):
......
274 274
                }
275 275
            )
276 276
        return attrs
277

  
278

  
279
class SubscriptionSerializer(serializers.ModelSerializer):
280
    class Meta:
281
        model = Subscription
282
        fields = ['user_external_id', 'date_start', 'date_end']
283

  
284
    def validate(self, attrs):
285
        super().validate(attrs)
286
        if attrs['date_start'] > attrs['date_end']:
287
            raise ValidationError(_('start_datetime must be before end_datetime'))
288
        return attrs
chrono/api/urls.py
88 88
        views.meeting_datetimes,
89 89
        name='api-agenda-meeting-datetimes',
90 90
    ),
91
    url(
92
        r'^agenda/(?P<agenda_identifier>[\w-]+)/subscription/$',
93
        views.subscription,
94
        name='api-agenda-subscription',
95
    ),
91 96
    url(r'^bookings/$', views.bookings, name='api-bookings'),
92 97
    url(r'^booking/(?P<booking_pk>\d+)/$', views.booking, name='api-booking'),
93 98
    url(r'^booking/(?P<booking_pk>\d+)/cancel/$', views.cancel_booking, name='api-cancel-booking'),
chrono/api/views.py
49 49
    Desk,
50 50
    Event,
51 51
    MeetingType,
52
    Subscription,
52 53
    TimePeriodException,
53 54
)
54 55
from chrono.api import serializers
......
1722 1723
agendas_events_fillslots = MultipleAgendasEventsFillslots.as_view()
1723 1724

  
1724 1725

  
1726
class SubscriptionAPI(APIView):
1727
    serializer_class = serializers.SubscriptionSerializer
1728
    permission_classes = (permissions.IsAuthenticated,)
1729

  
1730
    def post(self, request, agenda_identifier):
1731
        agenda = get_object_or_404(Agenda, slug=agenda_identifier, kind='events')
1732

  
1733
        serializer = self.serializer_class(data=request.data)
1734
        if not serializer.is_valid():
1735
            raise APIErrorBadRequest(N_('invalid payload'), errors=serializer.errors)
1736

  
1737
        subscription = Subscription.objects.create(agenda=agenda, **serializer.validated_data)
1738
        return Response({'err': 0, 'id': subscription.pk})
1739

  
1740

  
1741
subscription = SubscriptionAPI.as_view()
1742

  
1743

  
1725 1744
class BookingFilter(filters.FilterSet):
1726 1745
    agenda = filters.CharFilter(field_name='event__agenda__slug', lookup_expr='exact')
1727 1746
    category = filters.CharFilter(field_name='event__agenda__category__slug', lookup_expr='exact')
tests/api/test_all.py
15 15
    Event,
16 16
    MeetingType,
17 17
    Resource,
18
    Subscription,
18 19
    TimePeriodException,
19 20
    VirtualMember,
20 21
)
......
729 730
    assert agenda.view_role == view_group
730 731
    assert agenda.min_booking_datetime.date() == datetime.date(2021, 7, 12)
731 732
    assert agenda.category == category_a
733

  
734

  
735
def test_api_create_subscription(app, user):
736
    agenda = Agenda.objects.create(label='Foo bar', kind='events')
737

  
738
    resp = app.post('/api/agenda/%s/subscription/' % agenda.slug, status=401)
739

  
740
    app.authorization = ('Basic', ('john.doe', 'password'))
741

  
742
    params = {'user_external_id': 'xxx', 'date_start': '2021-09-01', 'date_end': '2021-10-01'}
743
    resp = app.post('/api/agenda/%s/subscription/' % agenda.slug, params=params)
744
    subscription = Subscription.objects.get(pk=resp.json['id'])
745
    assert subscription.agenda == agenda
746
    assert subscription.user_external_id == 'xxx'
747
    assert subscription.date_start == datetime.date(year=2021, month=9, day=1)
748
    assert subscription.date_end == datetime.date(year=2021, month=10, day=1)
749

  
750
    # check errors
751
    resp = app.post('/api/agenda/%s/subscription/' % agenda.slug, params={}, status=400)
752
    assert resp.json['err_class'] == 'invalid payload'
753
    for field in ('user_external_id', 'date_start', 'date_end'):
754
        assert 'required' in resp.json['errors'][field][0]
755

  
756
    params = {'user_external_id': 'xxx', 'date_start': 'wrong-format', 'date_end': 'wrong-format'}
757
    resp = app.post('/api/agenda/%s/subscription/' % agenda.slug, params=params, status=400)
758
    assert resp.json['err_class'] == 'invalid payload'
759
    assert 'wrong format' in resp.json['errors']['date_start'][0]
760
    assert 'wrong format' in resp.json['errors']['date_end'][0]
761

  
762
    params = {'user_external_id': 'xxx', 'date_start': '2021-10-01', 'date_end': '2021-09-01'}
763
    resp = app.post('/api/agenda/%s/subscription/' % agenda.slug, params=params, status=400)
764
    assert resp.json['errors']['non_field_errors'][0] == 'start_datetime must be before end_datetime'
732
-