Projet

Général

Profil

0002-api-use-APIError-in-fillslots-view-43077.patch

Lauréline Guérin, 25 mai 2020 10:32

Télécharger (11,8 ko)

Voir les différences:

Subject: [PATCH 2/5] api: use APIError in fillslots view (#43077)

 chrono/api/views.py | 166 ++++++++++++++++++++++----------------------
 1 file changed, 83 insertions(+), 83 deletions(-)
chrono/api/views.py
39 39
from ..interval import IntervalSet
40 40

  
41 41

  
42
class APIError(Exception):
43
    err = 1
44
    http_status = 200
45

  
46
    def __init__(self, *args, **kwargs):
47
        self.__dict__.update(kwargs)
48
        super(APIError, self).__init__(*args)
49

  
50
    def to_response(self):
51
        data = {
52
            'err': self.err,
53
            'err_class': self.err_class,
54
            'err_desc': force_text(self),
55
        }
56
        if hasattr(self, 'errors'):
57
            data['errors'] = self.errors
58
        return Response(data, status=self.http_status)
59

  
60

  
42 61
def format_response_datetime(dt):
43 62
    return localtime(dt).strftime('%Y-%m-%d %H:%M:%S')
44 63

  
......
562 581
    serializer_class = SlotsSerializer
563 582

  
564 583
    def post(self, request, agenda_identifier=None, event_identifier=None, format=None):
565
        return self.fillslot(request=request, agenda_identifier=agenda_identifier, format=format)
584
        try:
585
            return self.fillslot(request=request, agenda_identifier=agenda_identifier, format=format)
586
        except APIError as e:
587
            return e.to_response()
566 588

  
567 589
    def fillslot(self, request, agenda_identifier=None, slots=[], format=None):
568 590
        multiple_booking = bool(not slots)
......
577 599

  
578 600
        serializer = self.serializer_class(data=request.data, partial=True)
579 601
        if not serializer.is_valid():
580
            return Response(
581
                {
582
                    'err': 1,
583
                    'err_class': 'invalid payload',
584
                    'err_desc': _('invalid payload'),
585
                    'errors': serializer.errors,
586
                },
587
                status=status.HTTP_400_BAD_REQUEST,
602
            raise APIError(
603
                _('invalid payload'),
604
                err_class='invalid payload',
605
                errors=serializer.errors,
606
                http_status=status.HTTP_400_BAD_REQUEST,
588 607
            )
589 608
        payload = serializer.validated_data
590 609

  
591 610
        if 'slots' in payload:
592 611
            slots = payload['slots']
593 612
        if not slots:
594
            return Response(
595
                {
596
                    'err': 1,
597
                    'err_class': 'slots list cannot be empty',
598
                    'err_desc': _('slots list cannot be empty'),
599
                },
600
                status=status.HTTP_400_BAD_REQUEST,
613
            raise APIError(
614
                _('slots list cannot be empty'),
615
                err_class='slots list cannot be empty',
616
                http_status=status.HTTP_400_BAD_REQUEST,
601 617
            )
602 618

  
603 619
        if 'count' in payload:
......
607 623
            try:
608 624
                places_count = int(request.query_params['count'])
609 625
            except ValueError:
610
                return Response(
611
                    {
612
                        'err': 1,
613
                        'err_class': 'invalid value for count (%s)' % request.query_params['count'],
614
                        'err_desc': _('invalid value for count (%s)') % request.query_params['count'],
615
                    },
616
                    status=status.HTTP_400_BAD_REQUEST,
626
                raise APIError(
627
                    _('invalid value for count (%s)') % request.query_params['count'],
628
                    err_class='invalid value for count (%s)' % request.query_params['count'],
629
                    http_status=status.HTTP_400_BAD_REQUEST,
617 630
                )
618 631
        else:
619 632
            places_count = 1
620 633

  
621 634
        if places_count <= 0:
622
            return Response(
623
                {
624
                    'err': 1,
625
                    'err_class': 'count cannot be less than or equal to zero',
626
                    'err_desc': _('count cannot be less than or equal to zero'),
627
                },
628
                status=status.HTTP_400_BAD_REQUEST,
635
            raise APIError(
636
                _('count cannot be less than or equal to zero'),
637
                err_class='count cannot be less than or equal to zero',
638
                http_status=status.HTTP_400_BAD_REQUEST,
629 639
            )
630 640

  
631 641
        to_cancel_booking = None
......
634 644
            try:
635 645
                cancel_booking_id = int(payload.get('cancel_booking_id'))
636 646
            except (ValueError, TypeError):
637
                return Response(
638
                    {
639
                        'err': 1,
640
                        'err_class': 'cancel_booking_id is not an integer',
641
                        'err_desc': _('cancel_booking_id is not an integer'),
642
                    },
643
                    status=status.HTTP_400_BAD_REQUEST,
647
                raise APIError(
648
                    _('cancel_booking_id is not an integer'),
649
                    err_class='cancel_booking_id is not an integer',
650
                    http_status=status.HTTP_400_BAD_REQUEST,
644 651
                )
645 652

  
646 653
        if cancel_booking_id is not None:
......
660 667
                cancel_error = gettext_noop('cancel booking: booking does no exist')
661 668

  
662 669
            if cancel_error:
663
                return Response({'err': 1, 'err_class': cancel_error, 'err_desc': _(cancel_error),})
670
                raise APIError(
671
                    _(cancel_error), err_class=cancel_error,
672
                )
664 673

  
665 674
        extra_data = {}
666 675
        for k, v in request.data.items():
......
678 687
                try:
679 688
                    meeting_type_id_, datetime_str = slot.split(':')
680 689
                except ValueError:
681
                    return Response(
682
                        {
683
                            'err': 1,
684
                            'err_class': 'invalid slot: %s' % slot,
685
                            'err_desc': _('invalid slot: %s') % slot,
686
                        },
687
                        status=status.HTTP_400_BAD_REQUEST,
690
                    raise APIError(
691
                        _('invalid slot: %s') % slot,
692
                        err_class='invalid slot: %s' % slot,
693
                        http_status=status.HTTP_400_BAD_REQUEST,
688 694
                    )
689 695
                if meeting_type_id_ != meeting_type_id:
690
                    return Response(
691
                        {
692
                            'err': 1,
693
                            'err_class': 'all slots must have the same meeting type id (%s)'
694
                            % meeting_type_id,
695
                            'err_desc': _('all slots must have the same meeting type id (%s)')
696
                            % meeting_type_id,
697
                        },
698
                        status=status.HTTP_400_BAD_REQUEST,
696
                    raise APIError(
697
                        _('all slots must have the same meeting type id (%s)') % meeting_type_id,
698
                        err_class='all slots must have the same meeting type id (%s)' % meeting_type_id,
699
                        http_status=status.HTTP_400_BAD_REQUEST,
699 700
                    )
700 701
                datetimes.add(make_aware(datetime.datetime.strptime(datetime_str, '%Y-%m-%d-%H%M')))
701 702

  
......
706 707
                    key=lambda slot: slot.start_datetime,
707 708
                )
708 709
            except (MeetingType.DoesNotExist, ValueError):
709
                return Response(
710
                    {
711
                        'err': 1,
712
                        'err_class': 'invalid meeting type id: %s' % meeting_type_id,
713
                        'err_desc': _('invalid meeting type id: %s') % meeting_type_id,
714
                    },
715
                    status=status.HTTP_400_BAD_REQUEST,
710
                raise APIError(
711
                    _('invalid meeting type id: %s') % meeting_type_id,
712
                    err_class='invalid meeting type id: %s' % meeting_type_id,
713
                    http_status=status.HTTP_400_BAD_REQUEST,
716 714
                )
717 715

  
718 716
            all_free_slots = [slot for slot in all_slots if not slot.full]
......
768 766
                        break
769 767

  
770 768
            if available_desk is None:
771
                return Response(
772
                    {
773
                        'err': 1,
774
                        'err_class': 'no more desk available',
775
                        'err_desc': _('no more desk available'),
776
                    }
769
                raise APIError(
770
                    _('no more desk available'), err_class='no more desk available',
777 771
                )
778 772

  
779 773
            # all datetimes are free, book them in order
......
807 801
                events = Event.objects.filter(slug__in=slots).order_by('start_datetime')
808 802

  
809 803
            if not events.count():
810
                return Response(
811
                    {
812
                        'err': 1,
813
                        'err_class': 'unknown event identifiers or slugs',
814
                        'err_desc': _('unknown event identifiers or slugs'),
815
                    },
816
                    status=status.HTTP_400_BAD_REQUEST,
804
                raise APIError(
805
                    _('unknown event identifiers or slugs'),
806
                    err_class='unknown event identifiers or slugs',
807
                    http_status=status.HTTP_400_BAD_REQUEST,
817 808
                )
818 809

  
819 810
        # search free places. Switch to waiting list if necessary.
820 811
        in_waiting_list = False
821 812
        for event in events:
822 813
            if payload.get('force_waiting_list') and not event.waiting_list_places:
823
                return Response({'err': 1, 'err_class': 'no waiting list', 'err_desc': _('no waiting list')})
814
                raise APIError(
815
                    _('no waiting list'), err_class='no waiting list',
816
                )
824 817

  
825 818
            if event.waiting_list_places:
826 819
                if (
......
832 825
                    # in the waiting list.
833 826
                    in_waiting_list = True
834 827
                    if (event.waiting_list + places_count) > event.waiting_list_places:
835
                        return Response({'err': 1, 'err_class': 'sold out', 'err_desc': _('sold out')})
828
                        raise APIError(
829
                            _('sold out'), err_class='sold out',
830
                        )
836 831
            else:
837 832
                if (event.booked_places + places_count) > event.places:
838
                    return Response({'err': 1, 'err_class': 'sold out', 'err_desc': _('sold out')})
833
                    raise APIError(
834
                        _('sold out'), err_class='sold out',
835
                    )
839 836

  
840 837
        with transaction.atomic():
841 838
            if to_cancel_booking:
......
921 918
    serializer_class = SlotSerializer
922 919

  
923 920
    def post(self, request, agenda_identifier=None, event_identifier=None, format=None):
924
        return self.fillslot(
925
            request=request,
926
            agenda_identifier=agenda_identifier,
927
            slots=[event_identifier],  # fill a "list on one slot"
928
            format=format,
929
        )
921
        try:
922
            return self.fillslot(
923
                request=request,
924
                agenda_identifier=agenda_identifier,
925
                slots=[event_identifier],  # fill a "list on one slot"
926
                format=format,
927
            )
928
        except APIError as e:
929
            return e.to_response()
930 930

  
931 931

  
932 932
fillslot = Fillslot.as_view()
933
-